* configure.in (FLAGS_FOR_TARGET): Remove -nostdinc and -isystem
[binutils.git] / gas / config / tc-arm.c
blob83f997df9bd55310d12083621a66af8f99a6244a
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 *));
485 static void do_cmp PARAMS ((char *));
486 static void do_mov PARAMS ((char *));
487 static void do_ldst PARAMS ((char *));
488 static void do_ldstt PARAMS ((char *));
489 static void do_ldmstm PARAMS ((char *));
490 static void do_branch PARAMS ((char *));
491 static void do_swi PARAMS ((char *));
493 /* Pseudo Op codes. */
494 static void do_adr PARAMS ((char *));
495 static void do_adrl PARAMS ((char *));
496 static void do_empty PARAMS ((char *));
498 /* ARM v2. */
499 static void do_mul PARAMS ((char *));
500 static void do_mla PARAMS ((char *));
502 /* ARM v2S. */
503 static void do_swap PARAMS ((char *));
505 /* ARM v3. */
506 static void do_msr PARAMS ((char *));
507 static void do_mrs PARAMS ((char *));
509 /* ARM v3M. */
510 static void do_mull PARAMS ((char *));
512 /* ARM v4. */
513 static void do_ldstv4 PARAMS ((char *));
515 /* ARM v4T. */
516 static void do_bx PARAMS ((char *));
518 /* ARM v5. */
519 static void do_blx PARAMS ((char *));
520 static void do_bkpt PARAMS ((char *));
521 static void do_clz PARAMS ((char *));
522 static void do_lstc2 PARAMS ((char *));
523 static void do_cdp2 PARAMS ((char *));
524 static void do_co_reg2 PARAMS ((char *));
526 /* ARM v5ExP. */
527 static void do_smla PARAMS ((char *));
528 static void do_smlal PARAMS ((char *));
529 static void do_smul PARAMS ((char *));
530 static void do_qadd PARAMS ((char *));
532 /* ARM v5E. */
533 static void do_pld PARAMS ((char *));
534 static void do_ldrd PARAMS ((char *));
535 static void do_co_reg2c PARAMS ((char *));
537 /* Coprocessor Instructions. */
538 static void do_cdp PARAMS ((char *));
539 static void do_lstc PARAMS ((char *));
540 static void do_co_reg PARAMS ((char *));
542 /* FPA instructions. */
543 static void do_fpa_ctrl PARAMS ((char *));
544 static void do_fpa_ldst PARAMS ((char *));
545 static void do_fpa_ldmstm PARAMS ((char *));
546 static void do_fpa_dyadic PARAMS ((char *));
547 static void do_fpa_monadic PARAMS ((char *));
548 static void do_fpa_cmp PARAMS ((char *));
549 static void do_fpa_from_reg PARAMS ((char *));
550 static void do_fpa_to_reg PARAMS ((char *));
552 /* XScale. */
553 static void do_mia PARAMS ((char *));
554 static void do_mar PARAMS ((char *));
555 static void do_mra PARAMS ((char *));
557 /* Maverick. */
558 static void do_c_binops PARAMS ((char *, int));
559 static void do_c_binops_1 PARAMS ((char *));
560 static void do_c_binops_2 PARAMS ((char *));
561 static void do_c_binops_3 PARAMS ((char *));
562 static void do_c_triple PARAMS ((char *, int));
563 static void do_c_triple_4 PARAMS ((char *));
564 static void do_c_triple_5 PARAMS ((char *));
565 static void do_c_quad PARAMS ((char *, int));
566 static void do_c_quad_6 PARAMS ((char *));
567 static void do_c_dspsc PARAMS ((char *, int));
568 static void do_c_dspsc_1 PARAMS ((char *));
569 static void do_c_dspsc_2 PARAMS ((char *));
570 static void do_c_shift PARAMS ((char *, int));
571 static void do_c_shift_1 PARAMS ((char *));
572 static void do_c_shift_2 PARAMS ((char *));
573 static void do_c_ldst PARAMS ((char *, int));
574 static void do_c_ldst_1 PARAMS ((char *));
575 static void do_c_ldst_2 PARAMS ((char *));
576 static void do_c_ldst_3 PARAMS ((char *));
577 static void do_c_ldst_4 PARAMS ((char *));
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 build_arm_ops_hsh PARAMS ((void));
620 static void set_constant_flonums PARAMS ((void));
621 static valueT md_chars_to_number PARAMS ((char *, int));
622 static void insert_reg_alias PARAMS ((char *, int));
623 static void output_inst PARAMS ((void));
624 static int accum0_required_here PARAMS ((char **));
625 static int ld_mode_required_here PARAMS ((char **));
626 static void do_branch25 PARAMS ((char *));
627 static symbolS * find_real_start PARAMS ((symbolS *));
628 #ifdef OBJ_ELF
629 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
630 #endif
632 /* ARM instructions take 4bytes in the object file, Thumb instructions
633 take 2: */
634 #define INSN_SIZE 4
636 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
637 #define CIRRUS_MODE1 0x100c
639 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
640 #define CIRRUS_MODE2 0x0c10
642 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
643 #define CIRRUS_MODE3 0x1000
645 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
646 #define CIRRUS_MODE4 0x0c0010
648 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
649 #define CIRRUS_MODE5 0x00100c
651 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
652 #define CIRRUS_MODE6 0x00100c05
654 struct asm_opcode
656 /* Basic string to match. */
657 const char * template;
659 /* Basic instruction code. */
660 unsigned long value;
662 /* Offset into the template where the condition code (if any) will be.
663 If zero, then the instruction is never conditional. */
664 unsigned cond_offset;
666 /* Which architecture variant provides this instruction. */
667 unsigned long variant;
669 /* Function to call to parse args. */
670 void (* parms) PARAMS ((char *));
673 static const struct asm_opcode insns[] =
675 /* Core ARM Instructions. */
676 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
677 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
678 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
679 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
680 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
681 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
682 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
683 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
684 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
685 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
686 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
687 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
688 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
689 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
690 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
691 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
692 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
693 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
694 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
695 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
697 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
698 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
699 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
700 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
701 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
702 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
703 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
704 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
705 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
706 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
707 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
708 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
710 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
711 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
712 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
713 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
715 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
716 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
717 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
718 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
719 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
720 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
721 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
722 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
724 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
725 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
726 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
727 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
728 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
729 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
730 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
731 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
733 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
734 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
735 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
736 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
737 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
738 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
739 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
740 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
742 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
743 #ifdef TE_WINCE
744 /* XXX This is the wrong place to do this. Think multi-arch. */
745 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
746 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
747 #else
748 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
749 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
750 #endif
752 /* Pseudo ops. */
753 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
754 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
755 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
757 /* ARM 2 multiplies. */
758 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
759 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
760 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
761 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
763 /* Generic copressor instructions. */
764 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
765 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
766 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
767 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
768 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
769 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
770 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
772 /* ARM 3 - swp instructions. */
773 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
774 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
776 /* ARM 6 Status register instructions. */
777 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
778 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
779 /* ScottB: our code uses 0xe128f000 for msr.
780 NickC: but this is wrong because the bits 16 through 19 are
781 handled by the PSR_xxx defines above. */
783 /* ARM 7M long multiplies. */
784 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
785 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
786 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
787 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
788 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
789 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
790 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
791 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
793 /* ARM Architecture 4. */
794 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
795 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
796 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
797 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
799 /* ARM Architecture 4T. */
800 /* Note: bx (and blx) are required on V5, even if the processor does
801 not support Thumb. */
802 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
804 /* ARM Architecture 5. */
805 /* Note: blx has 2 variants, so the .value is set dynamically.
806 Only one of the variants has conditional execution. */
807 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
808 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
809 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
810 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
811 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
812 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
813 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
814 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
815 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
816 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
818 /* ARM Architecture 5ExP. */
819 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
820 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
821 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
822 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
824 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
825 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
827 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
828 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
829 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
830 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
832 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
833 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
834 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
835 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
837 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
838 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
840 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
841 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
842 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
843 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
845 /* ARM Architecture 5E. */
846 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
847 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
848 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
850 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
851 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
853 /* Core FPA instruction set (V1). */
854 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
855 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
856 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
857 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
859 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
860 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
861 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
862 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
864 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
865 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
866 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
867 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
869 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
870 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
871 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
872 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
873 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
874 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
875 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
876 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
877 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
878 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
879 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
880 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
882 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
883 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
884 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
885 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
886 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
887 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
888 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
889 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
890 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
891 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
892 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
893 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
895 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
896 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
897 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
898 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
899 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
900 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
901 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
902 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
903 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
904 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
905 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
906 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
908 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
909 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
910 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
911 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
912 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
913 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
914 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
915 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
916 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
917 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
918 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
919 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
921 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
922 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
923 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
924 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
925 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
926 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
927 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
928 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
929 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
930 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
931 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
932 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
934 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
935 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
936 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
937 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
938 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
939 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
940 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
941 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
942 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
943 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
944 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
945 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
947 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
948 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
949 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
950 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
951 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
952 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
953 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
954 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
955 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
956 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
957 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
958 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
960 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
961 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
962 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
963 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
964 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
965 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
966 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
967 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
968 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
969 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
970 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
971 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
973 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
974 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
975 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
976 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
977 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
978 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
979 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
980 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
981 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
982 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
983 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
984 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
986 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
987 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
988 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
989 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
990 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
991 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
992 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
993 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
994 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
995 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
996 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
997 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
999 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1000 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1001 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1002 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1003 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1004 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1005 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1006 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1007 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1008 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1009 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1010 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1012 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1013 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1014 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1015 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1016 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1017 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1018 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1019 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1020 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1021 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1022 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1023 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1025 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1026 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1027 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1028 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1029 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1030 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1031 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1032 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1033 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1034 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1035 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1036 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1038 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1039 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1040 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1041 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1042 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1043 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1044 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1045 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1046 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1047 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1048 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1049 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1051 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1052 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1053 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1054 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1055 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1056 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1057 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1058 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1059 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1060 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1061 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1062 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1064 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1065 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1066 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1067 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1068 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1069 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1070 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1071 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1072 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1073 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1074 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1075 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1077 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1078 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1079 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1080 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1081 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1082 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1083 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1084 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1085 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1086 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1087 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1088 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1090 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1091 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1092 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1093 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1094 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1095 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1096 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1097 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1098 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1099 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1100 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1101 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1103 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1104 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1105 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1106 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1107 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1108 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1109 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1110 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1111 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1112 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1113 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1114 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1116 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1117 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1118 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1119 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1120 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1121 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1122 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1123 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1124 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1125 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1126 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1127 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1129 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1130 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1131 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1132 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1133 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1134 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1135 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1136 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1137 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1138 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1139 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1140 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1142 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1143 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1144 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1145 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1146 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1147 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1148 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1149 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1150 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1151 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1152 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1153 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1155 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1156 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1157 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1158 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1159 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1160 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1161 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1162 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1163 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1164 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1165 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1166 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1168 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1169 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1170 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1171 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1172 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1173 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1174 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1175 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1176 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1177 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1178 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1179 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1181 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1182 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1183 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1184 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1185 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1186 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1187 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1188 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1189 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1190 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1191 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1192 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1194 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1195 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1196 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1197 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1198 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1199 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1200 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1201 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1202 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1203 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1204 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1205 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1207 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1208 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1209 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1210 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1211 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1212 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1213 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1214 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1215 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1216 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1217 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1218 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1220 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1221 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1222 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1223 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1224 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1225 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1226 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1227 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1228 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1229 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1230 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1231 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1233 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1234 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1235 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1236 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1237 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1238 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1239 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1240 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1241 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1242 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1243 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1244 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1246 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1247 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1248 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1249 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1250 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1251 not be an optional suffix, but part of the instruction. To be
1252 compatible, we accept either. */
1253 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1254 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1256 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1257 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1258 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1259 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1260 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1261 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1262 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1263 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1264 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1265 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1266 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1267 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1269 /* The implementation of the FIX instruction is broken on some
1270 assemblers, in that it accepts a precision specifier as well as a
1271 rounding specifier, despite the fact that this is meaningless.
1272 To be more compatible, we accept it as well, though of course it
1273 does not set any bits. */
1274 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1275 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1276 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1277 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1278 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1279 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1280 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1281 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1282 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1283 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1284 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1285 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1286 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1288 /* Instructions that were new with the real FPA, call them V2. */
1289 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1290 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1291 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1292 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1293 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1294 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1296 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1297 {"mia", 0xee200010, 3, ARM_EXT_XSCALE, do_mia},
1298 {"miaph", 0xee280010, 5, ARM_EXT_XSCALE, do_mia},
1299 {"miabb", 0xee2c0010, 5, ARM_EXT_XSCALE, do_mia},
1300 {"miabt", 0xee2d0010, 5, ARM_EXT_XSCALE, do_mia},
1301 {"miatb", 0xee2e0010, 5, ARM_EXT_XSCALE, do_mia},
1302 {"miatt", 0xee2f0010, 5, ARM_EXT_XSCALE, do_mia},
1303 {"mar", 0xec400000, 3, ARM_EXT_XSCALE, do_mar},
1304 {"mra", 0xec500000, 3, ARM_EXT_XSCALE, do_mra},
1306 /* Cirrus DSP instructions. */
1307 {"cfldrs", 0xec100400, 6, ARM_EXT_MAVERICK, do_c_ldst_1},
1308 {"cfldrd", 0xec500400, 6, ARM_EXT_MAVERICK, do_c_ldst_2},
1309 {"cfldr32", 0xec100500, 7, ARM_EXT_MAVERICK, do_c_ldst_3},
1310 {"cfldr64", 0xec500500, 7, ARM_EXT_MAVERICK, do_c_ldst_4},
1311 {"cfstrs", 0xec000400, 6, ARM_EXT_MAVERICK, do_c_ldst_1},
1312 {"cfstrd", 0xec400400, 6, ARM_EXT_MAVERICK, do_c_ldst_2},
1313 {"cfstr32", 0xec000500, 7, ARM_EXT_MAVERICK, do_c_ldst_3},
1314 {"cfstr64", 0xec400500, 7, ARM_EXT_MAVERICK, do_c_ldst_4},
1315 {"cfmvsr", 0xee000450, 6, ARM_EXT_MAVERICK, do_c_binops_2},
1316 {"cfmvrs", 0xee100450, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1317 {"cfmvdlr", 0xee000410, 7, ARM_EXT_MAVERICK, do_c_binops_2},
1318 {"cfmvrdl", 0xee100410, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1319 {"cfmvdhr", 0xee000430, 7, ARM_EXT_MAVERICK, do_c_binops_2},
1320 {"cfmvrdh", 0xee100430, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1321 {"cfmv64lr", 0xee000510, 8, ARM_EXT_MAVERICK, do_c_binops_2},
1322 {"cfmvr64l", 0xee100510, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1323 {"cfmv64hr", 0xee000530, 8, ARM_EXT_MAVERICK, do_c_binops_2},
1324 {"cfmvr64h", 0xee100530, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1325 {"cfmval32", 0xee100610, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1326 {"cfmv32al", 0xee000610, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1327 {"cfmvam32", 0xee100630, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1328 {"cfmv32am", 0xee000630, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1329 {"cfmvah32", 0xee100650, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1330 {"cfmv32ah", 0xee000650, 8, ARM_EXT_MAVERICK, do_c_binops_3},
1331 {"cfmv32a", 0xee000670, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1332 {"cfmva32", 0xee100670, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1333 {"cfmv64a", 0xee000690, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1334 {"cfmva64", 0xee100690, 7, ARM_EXT_MAVERICK, do_c_binops_3},
1335 {"cfmvsc32", 0xee1006b0, 8, ARM_EXT_MAVERICK, do_c_dspsc_1},
1336 {"cfmv32sc", 0xee0006b0, 8, ARM_EXT_MAVERICK, do_c_dspsc_2},
1337 {"cfcpys", 0xee000400, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1338 {"cfcpyd", 0xee000420, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1339 {"cfcvtsd", 0xee000460, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1340 {"cfcvtds", 0xee000440, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1341 {"cfcvt32s", 0xee000480, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1342 {"cfcvt32d", 0xee0004a0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1343 {"cfcvt64s", 0xee0004c0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1344 {"cfcvt64d", 0xee0004e0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1345 {"cfcvts32", 0xee100580, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1346 {"cfcvtd32", 0xee1005a0, 8, ARM_EXT_MAVERICK, do_c_binops_1},
1347 {"cftruncs32", 0xee1005c0, 10, ARM_EXT_MAVERICK, do_c_binops_1},
1348 {"cftruncd32", 0xee1005e0, 10, ARM_EXT_MAVERICK, do_c_binops_1},
1349 {"cfrshl32", 0xee000550, 8, ARM_EXT_MAVERICK, do_c_triple_4},
1350 {"cfrshl64", 0xee000570, 8, ARM_EXT_MAVERICK, do_c_triple_4},
1351 {"cfsh32", 0xee000500, 6, ARM_EXT_MAVERICK, do_c_shift_1},
1352 {"cfsh64", 0xee200500, 6, ARM_EXT_MAVERICK, do_c_shift_2},
1353 {"cfcmps", 0xee100490, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1354 {"cfcmpd", 0xee1004b0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1355 {"cfcmp32", 0xee100590, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1356 {"cfcmp64", 0xee1005b0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1357 {"cfabss", 0xee300400, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1358 {"cfabsd", 0xee300420, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1359 {"cfnegs", 0xee300440, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1360 {"cfnegd", 0xee300460, 6, ARM_EXT_MAVERICK, do_c_binops_1},
1361 {"cfadds", 0xee300480, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1362 {"cfaddd", 0xee3004a0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1363 {"cfsubs", 0xee3004c0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1364 {"cfsubd", 0xee3004e0, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1365 {"cfmuls", 0xee100400, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1366 {"cfmuld", 0xee100420, 6, ARM_EXT_MAVERICK, do_c_triple_5},
1367 {"cfabs32", 0xee300500, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1368 {"cfabs64", 0xee300520, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1369 {"cfneg32", 0xee300540, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1370 {"cfneg64", 0xee300560, 7, ARM_EXT_MAVERICK, do_c_binops_1},
1371 {"cfadd32", 0xee300580, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1372 {"cfadd64", 0xee3005a0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1373 {"cfsub32", 0xee3005c0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1374 {"cfsub64", 0xee3005e0, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1375 {"cfmul32", 0xee100500, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1376 {"cfmul64", 0xee100520, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1377 {"cfmac32", 0xee100540, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1378 {"cfmsc32", 0xee100560, 7, ARM_EXT_MAVERICK, do_c_triple_5},
1379 {"cfmadd32", 0xee000600, 8, ARM_EXT_MAVERICK, do_c_quad_6},
1380 {"cfmsub32", 0xee100600, 8, ARM_EXT_MAVERICK, do_c_quad_6},
1381 {"cfmadda32", 0xee200600, 9, ARM_EXT_MAVERICK, do_c_quad_6},
1382 {"cfmsuba32", 0xee300600, 9, ARM_EXT_MAVERICK, do_c_quad_6},
1385 /* Defines for various bits that we will want to toggle. */
1386 #define INST_IMMEDIATE 0x02000000
1387 #define OFFSET_REG 0x02000000
1388 #define HWOFFSET_IMM 0x00400000
1389 #define SHIFT_BY_REG 0x00000010
1390 #define PRE_INDEX 0x01000000
1391 #define INDEX_UP 0x00800000
1392 #define WRITE_BACK 0x00200000
1393 #define LDM_TYPE_2_OR_3 0x00400000
1395 #define LITERAL_MASK 0xf000f000
1396 #define OPCODE_MASK 0xfe1fffff
1397 #define V4_STR_BIT 0x00000020
1399 #define DATA_OP_SHIFT 21
1401 /* Codes to distinguish the arithmetic instructions. */
1402 #define OPCODE_AND 0
1403 #define OPCODE_EOR 1
1404 #define OPCODE_SUB 2
1405 #define OPCODE_RSB 3
1406 #define OPCODE_ADD 4
1407 #define OPCODE_ADC 5
1408 #define OPCODE_SBC 6
1409 #define OPCODE_RSC 7
1410 #define OPCODE_TST 8
1411 #define OPCODE_TEQ 9
1412 #define OPCODE_CMP 10
1413 #define OPCODE_CMN 11
1414 #define OPCODE_ORR 12
1415 #define OPCODE_MOV 13
1416 #define OPCODE_BIC 14
1417 #define OPCODE_MVN 15
1419 /* Thumb v1 (ARMv4T). */
1420 static void do_t_nop PARAMS ((char *));
1421 static void do_t_arit PARAMS ((char *));
1422 static void do_t_add PARAMS ((char *));
1423 static void do_t_asr PARAMS ((char *));
1424 static void do_t_branch9 PARAMS ((char *));
1425 static void do_t_branch12 PARAMS ((char *));
1426 static void do_t_branch23 PARAMS ((char *));
1427 static void do_t_bx PARAMS ((char *));
1428 static void do_t_compare PARAMS ((char *));
1429 static void do_t_ldmstm PARAMS ((char *));
1430 static void do_t_ldr PARAMS ((char *));
1431 static void do_t_ldrb PARAMS ((char *));
1432 static void do_t_ldrh PARAMS ((char *));
1433 static void do_t_lds PARAMS ((char *));
1434 static void do_t_lsl PARAMS ((char *));
1435 static void do_t_lsr PARAMS ((char *));
1436 static void do_t_mov PARAMS ((char *));
1437 static void do_t_push_pop PARAMS ((char *));
1438 static void do_t_str PARAMS ((char *));
1439 static void do_t_strb PARAMS ((char *));
1440 static void do_t_strh PARAMS ((char *));
1441 static void do_t_sub PARAMS ((char *));
1442 static void do_t_swi PARAMS ((char *));
1443 static void do_t_adr PARAMS ((char *));
1445 /* Thumb v2 (ARMv5T). */
1446 static void do_t_blx PARAMS ((char *));
1447 static void do_t_bkpt PARAMS ((char *));
1449 #define T_OPCODE_MUL 0x4340
1450 #define T_OPCODE_TST 0x4200
1451 #define T_OPCODE_CMN 0x42c0
1452 #define T_OPCODE_NEG 0x4240
1453 #define T_OPCODE_MVN 0x43c0
1455 #define T_OPCODE_ADD_R3 0x1800
1456 #define T_OPCODE_SUB_R3 0x1a00
1457 #define T_OPCODE_ADD_HI 0x4400
1458 #define T_OPCODE_ADD_ST 0xb000
1459 #define T_OPCODE_SUB_ST 0xb080
1460 #define T_OPCODE_ADD_SP 0xa800
1461 #define T_OPCODE_ADD_PC 0xa000
1462 #define T_OPCODE_ADD_I8 0x3000
1463 #define T_OPCODE_SUB_I8 0x3800
1464 #define T_OPCODE_ADD_I3 0x1c00
1465 #define T_OPCODE_SUB_I3 0x1e00
1467 #define T_OPCODE_ASR_R 0x4100
1468 #define T_OPCODE_LSL_R 0x4080
1469 #define T_OPCODE_LSR_R 0x40c0
1470 #define T_OPCODE_ASR_I 0x1000
1471 #define T_OPCODE_LSL_I 0x0000
1472 #define T_OPCODE_LSR_I 0x0800
1474 #define T_OPCODE_MOV_I8 0x2000
1475 #define T_OPCODE_CMP_I8 0x2800
1476 #define T_OPCODE_CMP_LR 0x4280
1477 #define T_OPCODE_MOV_HR 0x4600
1478 #define T_OPCODE_CMP_HR 0x4500
1480 #define T_OPCODE_LDR_PC 0x4800
1481 #define T_OPCODE_LDR_SP 0x9800
1482 #define T_OPCODE_STR_SP 0x9000
1483 #define T_OPCODE_LDR_IW 0x6800
1484 #define T_OPCODE_STR_IW 0x6000
1485 #define T_OPCODE_LDR_IH 0x8800
1486 #define T_OPCODE_STR_IH 0x8000
1487 #define T_OPCODE_LDR_IB 0x7800
1488 #define T_OPCODE_STR_IB 0x7000
1489 #define T_OPCODE_LDR_RW 0x5800
1490 #define T_OPCODE_STR_RW 0x5000
1491 #define T_OPCODE_LDR_RH 0x5a00
1492 #define T_OPCODE_STR_RH 0x5200
1493 #define T_OPCODE_LDR_RB 0x5c00
1494 #define T_OPCODE_STR_RB 0x5400
1496 #define T_OPCODE_PUSH 0xb400
1497 #define T_OPCODE_POP 0xbc00
1499 #define T_OPCODE_BRANCH 0xe7fe
1501 static int thumb_reg PARAMS ((char ** str, int hi_lo));
1503 #define THUMB_SIZE 2 /* Size of thumb instruction. */
1504 #define THUMB_REG_LO 0x1
1505 #define THUMB_REG_HI 0x2
1506 #define THUMB_REG_ANY 0x3
1508 #define THUMB_H1 0x0080
1509 #define THUMB_H2 0x0040
1511 #define THUMB_ASR 0
1512 #define THUMB_LSL 1
1513 #define THUMB_LSR 2
1515 #define THUMB_MOVE 0
1516 #define THUMB_COMPARE 1
1518 #define THUMB_LOAD 0
1519 #define THUMB_STORE 1
1521 #define THUMB_PP_PC_LR 0x0100
1523 /* These three are used for immediate shifts, do not alter. */
1524 #define THUMB_WORD 2
1525 #define THUMB_HALFWORD 1
1526 #define THUMB_BYTE 0
1528 struct thumb_opcode
1530 /* Basic string to match. */
1531 const char * template;
1533 /* Basic instruction code. */
1534 unsigned long value;
1536 int size;
1538 /* Which CPU variants this exists for. */
1539 unsigned long variant;
1541 /* Function to call to parse args. */
1542 void (* parms) PARAMS ((char *));
1545 static const struct thumb_opcode tinsns[] =
1547 /* Thumb v1 (ARMv4T). */
1548 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
1549 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
1550 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
1551 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
1552 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
1553 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
1554 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
1555 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
1556 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
1557 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1558 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1559 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
1560 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
1561 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
1562 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
1563 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
1564 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
1565 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
1566 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
1567 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
1568 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
1569 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
1570 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
1571 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
1572 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
1573 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
1574 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
1575 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
1576 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
1577 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
1578 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
1579 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
1580 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
1581 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
1582 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
1583 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
1584 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
1585 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
1586 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
1587 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
1588 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
1589 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
1590 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
1591 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
1592 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
1593 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
1594 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
1595 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
1596 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
1597 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
1598 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
1599 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
1600 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
1601 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
1602 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
1603 /* Pseudo ops: */
1604 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
1605 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
1606 /* Thumb v2 (ARMv5T). */
1607 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
1608 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
1611 struct reg_entry
1613 const char * name;
1614 int number;
1617 #define int_register(reg) ((reg) >= 0 && (reg) <= 15)
1618 #define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
1619 #define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
1621 #define ARM_EXT_MAVERICKSC_REG 134
1623 #define cirrus_register(reg) ((reg) >= 50 && (reg) <= 134)
1624 #define cirrus_mvf_register(reg) ((reg) >= 50 && (reg) <= 65)
1625 #define cirrus_mvd_register(reg) ((reg) >= 70 && (reg) <= 85)
1626 #define cirrus_mvfx_register(reg) ((reg) >= 90 && (reg) <= 105)
1627 #define cirrus_mvdx_register(reg) ((reg) >= 110 && (reg) <= 125)
1628 #define cirrus_mvax_register(reg) ((reg) >= 130 && (reg) <= 133)
1629 #define ARM_EXT_MAVERICKsc_register(reg) ((reg) == ARM_EXT_MAVERICKSC_REG)
1631 #define REG_SP 13
1632 #define REG_LR 14
1633 #define REG_PC 15
1635 /* These are the standard names. Users can add aliases with .req. */
1636 static const struct reg_entry reg_table[] =
1638 /* Processor Register Numbers. */
1639 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
1640 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
1641 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
1642 {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
1643 /* APCS conventions. */
1644 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
1645 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
1646 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
1647 {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
1648 /* ATPCS additions to APCS conventions. */
1649 {"wr", 7}, {"v8", 11},
1650 /* FP Registers. */
1651 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
1652 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
1653 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
1654 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
1655 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
1656 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
1657 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
1658 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
1659 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
1660 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
1661 /* ATPCS additions to float register names. */
1662 {"s0",16}, {"s1",17}, {"s2",18}, {"s3",19},
1663 {"s4",20}, {"s5",21}, {"s6",22}, {"s7",23},
1664 {"d0",16}, {"d1",17}, {"d2",18}, {"d3",19},
1665 {"d4",20}, {"d5",21}, {"d6",22}, {"d7",23},
1666 /* Cirrus DSP coprocessor registers. */
1667 {"mvf0", 50}, {"mvf1", 51}, {"mvf2", 52}, {"mvf3", 53},
1668 {"mvf4", 54}, {"mvf5", 55}, {"mvf6", 56}, {"mvf7", 57},
1669 {"mvf8", 58}, {"mvf9", 59}, {"mvf10", 60}, {"mvf11", 61},
1670 {"mvf12", 62},{"mvf13", 63}, {"mvf14", 64}, {"mvf15", 65},
1671 {"mvd0", 70}, {"mvd1", 71}, {"mvd2", 72}, {"mvd3", 73},
1672 {"mvd4", 74}, {"mvd5", 75}, {"mvd6", 76}, {"mvd7", 77},
1673 {"mvd8", 78}, {"mvd9", 79}, {"mvd10", 80}, {"mvd11", 81},
1674 {"mvd12", 82},{"mvd13", 83}, {"mvd14", 84}, {"mvd15", 85},
1675 {"mvfx0", 90},{"mvfx1", 91}, {"mvfx2", 92}, {"mvfx3", 93},
1676 {"mvfx4", 94},{"mvfx5", 95}, {"mvfx6", 96}, {"mvfx7", 97},
1677 {"mvfx8", 98},{"mvfx9", 99}, {"mvfx10", 100},{"mvfx11", 101},
1678 {"mvfx12", 102},{"mvfx13", 103},{"mvfx14", 104},{"mvfx15", 105},
1679 {"mvdx0", 110}, {"mvdx1", 111}, {"mvdx2", 112}, {"mvdx3", 113},
1680 {"mvdx4", 114}, {"mvdx5", 115}, {"mvdx6", 116}, {"mvdx7", 117},
1681 {"mvdx8", 118}, {"mvdx9", 119}, {"mvdx10", 120},{"mvdx11", 121},
1682 {"mvdx12", 122},{"mvdx13", 123},{"mvdx14", 124},{"mvdx15", 125},
1683 {"mvax0", 130}, {"mvax1", 131}, {"mvax2", 132}, {"mvax3", 133},
1684 {"dspsc", ARM_EXT_MAVERICKSC_REG},
1685 /* FIXME: At some point we need to add VFP register names. */
1686 /* Array terminator. */
1687 {NULL, 0}
1690 #define BAD_ARGS _("Bad arguments to instruction")
1691 #define BAD_PC _("r15 not allowed here")
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)
2720 char * str;
2722 /* Do nothing really. */
2723 end_of_line (str);
2724 return;
2727 static void
2728 do_mrs (str)
2729 char *str;
2731 int skip = 0;
2733 /* Only one syntax. */
2734 skip_whitespace (str);
2736 if (reg_required_here (&str, 12) == FAIL)
2738 inst.error = BAD_ARGS;
2739 return;
2742 if (skip_past_comma (&str) == FAIL)
2744 inst.error = _("comma expected after register name");
2745 return;
2748 skip_whitespace (str);
2750 if ( strcmp (str, "CPSR") == 0
2751 || strcmp (str, "SPSR") == 0
2752 /* Lower case versions for backwards compatability. */
2753 || strcmp (str, "cpsr") == 0
2754 || strcmp (str, "spsr") == 0)
2755 skip = 4;
2757 /* This is for backwards compatability with older toolchains. */
2758 else if ( strcmp (str, "cpsr_all") == 0
2759 || strcmp (str, "spsr_all") == 0)
2760 skip = 8;
2761 else
2763 inst.error = _("{C|S}PSR expected");
2764 return;
2767 if (* str == 's' || * str == 'S')
2768 inst.instruction |= SPSR_BIT;
2769 str += skip;
2771 end_of_line (str);
2774 /* Two possible forms:
2775 "{C|S}PSR_<field>, Rm",
2776 "{C|S}PSR_f, #expression". */
2778 static void
2779 do_msr (str)
2780 char * str;
2782 skip_whitespace (str);
2784 if (psr_required_here (& str) == FAIL)
2785 return;
2787 if (skip_past_comma (& str) == FAIL)
2789 inst.error = _("comma missing after psr flags");
2790 return;
2793 skip_whitespace (str);
2795 if (reg_required_here (& str, 0) != FAIL)
2797 inst.error = NULL;
2798 end_of_line (str);
2799 return;
2802 if (! is_immediate_prefix (* str))
2804 inst.error =
2805 _("only a register or immediate value can follow a psr flag");
2806 return;
2809 str ++;
2810 inst.error = NULL;
2812 if (my_get_expression (& inst.reloc.exp, & str))
2814 inst.error =
2815 _("only a register or immediate value can follow a psr flag");
2816 return;
2819 #if 0 /* The first edition of the ARM architecture manual stated that
2820 writing anything other than the flags with an immediate operation
2821 had UNPREDICTABLE effects. This constraint was removed in the
2822 second edition of the specification. */
2823 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2824 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2826 inst.error = _("immediate value cannot be used to set this field");
2827 return;
2829 #endif
2831 inst.instruction |= INST_IMMEDIATE;
2833 if (inst.reloc.exp.X_add_symbol)
2835 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2836 inst.reloc.pc_rel = 0;
2838 else
2840 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2842 if (value == (unsigned) FAIL)
2844 inst.error = _("Invalid constant");
2845 return;
2848 inst.instruction |= value;
2851 inst.error = NULL;
2852 end_of_line (str);
2855 /* Long Multiply Parser
2856 UMULL RdLo, RdHi, Rm, Rs
2857 SMULL RdLo, RdHi, Rm, Rs
2858 UMLAL RdLo, RdHi, Rm, Rs
2859 SMLAL RdLo, RdHi, Rm, Rs. */
2861 static void
2862 do_mull (str)
2863 char * str;
2865 int rdlo, rdhi, rm, rs;
2867 /* Only one format "rdlo, rdhi, rm, rs". */
2868 skip_whitespace (str);
2870 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2872 inst.error = BAD_ARGS;
2873 return;
2876 if (skip_past_comma (&str) == FAIL
2877 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2879 inst.error = BAD_ARGS;
2880 return;
2883 if (skip_past_comma (&str) == FAIL
2884 || (rm = reg_required_here (&str, 0)) == FAIL)
2886 inst.error = BAD_ARGS;
2887 return;
2890 /* rdhi, rdlo and rm must all be different. */
2891 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2892 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2894 if (skip_past_comma (&str) == FAIL
2895 || (rs = reg_required_here (&str, 8)) == FAIL)
2897 inst.error = BAD_ARGS;
2898 return;
2901 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2903 inst.error = BAD_PC;
2904 return;
2907 end_of_line (str);
2908 return;
2911 static void
2912 do_mul (str)
2913 char * str;
2915 int rd, rm;
2917 /* Only one format "rd, rm, rs". */
2918 skip_whitespace (str);
2920 if ((rd = reg_required_here (&str, 16)) == FAIL)
2922 inst.error = BAD_ARGS;
2923 return;
2926 if (rd == REG_PC)
2928 inst.error = BAD_PC;
2929 return;
2932 if (skip_past_comma (&str) == FAIL
2933 || (rm = reg_required_here (&str, 0)) == FAIL)
2935 inst.error = BAD_ARGS;
2936 return;
2939 if (rm == REG_PC)
2941 inst.error = BAD_PC;
2942 return;
2945 if (rm == rd)
2946 as_tsktsk (_("rd and rm should be different in mul"));
2948 if (skip_past_comma (&str) == FAIL
2949 || (rm = reg_required_here (&str, 8)) == FAIL)
2951 inst.error = BAD_ARGS;
2952 return;
2955 if (rm == REG_PC)
2957 inst.error = BAD_PC;
2958 return;
2961 end_of_line (str);
2962 return;
2965 static void
2966 do_mla (str)
2967 char * str;
2969 int rd, rm;
2971 /* Only one format "rd, rm, rs, rn". */
2972 skip_whitespace (str);
2974 if ((rd = reg_required_here (&str, 16)) == FAIL)
2976 inst.error = BAD_ARGS;
2977 return;
2980 if (rd == REG_PC)
2982 inst.error = BAD_PC;
2983 return;
2986 if (skip_past_comma (&str) == FAIL
2987 || (rm = reg_required_here (&str, 0)) == FAIL)
2989 inst.error = BAD_ARGS;
2990 return;
2993 if (rm == REG_PC)
2995 inst.error = BAD_PC;
2996 return;
2999 if (rm == rd)
3000 as_tsktsk (_("rd and rm should be different in mla"));
3002 if (skip_past_comma (&str) == FAIL
3003 || (rd = reg_required_here (&str, 8)) == FAIL
3004 || skip_past_comma (&str) == FAIL
3005 || (rm = reg_required_here (&str, 12)) == FAIL)
3007 inst.error = BAD_ARGS;
3008 return;
3011 if (rd == REG_PC || rm == REG_PC)
3013 inst.error = BAD_PC;
3014 return;
3017 end_of_line (str);
3018 return;
3021 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3022 Advances *str to the next non-alphanumeric.
3023 Returns 0, or else FAIL (in which case sets inst.error).
3025 (In a future XScale, there may be accumulators other than zero.
3026 At that time this routine and its callers can be upgraded to suit.) */
3028 static int
3029 accum0_required_here (str)
3030 char ** str;
3032 static char buff [128]; /* Note the address is taken. Hence, static. */
3033 char * p = * str;
3034 char c;
3035 int result = 0; /* The accum number. */
3037 skip_whitespace (p);
3039 *str = p; /* Advance caller's string pointer too. */
3040 c = *p++;
3041 while (ISALNUM (c))
3042 c = *p++;
3044 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3046 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3048 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3049 inst.error = buff;
3050 result = FAIL;
3053 *p = c; /* Unzap. */
3054 *str = p; /* Caller's string pointer to after match. */
3055 return result;
3058 /* Expects **str -> after a comma. May be leading blanks.
3059 Advances *str, recognizing a load mode, and setting inst.instruction.
3060 Returns rn, or else FAIL (in which case may set inst.error
3061 and not advance str)
3063 Note: doesn't know Rd, so no err checks that require such knowledge. */
3065 static int
3066 ld_mode_required_here (string)
3067 char ** string;
3069 char * str = * string;
3070 int rn;
3071 int pre_inc = 0;
3073 skip_whitespace (str);
3075 if (* str == '[')
3077 str++;
3079 skip_whitespace (str);
3081 if ((rn = reg_required_here (& str, 16)) == FAIL)
3082 return FAIL;
3084 skip_whitespace (str);
3086 if (* str == ']')
3088 str ++;
3090 if (skip_past_comma (& str) == SUCCESS)
3092 /* [Rn],... (post inc) */
3093 if (ldst_extend_v4 (&str) == FAIL)
3094 return FAIL;
3096 else /* [Rn] */
3098 skip_whitespace (str);
3100 if (* str == '!')
3102 str ++;
3103 inst.instruction |= WRITE_BACK;
3106 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3107 pre_inc = 1;
3110 else /* [Rn,...] */
3112 if (skip_past_comma (& str) == FAIL)
3114 inst.error = _("pre-indexed expression expected");
3115 return FAIL;
3118 pre_inc = 1;
3120 if (ldst_extend_v4 (&str) == FAIL)
3121 return FAIL;
3123 skip_whitespace (str);
3125 if (* str ++ != ']')
3127 inst.error = _("missing ]");
3128 return FAIL;
3131 skip_whitespace (str);
3133 if (* str == '!')
3135 str ++;
3136 inst.instruction |= WRITE_BACK;
3140 else if (* str == '=') /* ldr's "r,=label" syntax */
3141 /* We should never reach here, because <text> = <expression> is
3142 caught gas/read.c read_a_source_file() as a .set operation. */
3143 return FAIL;
3144 else /* PC +- 8 bit immediate offset. */
3146 if (my_get_expression (& inst.reloc.exp, & str))
3147 return FAIL;
3149 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3150 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3151 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3152 inst.reloc.pc_rel = 1;
3153 inst.instruction |= (REG_PC << 16);
3155 rn = REG_PC;
3156 pre_inc = 1;
3159 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3160 * string = str;
3162 return rn;
3165 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3166 SMLAxy{cond} Rd,Rm,Rs,Rn
3167 SMLAWy{cond} Rd,Rm,Rs,Rn
3168 Error if any register is R15. */
3170 static void
3171 do_smla (str)
3172 char * str;
3174 int rd, rm, rs, rn;
3176 skip_whitespace (str);
3178 if ((rd = reg_required_here (& str, 16)) == FAIL
3179 || skip_past_comma (& str) == FAIL
3180 || (rm = reg_required_here (& str, 0)) == FAIL
3181 || skip_past_comma (& str) == FAIL
3182 || (rs = reg_required_here (& str, 8)) == FAIL
3183 || skip_past_comma (& str) == FAIL
3184 || (rn = reg_required_here (& str, 12)) == FAIL)
3185 inst.error = BAD_ARGS;
3187 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3188 inst.error = BAD_PC;
3190 else
3191 end_of_line (str);
3194 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3195 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3196 Error if any register is R15.
3197 Warning if Rdlo == Rdhi. */
3199 static void
3200 do_smlal (str)
3201 char * str;
3203 int rdlo, rdhi, rm, rs;
3205 skip_whitespace (str);
3207 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3208 || skip_past_comma (& str) == FAIL
3209 || (rdhi = reg_required_here (& str, 16)) == FAIL
3210 || skip_past_comma (& str) == FAIL
3211 || (rm = reg_required_here (& str, 0)) == FAIL
3212 || skip_past_comma (& str) == FAIL
3213 || (rs = reg_required_here (& str, 8)) == FAIL)
3215 inst.error = BAD_ARGS;
3216 return;
3219 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3221 inst.error = BAD_PC;
3222 return;
3225 if (rdlo == rdhi)
3226 as_tsktsk (_("rdhi and rdlo must be different"));
3228 end_of_line (str);
3231 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3232 SMULxy{cond} Rd,Rm,Rs
3233 Error if any register is R15. */
3235 static void
3236 do_smul (str)
3237 char * str;
3239 int rd, rm, rs;
3241 skip_whitespace (str);
3243 if ((rd = reg_required_here (& str, 16)) == FAIL
3244 || skip_past_comma (& str) == FAIL
3245 || (rm = reg_required_here (& str, 0)) == FAIL
3246 || skip_past_comma (& str) == FAIL
3247 || (rs = reg_required_here (& str, 8)) == FAIL)
3248 inst.error = BAD_ARGS;
3250 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3251 inst.error = BAD_PC;
3253 else
3254 end_of_line (str);
3257 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3258 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3259 Error if any register is R15. */
3261 static void
3262 do_qadd (str)
3263 char * str;
3265 int rd, rm, rn;
3267 skip_whitespace (str);
3269 if ((rd = reg_required_here (& str, 12)) == FAIL
3270 || skip_past_comma (& str) == FAIL
3271 || (rm = reg_required_here (& str, 0)) == FAIL
3272 || skip_past_comma (& str) == FAIL
3273 || (rn = reg_required_here (& str, 16)) == FAIL)
3274 inst.error = BAD_ARGS;
3276 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3277 inst.error = BAD_PC;
3279 else
3280 end_of_line (str);
3283 /* ARM V5E (el Segundo)
3284 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3285 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3287 These are equivalent to the XScale instructions MAR and MRA,
3288 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3290 Result unpredicatable if Rd or Rn is R15. */
3292 static void
3293 do_co_reg2c (str)
3294 char * str;
3296 int rd, rn;
3298 skip_whitespace (str);
3300 if (co_proc_number (& str) == FAIL)
3302 if (!inst.error)
3303 inst.error = BAD_ARGS;
3304 return;
3307 if (skip_past_comma (& str) == FAIL
3308 || cp_opc_expr (& str, 4, 4) == FAIL)
3310 if (!inst.error)
3311 inst.error = BAD_ARGS;
3312 return;
3315 if (skip_past_comma (& str) == FAIL
3316 || (rd = reg_required_here (& str, 12)) == FAIL)
3318 if (!inst.error)
3319 inst.error = BAD_ARGS;
3320 return;
3323 if (skip_past_comma (& str) == FAIL
3324 || (rn = reg_required_here (& str, 16)) == FAIL)
3326 if (!inst.error)
3327 inst.error = BAD_ARGS;
3328 return;
3331 /* Unpredictable result if rd or rn is R15. */
3332 if (rd == REG_PC || rn == REG_PC)
3333 as_tsktsk
3334 (_("Warning: Instruction unpredictable when using r15"));
3336 if (skip_past_comma (& str) == FAIL
3337 || cp_reg_required_here (& str, 0) == FAIL)
3339 if (!inst.error)
3340 inst.error = BAD_ARGS;
3341 return;
3344 end_of_line (str);
3347 /* ARM V5 count-leading-zeroes instruction (argument parse)
3348 CLZ{<cond>} <Rd>, <Rm>
3349 Condition defaults to COND_ALWAYS.
3350 Error if Rd or Rm are R15. */
3352 static void
3353 do_clz (str)
3354 char * str;
3356 int rd, rm;
3358 skip_whitespace (str);
3360 if (((rd = reg_required_here (& str, 12)) == FAIL)
3361 || (skip_past_comma (& str) == FAIL)
3362 || ((rm = reg_required_here (& str, 0)) == FAIL))
3363 inst.error = BAD_ARGS;
3365 else if (rd == REG_PC || rm == REG_PC )
3366 inst.error = BAD_PC;
3368 else
3369 end_of_line (str);
3372 /* ARM V5 (argument parse)
3373 LDC2{L} <coproc>, <CRd>, <addressing mode>
3374 STC2{L} <coproc>, <CRd>, <addressing mode>
3375 Instruction is not conditional, and has 0xf in the codition field.
3376 Otherwise, it's the same as LDC/STC. */
3378 static void
3379 do_lstc2 (str)
3380 char * str;
3382 skip_whitespace (str);
3384 if (co_proc_number (& str) == FAIL)
3386 if (!inst.error)
3387 inst.error = BAD_ARGS;
3389 else if (skip_past_comma (& str) == FAIL
3390 || cp_reg_required_here (& str, 12) == FAIL)
3392 if (!inst.error)
3393 inst.error = BAD_ARGS;
3395 else if (skip_past_comma (& str) == FAIL
3396 || cp_address_required_here (& str) == FAIL)
3398 if (! inst.error)
3399 inst.error = BAD_ARGS;
3401 else
3402 end_of_line (str);
3405 /* ARM V5 (argument parse)
3406 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3407 Instruction is not conditional, and has 0xf in the condition field.
3408 Otherwise, it's the same as CDP. */
3410 static void
3411 do_cdp2 (str)
3412 char * str;
3414 skip_whitespace (str);
3416 if (co_proc_number (& str) == FAIL)
3418 if (!inst.error)
3419 inst.error = BAD_ARGS;
3420 return;
3423 if (skip_past_comma (& str) == FAIL
3424 || cp_opc_expr (& str, 20,4) == FAIL)
3426 if (!inst.error)
3427 inst.error = BAD_ARGS;
3428 return;
3431 if (skip_past_comma (& str) == FAIL
3432 || cp_reg_required_here (& str, 12) == FAIL)
3434 if (!inst.error)
3435 inst.error = BAD_ARGS;
3436 return;
3439 if (skip_past_comma (& str) == FAIL
3440 || cp_reg_required_here (& str, 16) == FAIL)
3442 if (!inst.error)
3443 inst.error = BAD_ARGS;
3444 return;
3447 if (skip_past_comma (& str) == FAIL
3448 || cp_reg_required_here (& str, 0) == FAIL)
3450 if (!inst.error)
3451 inst.error = BAD_ARGS;
3452 return;
3455 if (skip_past_comma (& str) == SUCCESS)
3457 if (cp_opc_expr (& str, 5, 3) == FAIL)
3459 if (!inst.error)
3460 inst.error = BAD_ARGS;
3461 return;
3465 end_of_line (str);
3468 /* ARM V5 (argument parse)
3469 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3470 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3471 Instruction is not conditional, and has 0xf in the condition field.
3472 Otherwise, it's the same as MCR/MRC. */
3474 static void
3475 do_co_reg2 (str)
3476 char * str;
3478 skip_whitespace (str);
3480 if (co_proc_number (& str) == FAIL)
3482 if (!inst.error)
3483 inst.error = BAD_ARGS;
3484 return;
3487 if (skip_past_comma (& str) == FAIL
3488 || cp_opc_expr (& str, 21, 3) == FAIL)
3490 if (!inst.error)
3491 inst.error = BAD_ARGS;
3492 return;
3495 if (skip_past_comma (& str) == FAIL
3496 || reg_required_here (& str, 12) == FAIL)
3498 if (!inst.error)
3499 inst.error = BAD_ARGS;
3500 return;
3503 if (skip_past_comma (& str) == FAIL
3504 || cp_reg_required_here (& str, 16) == FAIL)
3506 if (!inst.error)
3507 inst.error = BAD_ARGS;
3508 return;
3511 if (skip_past_comma (& str) == FAIL
3512 || cp_reg_required_here (& str, 0) == FAIL)
3514 if (!inst.error)
3515 inst.error = BAD_ARGS;
3516 return;
3519 if (skip_past_comma (& str) == SUCCESS)
3521 if (cp_opc_expr (& str, 5, 3) == FAIL)
3523 if (!inst.error)
3524 inst.error = BAD_ARGS;
3525 return;
3529 end_of_line (str);
3532 /* THUMB V5 breakpoint instruction (argument parse)
3533 BKPT <immed_8>. */
3535 static void
3536 do_t_bkpt (str)
3537 char * str;
3539 expressionS expr;
3540 unsigned long number;
3542 skip_whitespace (str);
3544 /* Allow optional leading '#'. */
3545 if (is_immediate_prefix (*str))
3546 str ++;
3548 memset (& expr, '\0', sizeof (expr));
3549 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3551 inst.error = _("bad or missing expression");
3552 return;
3555 number = expr.X_add_number;
3557 /* Check it fits an 8 bit unsigned. */
3558 if (number != (number & 0xff))
3560 inst.error = _("immediate value out of range");
3561 return;
3564 inst.instruction |= number;
3566 end_of_line (str);
3569 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3570 Expects inst.instruction is set for BLX(1).
3571 Note: this is cloned from do_branch, and the reloc changed to be a
3572 new one that can cope with setting one extra bit (the H bit). */
3574 static void
3575 do_branch25 (str)
3576 char * str;
3578 if (my_get_expression (& inst.reloc.exp, & str))
3579 return;
3581 #ifdef OBJ_ELF
3583 char * save_in;
3585 /* ScottB: February 5, 1998 */
3586 /* Check to see of PLT32 reloc required for the instruction. */
3588 /* arm_parse_reloc() works on input_line_pointer.
3589 We actually want to parse the operands to the branch instruction
3590 passed in 'str'. Save the input pointer and restore it later. */
3591 save_in = input_line_pointer;
3592 input_line_pointer = str;
3594 if (inst.reloc.exp.X_op == O_symbol
3595 && *str == '('
3596 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
3598 inst.reloc.type = BFD_RELOC_ARM_PLT32;
3599 inst.reloc.pc_rel = 0;
3600 /* Modify str to point to after parsed operands, otherwise
3601 end_of_line() will complain about the (PLT) left in str. */
3602 str = input_line_pointer;
3604 else
3606 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3607 inst.reloc.pc_rel = 1;
3610 input_line_pointer = save_in;
3612 #else
3613 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3614 inst.reloc.pc_rel = 1;
3615 #endif /* OBJ_ELF */
3617 end_of_line (str);
3620 /* ARM V5 branch-link-exchange instruction (argument parse)
3621 BLX <target_addr> ie BLX(1)
3622 BLX{<condition>} <Rm> ie BLX(2)
3623 Unfortunately, there are two different opcodes for this mnemonic.
3624 So, the insns[].value is not used, and the code here zaps values
3625 into inst.instruction.
3626 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
3628 static void
3629 do_blx (str)
3630 char * str;
3632 char * mystr = str;
3633 int rm;
3635 skip_whitespace (mystr);
3636 rm = reg_required_here (& mystr, 0);
3638 /* The above may set inst.error. Ignore his opinion. */
3639 inst.error = 0;
3641 if (rm != FAIL)
3643 /* Arg is a register.
3644 Use the condition code our caller put in inst.instruction.
3645 Pass ourselves off as a BX with a funny opcode. */
3646 inst.instruction |= 0x012fff30;
3647 do_bx (str);
3649 else
3651 /* This must be is BLX <target address>, no condition allowed. */
3652 if (inst.instruction != COND_ALWAYS)
3654 inst.error = BAD_COND;
3655 return;
3658 inst.instruction = 0xfafffffe;
3660 /* Process like a B/BL, but with a different reloc.
3661 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
3662 do_branch25 (str);
3666 /* ARM V5 Thumb BLX (argument parse)
3667 BLX <target_addr> which is BLX(1)
3668 BLX <Rm> which is BLX(2)
3669 Unfortunately, there are two different opcodes for this mnemonic.
3670 So, the tinsns[].value is not used, and the code here zaps values
3671 into inst.instruction. */
3673 static void
3674 do_t_blx (str)
3675 char * str;
3677 char * mystr = str;
3678 int rm;
3680 skip_whitespace (mystr);
3681 inst.instruction = 0x4780;
3683 /* Note that this call is to the ARM register recognizer. BLX(2)
3684 uses the ARM register space, not the Thumb one, so a call to
3685 thumb_reg() would be wrong. */
3686 rm = reg_required_here (& mystr, 3);
3687 inst.error = 0;
3689 if (rm != FAIL)
3691 /* It's BLX(2). The .instruction was zapped with rm & is final. */
3692 inst.size = 2;
3694 else
3696 /* No ARM register. This must be BLX(1). Change the .instruction. */
3697 inst.instruction = 0xf7ffeffe;
3698 inst.size = 4;
3700 if (my_get_expression (& inst.reloc.exp, & mystr))
3701 return;
3703 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
3704 inst.reloc.pc_rel = 1;
3707 end_of_line (mystr);
3710 /* ARM V5 breakpoint instruction (argument parse)
3711 BKPT <16 bit unsigned immediate>
3712 Instruction is not conditional.
3713 The bit pattern given in insns[] has the COND_ALWAYS condition,
3714 and it is an error if the caller tried to override that. */
3716 static void
3717 do_bkpt (str)
3718 char * str;
3720 expressionS expr;
3721 unsigned long number;
3723 skip_whitespace (str);
3725 /* Allow optional leading '#'. */
3726 if (is_immediate_prefix (* str))
3727 str++;
3729 memset (& expr, '\0', sizeof (expr));
3731 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3733 inst.error = _("bad or missing expression");
3734 return;
3737 number = expr.X_add_number;
3739 /* Check it fits a 16 bit unsigned. */
3740 if (number != (number & 0xffff))
3742 inst.error = _("immediate value out of range");
3743 return;
3746 /* Top 12 of 16 bits to bits 19:8. */
3747 inst.instruction |= (number & 0xfff0) << 4;
3749 /* Bottom 4 of 16 bits to bits 3:0. */
3750 inst.instruction |= number & 0xf;
3752 end_of_line (str);
3755 /* Xscale multiply-accumulate (argument parse)
3756 MIAcc acc0,Rm,Rs
3757 MIAPHcc acc0,Rm,Rs
3758 MIAxycc acc0,Rm,Rs. */
3760 static void
3761 do_mia (str)
3762 char * str;
3764 int rs;
3765 int rm;
3767 if (accum0_required_here (& str) == FAIL)
3768 inst.error = ERR_NO_ACCUM;
3770 else if (skip_past_comma (& str) == FAIL
3771 || (rm = reg_required_here (& str, 0)) == FAIL)
3772 inst.error = BAD_ARGS;
3774 else if (skip_past_comma (& str) == FAIL
3775 || (rs = reg_required_here (& str, 12)) == FAIL)
3776 inst.error = BAD_ARGS;
3778 /* inst.instruction has now been zapped with both rm and rs. */
3779 else if (rm == REG_PC || rs == REG_PC)
3780 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
3782 else
3783 end_of_line (str);
3786 /* Xscale move-accumulator-register (argument parse)
3788 MARcc acc0,RdLo,RdHi. */
3790 static void
3791 do_mar (str)
3792 char * str;
3794 int rdlo, rdhi;
3796 if (accum0_required_here (& str) == FAIL)
3797 inst.error = ERR_NO_ACCUM;
3799 else if (skip_past_comma (& str) == FAIL
3800 || (rdlo = reg_required_here (& str, 12)) == FAIL)
3801 inst.error = BAD_ARGS;
3803 else if (skip_past_comma (& str) == FAIL
3804 || (rdhi = reg_required_here (& str, 16)) == FAIL)
3805 inst.error = BAD_ARGS;
3807 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3808 else if (rdlo == REG_PC || rdhi == REG_PC)
3809 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
3811 else
3812 end_of_line (str);
3815 /* Xscale move-register-accumulator (argument parse)
3817 MRAcc RdLo,RdHi,acc0. */
3819 static void
3820 do_mra (str)
3821 char * str;
3823 int rdlo;
3824 int rdhi;
3826 skip_whitespace (str);
3828 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
3829 inst.error = BAD_ARGS;
3831 else if (skip_past_comma (& str) == FAIL
3832 || (rdhi = reg_required_here (& str, 16)) == FAIL)
3833 inst.error = BAD_ARGS;
3835 else if (skip_past_comma (& str) == FAIL
3836 || accum0_required_here (& str) == FAIL)
3837 inst.error = ERR_NO_ACCUM;
3839 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3840 else if (rdlo == rdhi)
3841 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
3843 else if (rdlo == REG_PC || rdhi == REG_PC)
3844 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
3845 else
3846 end_of_line (str);
3849 /* ARMv5TE: Preload-Cache
3851 PLD <addr_mode>
3853 Syntactically, like LDR with B=1, W=0, L=1. */
3855 static void
3856 do_pld (str)
3857 char * str;
3859 int rd;
3861 skip_whitespace (str);
3863 if (* str != '[')
3865 inst.error = _("'[' expected after PLD mnemonic");
3866 return;
3869 ++str;
3870 skip_whitespace (str);
3872 if ((rd = reg_required_here (& str, 16)) == FAIL)
3873 return;
3875 skip_whitespace (str);
3877 if (*str == ']')
3879 /* [Rn], ... ? */
3880 ++str;
3881 skip_whitespace (str);
3883 /* Post-indexed addressing is not allowed with PLD. */
3884 if (skip_past_comma (&str) == SUCCESS)
3886 inst.error
3887 = _("post-indexed expression used in preload instruction");
3888 return;
3890 else if (*str == '!') /* [Rn]! */
3892 inst.error = _("writeback used in preload instruction");
3893 ++str;
3895 else /* [Rn] */
3896 inst.instruction |= INDEX_UP | PRE_INDEX;
3898 else /* [Rn, ...] */
3900 if (skip_past_comma (& str) == FAIL)
3902 inst.error = _("pre-indexed expression expected");
3903 return;
3906 if (ldst_extend (&str) == FAIL)
3907 return;
3909 skip_whitespace (str);
3911 if (* str != ']')
3913 inst.error = _("missing ]");
3914 return;
3917 ++ str;
3918 skip_whitespace (str);
3920 if (* str == '!') /* [Rn]! */
3922 inst.error = _("writeback used in preload instruction");
3923 ++ str;
3926 inst.instruction |= PRE_INDEX;
3929 end_of_line (str);
3932 /* ARMv5TE load-consecutive (argument parse)
3933 Mode is like LDRH.
3935 LDRccD R, mode
3936 STRccD R, mode. */
3938 static void
3939 do_ldrd (str)
3940 char * str;
3942 int rd;
3943 int rn;
3945 skip_whitespace (str);
3947 if ((rd = reg_required_here (& str, 12)) == FAIL)
3949 inst.error = BAD_ARGS;
3950 return;
3953 if (skip_past_comma (& str) == FAIL
3954 || (rn = ld_mode_required_here (& str)) == FAIL)
3956 if (!inst.error)
3957 inst.error = BAD_ARGS;
3958 return;
3961 /* inst.instruction has now been zapped with Rd and the addressing mode. */
3962 if (rd & 1) /* Unpredictable result if Rd is odd. */
3964 inst.error = _("Destination register must be even");
3965 return;
3968 if (rd == REG_LR)
3970 inst.error = _("r14 not allowed here");
3971 return;
3974 if (((rd == rn) || (rd + 1 == rn))
3975 && ((inst.instruction & WRITE_BACK)
3976 || (!(inst.instruction & PRE_INDEX))))
3977 as_warn (_("pre/post-indexing used when modified address register is destination"));
3979 /* For an index-register load, the index register must not overlap the
3980 destination (even if not write-back). */
3981 if ((inst.instruction & V4_STR_BIT) == 0
3982 && (inst.instruction & HWOFFSET_IMM) == 0)
3984 int rm = inst.instruction & 0x0000000f;
3986 if (rm == rd || (rm == rd + 1))
3987 as_warn (_("ldrd destination registers must not overlap index register"));
3990 end_of_line (str);
3993 /* Returns the index into fp_values of a floating point number,
3994 or -1 if not in the table. */
3996 static int
3997 my_get_float_expression (str)
3998 char ** str;
4000 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4001 char * save_in;
4002 expressionS exp;
4003 int i;
4004 int j;
4006 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
4008 /* Look for a raw floating point number. */
4009 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
4010 && is_end_of_line[(unsigned char) *save_in])
4012 for (i = 0; i < NUM_FLOAT_VALS; i++)
4014 for (j = 0; j < MAX_LITTLENUMS; j++)
4016 if (words[j] != fp_values[i][j])
4017 break;
4020 if (j == MAX_LITTLENUMS)
4022 *str = save_in;
4023 return i;
4028 /* Try and parse a more complex expression, this will probably fail
4029 unless the code uses a floating point prefix (eg "0f"). */
4030 save_in = input_line_pointer;
4031 input_line_pointer = *str;
4032 if (expression (&exp) == absolute_section
4033 && exp.X_op == O_big
4034 && exp.X_add_number < 0)
4036 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4037 Ditto for 15. */
4038 if (gen_to_words (words, 5, (long) 15) == 0)
4040 for (i = 0; i < NUM_FLOAT_VALS; i++)
4042 for (j = 0; j < MAX_LITTLENUMS; j++)
4044 if (words[j] != fp_values[i][j])
4045 break;
4048 if (j == MAX_LITTLENUMS)
4050 *str = input_line_pointer;
4051 input_line_pointer = save_in;
4052 return i;
4058 *str = input_line_pointer;
4059 input_line_pointer = save_in;
4060 return -1;
4063 /* Return true if anything in the expression is a bignum. */
4065 static int
4066 walk_no_bignums (sp)
4067 symbolS * sp;
4069 if (symbol_get_value_expression (sp)->X_op == O_big)
4070 return 1;
4072 if (symbol_get_value_expression (sp)->X_add_symbol)
4074 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
4075 || (symbol_get_value_expression (sp)->X_op_symbol
4076 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
4079 return 0;
4082 static int
4083 my_get_expression (ep, str)
4084 expressionS * ep;
4085 char ** str;
4087 char * save_in;
4088 segT seg;
4090 save_in = input_line_pointer;
4091 input_line_pointer = *str;
4092 seg = expression (ep);
4094 #ifdef OBJ_AOUT
4095 if (seg != absolute_section
4096 && seg != text_section
4097 && seg != data_section
4098 && seg != bss_section
4099 && seg != undefined_section)
4101 inst.error = _("bad_segment");
4102 *str = input_line_pointer;
4103 input_line_pointer = save_in;
4104 return 1;
4106 #endif
4108 /* Get rid of any bignums now, so that we don't generate an error for which
4109 we can't establish a line number later on. Big numbers are never valid
4110 in instructions, which is where this routine is always called. */
4111 if (ep->X_op == O_big
4112 || (ep->X_add_symbol
4113 && (walk_no_bignums (ep->X_add_symbol)
4114 || (ep->X_op_symbol
4115 && walk_no_bignums (ep->X_op_symbol)))))
4117 inst.error = _("Invalid constant");
4118 *str = input_line_pointer;
4119 input_line_pointer = save_in;
4120 return 1;
4123 *str = input_line_pointer;
4124 input_line_pointer = save_in;
4125 return 0;
4128 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4129 instruction. */
4131 static int
4132 decode_shift (str, unrestrict)
4133 char ** str;
4134 int unrestrict;
4136 const struct asm_shift_name * shift;
4137 char * p;
4138 char c;
4140 skip_whitespace (* str);
4142 for (p = * str; ISALPHA (* p); p ++)
4145 if (p == * str)
4147 inst.error = _("Shift expression expected");
4148 return FAIL;
4151 c = * p;
4152 * p = '\0';
4153 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
4154 * p = c;
4156 if (shift == NULL)
4158 inst.error = _("Shift expression expected");
4159 return FAIL;
4162 assert (shift->properties->index == shift_properties[shift->properties->index].index);
4164 if (shift->properties->index == SHIFT_RRX)
4166 * str = p;
4167 inst.instruction |= shift->properties->bit_field;
4168 return SUCCESS;
4171 skip_whitespace (p);
4173 if (unrestrict && reg_required_here (& p, 8) != FAIL)
4175 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
4176 * str = p;
4177 return SUCCESS;
4179 else if (! is_immediate_prefix (* p))
4181 inst.error = (unrestrict
4182 ? _("shift requires register or #expression")
4183 : _("shift requires #expression"));
4184 * str = p;
4185 return FAIL;
4188 inst.error = NULL;
4189 p ++;
4191 if (my_get_expression (& inst.reloc.exp, & p))
4192 return FAIL;
4194 /* Validate some simple #expressions. */
4195 if (inst.reloc.exp.X_op == O_constant)
4197 unsigned num = inst.reloc.exp.X_add_number;
4199 /* Reject operations greater than 32. */
4200 if (num > 32
4201 /* Reject a shift of 0 unless the mode allows it. */
4202 || (num == 0 && shift->properties->allows_0 == 0)
4203 /* Reject a shift of 32 unless the mode allows it. */
4204 || (num == 32 && shift->properties->allows_32 == 0)
4207 /* As a special case we allow a shift of zero for
4208 modes that do not support it to be recoded as an
4209 logical shift left of zero (ie nothing). We warn
4210 about this though. */
4211 if (num == 0)
4213 as_warn (_("Shift of 0 ignored."));
4214 shift = & shift_names[0];
4215 assert (shift->properties->index == SHIFT_LSL);
4217 else
4219 inst.error = _("Invalid immediate shift");
4220 return FAIL;
4224 /* Shifts of 32 are encoded as 0, for those shifts that
4225 support it. */
4226 if (num == 32)
4227 num = 0;
4229 inst.instruction |= (num << 7) | shift->properties->bit_field;
4231 else
4233 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
4234 inst.reloc.pc_rel = 0;
4235 inst.instruction |= shift->properties->bit_field;
4238 * str = p;
4239 return SUCCESS;
4242 /* Do those data_ops which can take a negative immediate constant
4243 by altering the instuction. A bit of a hack really.
4244 MOV <-> MVN
4245 AND <-> BIC
4246 ADC <-> SBC
4247 by inverting the second operand, and
4248 ADD <-> SUB
4249 CMP <-> CMN
4250 by negating the second operand. */
4252 static int
4253 negate_data_op (instruction, value)
4254 unsigned long * instruction;
4255 unsigned long value;
4257 int op, new_inst;
4258 unsigned long negated, inverted;
4260 negated = validate_immediate (-value);
4261 inverted = validate_immediate (~value);
4263 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
4264 switch (op)
4266 /* First negates. */
4267 case OPCODE_SUB: /* ADD <-> SUB */
4268 new_inst = OPCODE_ADD;
4269 value = negated;
4270 break;
4272 case OPCODE_ADD:
4273 new_inst = OPCODE_SUB;
4274 value = negated;
4275 break;
4277 case OPCODE_CMP: /* CMP <-> CMN */
4278 new_inst = OPCODE_CMN;
4279 value = negated;
4280 break;
4282 case OPCODE_CMN:
4283 new_inst = OPCODE_CMP;
4284 value = negated;
4285 break;
4287 /* Now Inverted ops. */
4288 case OPCODE_MOV: /* MOV <-> MVN */
4289 new_inst = OPCODE_MVN;
4290 value = inverted;
4291 break;
4293 case OPCODE_MVN:
4294 new_inst = OPCODE_MOV;
4295 value = inverted;
4296 break;
4298 case OPCODE_AND: /* AND <-> BIC */
4299 new_inst = OPCODE_BIC;
4300 value = inverted;
4301 break;
4303 case OPCODE_BIC:
4304 new_inst = OPCODE_AND;
4305 value = inverted;
4306 break;
4308 case OPCODE_ADC: /* ADC <-> SBC */
4309 new_inst = OPCODE_SBC;
4310 value = inverted;
4311 break;
4313 case OPCODE_SBC:
4314 new_inst = OPCODE_ADC;
4315 value = inverted;
4316 break;
4318 /* We cannot do anything. */
4319 default:
4320 return FAIL;
4323 if (value == (unsigned) FAIL)
4324 return FAIL;
4326 *instruction &= OPCODE_MASK;
4327 *instruction |= new_inst << DATA_OP_SHIFT;
4328 return value;
4331 static int
4332 data_op2 (str)
4333 char ** str;
4335 int value;
4336 expressionS expr;
4338 skip_whitespace (* str);
4340 if (reg_required_here (str, 0) != FAIL)
4342 if (skip_past_comma (str) == SUCCESS)
4343 /* Shift operation on register. */
4344 return decode_shift (str, NO_SHIFT_RESTRICT);
4346 return SUCCESS;
4348 else
4350 /* Immediate expression. */
4351 if (is_immediate_prefix (**str))
4353 (*str)++;
4354 inst.error = NULL;
4356 if (my_get_expression (&inst.reloc.exp, str))
4357 return FAIL;
4359 if (inst.reloc.exp.X_add_symbol)
4361 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4362 inst.reloc.pc_rel = 0;
4364 else
4366 if (skip_past_comma (str) == SUCCESS)
4368 /* #x, y -- ie explicit rotation by Y. */
4369 if (my_get_expression (&expr, str))
4370 return FAIL;
4372 if (expr.X_op != O_constant)
4374 inst.error = _("Constant expression expected");
4375 return FAIL;
4378 /* Rotate must be a multiple of 2. */
4379 if (((unsigned) expr.X_add_number) > 30
4380 || (expr.X_add_number & 1) != 0
4381 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
4383 inst.error = _("Invalid constant");
4384 return FAIL;
4386 inst.instruction |= INST_IMMEDIATE;
4387 inst.instruction |= inst.reloc.exp.X_add_number;
4388 inst.instruction |= expr.X_add_number << 7;
4389 return SUCCESS;
4392 /* Implicit rotation, select a suitable one. */
4393 value = validate_immediate (inst.reloc.exp.X_add_number);
4395 if (value == FAIL)
4397 /* Can't be done. Perhaps the code reads something like
4398 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4399 if ((value = negate_data_op (&inst.instruction,
4400 inst.reloc.exp.X_add_number))
4401 == FAIL)
4403 inst.error = _("Invalid constant");
4404 return FAIL;
4408 inst.instruction |= value;
4411 inst.instruction |= INST_IMMEDIATE;
4412 return SUCCESS;
4415 (*str)++;
4416 inst.error = _("Register or shift expression expected");
4417 return FAIL;
4421 static int
4422 fp_op2 (str)
4423 char ** str;
4425 skip_whitespace (* str);
4427 if (fp_reg_required_here (str, 0) != FAIL)
4428 return SUCCESS;
4429 else
4431 /* Immediate expression. */
4432 if (*((*str)++) == '#')
4434 int i;
4436 inst.error = NULL;
4438 skip_whitespace (* str);
4440 /* First try and match exact strings, this is to guarantee
4441 that some formats will work even for cross assembly. */
4443 for (i = 0; fp_const[i]; i++)
4445 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
4447 char *start = *str;
4449 *str += strlen (fp_const[i]);
4450 if (is_end_of_line[(unsigned char) **str])
4452 inst.instruction |= i + 8;
4453 return SUCCESS;
4455 *str = start;
4459 /* Just because we didn't get a match doesn't mean that the
4460 constant isn't valid, just that it is in a format that we
4461 don't automatically recognize. Try parsing it with
4462 the standard expression routines. */
4463 if ((i = my_get_float_expression (str)) >= 0)
4465 inst.instruction |= i + 8;
4466 return SUCCESS;
4469 inst.error = _("Invalid floating point immediate expression");
4470 return FAIL;
4472 inst.error =
4473 _("Floating point register or immediate expression expected");
4474 return FAIL;
4478 static void
4479 do_arit (str)
4480 char * str;
4482 skip_whitespace (str);
4484 if (reg_required_here (&str, 12) == FAIL
4485 || skip_past_comma (&str) == FAIL
4486 || reg_required_here (&str, 16) == FAIL
4487 || skip_past_comma (&str) == FAIL
4488 || data_op2 (&str) == FAIL)
4490 if (!inst.error)
4491 inst.error = BAD_ARGS;
4492 return;
4495 end_of_line (str);
4496 return;
4499 static void
4500 do_adr (str)
4501 char * str;
4503 /* This is a pseudo-op of the form "adr rd, label" to be converted
4504 into a relative address of the form "add rd, pc, #label-.-8". */
4505 skip_whitespace (str);
4507 if (reg_required_here (&str, 12) == FAIL
4508 || skip_past_comma (&str) == FAIL
4509 || my_get_expression (&inst.reloc.exp, &str))
4511 if (!inst.error)
4512 inst.error = BAD_ARGS;
4513 return;
4516 /* Frag hacking will turn this into a sub instruction if the offset turns
4517 out to be negative. */
4518 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4519 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
4520 inst.reloc.pc_rel = 1;
4522 end_of_line (str);
4525 static void
4526 do_adrl (str)
4527 char * str;
4529 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4530 into a relative address of the form:
4531 add rd, pc, #low(label-.-8)"
4532 add rd, rd, #high(label-.-8)" */
4534 skip_whitespace (str);
4536 if (reg_required_here (&str, 12) == FAIL
4537 || skip_past_comma (&str) == FAIL
4538 || my_get_expression (&inst.reloc.exp, &str))
4540 if (!inst.error)
4541 inst.error = BAD_ARGS;
4543 return;
4546 end_of_line (str);
4547 /* Frag hacking will turn this into a sub instruction if the offset turns
4548 out to be negative. */
4549 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
4550 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
4551 inst.reloc.pc_rel = 1;
4552 inst.size = INSN_SIZE * 2;
4554 return;
4557 static void
4558 do_cmp (str)
4559 char * str;
4561 skip_whitespace (str);
4563 if (reg_required_here (&str, 16) == FAIL)
4565 if (!inst.error)
4566 inst.error = BAD_ARGS;
4567 return;
4570 if (skip_past_comma (&str) == FAIL
4571 || data_op2 (&str) == FAIL)
4573 if (!inst.error)
4574 inst.error = BAD_ARGS;
4575 return;
4578 end_of_line (str);
4579 return;
4582 static void
4583 do_mov (str)
4584 char * str;
4586 skip_whitespace (str);
4588 if (reg_required_here (&str, 12) == FAIL)
4590 if (!inst.error)
4591 inst.error = BAD_ARGS;
4592 return;
4595 if (skip_past_comma (&str) == FAIL
4596 || data_op2 (&str) == FAIL)
4598 if (!inst.error)
4599 inst.error = BAD_ARGS;
4600 return;
4603 end_of_line (str);
4604 return;
4607 static int
4608 ldst_extend (str)
4609 char ** str;
4611 int add = INDEX_UP;
4613 switch (**str)
4615 case '#':
4616 case '$':
4617 (*str)++;
4618 if (my_get_expression (& inst.reloc.exp, str))
4619 return FAIL;
4621 if (inst.reloc.exp.X_op == O_constant)
4623 int value = inst.reloc.exp.X_add_number;
4625 if (value < -4095 || value > 4095)
4627 inst.error = _("address offset too large");
4628 return FAIL;
4631 if (value < 0)
4633 value = -value;
4634 add = 0;
4637 inst.instruction |= add | value;
4639 else
4641 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4642 inst.reloc.pc_rel = 0;
4644 return SUCCESS;
4646 case '-':
4647 add = 0;
4648 /* Fall through. */
4650 case '+':
4651 (*str)++;
4652 /* Fall through. */
4654 default:
4655 if (reg_required_here (str, 0) == FAIL)
4656 return FAIL;
4658 inst.instruction |= add | OFFSET_REG;
4659 if (skip_past_comma (str) == SUCCESS)
4660 return decode_shift (str, SHIFT_RESTRICT);
4662 return SUCCESS;
4666 static void
4667 do_ldst (str)
4668 char * str;
4670 int pre_inc = 0;
4671 int conflict_reg;
4672 int value;
4674 skip_whitespace (str);
4676 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
4678 if (!inst.error)
4679 inst.error = BAD_ARGS;
4680 return;
4683 if (skip_past_comma (&str) == FAIL)
4685 inst.error = _("Address expected");
4686 return;
4689 if (*str == '[')
4691 int reg;
4693 str++;
4695 skip_whitespace (str);
4697 if ((reg = reg_required_here (&str, 16)) == FAIL)
4698 return;
4700 /* Conflicts can occur on stores as well as loads. */
4701 conflict_reg = (conflict_reg == reg);
4703 skip_whitespace (str);
4705 if (*str == ']')
4707 str ++;
4709 if (skip_past_comma (&str) == SUCCESS)
4711 /* [Rn],... (post inc) */
4712 if (ldst_extend (&str) == FAIL)
4713 return;
4714 if (conflict_reg)
4715 as_warn (_("%s register same as write-back base"),
4716 ((inst.instruction & LOAD_BIT)
4717 ? _("destination") : _("source")));
4719 else
4721 /* [Rn] */
4722 skip_whitespace (str);
4724 if (*str == '!')
4726 if (conflict_reg)
4727 as_warn (_("%s register same as write-back base"),
4728 ((inst.instruction & LOAD_BIT)
4729 ? _("destination") : _("source")));
4730 str++;
4731 inst.instruction |= WRITE_BACK;
4734 inst.instruction |= INDEX_UP;
4735 pre_inc = 1;
4738 else
4740 /* [Rn,...] */
4741 if (skip_past_comma (&str) == FAIL)
4743 inst.error = _("pre-indexed expression expected");
4744 return;
4747 pre_inc = 1;
4748 if (ldst_extend (&str) == FAIL)
4749 return;
4751 skip_whitespace (str);
4753 if (*str++ != ']')
4755 inst.error = _("missing ]");
4756 return;
4759 skip_whitespace (str);
4761 if (*str == '!')
4763 if (conflict_reg)
4764 as_warn (_("%s register same as write-back base"),
4765 ((inst.instruction & LOAD_BIT)
4766 ? _("destination") : _("source")));
4767 str++;
4768 inst.instruction |= WRITE_BACK;
4772 else if (*str == '=')
4774 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
4775 str++;
4777 skip_whitespace (str);
4779 if (my_get_expression (&inst.reloc.exp, &str))
4780 return;
4782 if (inst.reloc.exp.X_op != O_constant
4783 && inst.reloc.exp.X_op != O_symbol)
4785 inst.error = _("Constant expression expected");
4786 return;
4789 if (inst.reloc.exp.X_op == O_constant
4790 && (value = validate_immediate (inst.reloc.exp.X_add_number)) != FAIL)
4792 /* This can be done with a mov instruction. */
4793 inst.instruction &= LITERAL_MASK;
4794 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
4795 inst.instruction |= (value & 0xfff);
4796 end_of_line (str);
4797 return;
4799 else
4801 /* Insert into literal pool. */
4802 if (add_to_lit_pool () == FAIL)
4804 if (!inst.error)
4805 inst.error = _("literal pool insertion failed");
4806 return;
4809 /* Change the instruction exp to point to the pool. */
4810 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
4811 inst.reloc.pc_rel = 1;
4812 inst.instruction |= (REG_PC << 16);
4813 pre_inc = 1;
4816 else
4818 if (my_get_expression (&inst.reloc.exp, &str))
4819 return;
4821 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4822 #ifndef TE_WINCE
4823 /* PC rel adjust. */
4824 inst.reloc.exp.X_add_number -= 8;
4825 #endif
4826 inst.reloc.pc_rel = 1;
4827 inst.instruction |= (REG_PC << 16);
4828 pre_inc = 1;
4831 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4832 end_of_line (str);
4833 return;
4836 static void
4837 do_ldstt (str)
4838 char * str;
4840 int conflict_reg;
4842 skip_whitespace (str);
4844 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
4846 if (!inst.error)
4847 inst.error = BAD_ARGS;
4848 return;
4851 if (skip_past_comma (& str) == FAIL)
4853 inst.error = _("Address expected");
4854 return;
4857 if (*str == '[')
4859 int reg;
4861 str++;
4863 skip_whitespace (str);
4865 if ((reg = reg_required_here (&str, 16)) == FAIL)
4866 return;
4868 /* ldrt/strt always use post-indexed addressing, so if the base is
4869 the same as Rd, we warn. */
4870 if (conflict_reg == reg)
4871 as_warn (_("%s register same as write-back base"),
4872 ((inst.instruction & LOAD_BIT)
4873 ? _("destination") : _("source")));
4875 skip_whitespace (str);
4877 if (*str == ']')
4879 str ++;
4881 if (skip_past_comma (&str) == SUCCESS)
4883 /* [Rn],... (post inc) */
4884 if (ldst_extend (&str) == FAIL)
4885 return;
4887 else
4889 /* [Rn] */
4890 skip_whitespace (str);
4892 /* Skip a write-back '!'. */
4893 if (*str == '!')
4894 str++;
4896 inst.instruction |= INDEX_UP;
4899 else
4901 inst.error = _("post-indexed expression expected");
4902 return;
4905 else
4907 inst.error = _("post-indexed expression expected");
4908 return;
4911 end_of_line (str);
4912 return;
4915 static int
4916 ldst_extend_v4 (str)
4917 char ** str;
4919 int add = INDEX_UP;
4921 switch (**str)
4923 case '#':
4924 case '$':
4925 (*str)++;
4926 if (my_get_expression (& inst.reloc.exp, str))
4927 return FAIL;
4929 if (inst.reloc.exp.X_op == O_constant)
4931 int value = inst.reloc.exp.X_add_number;
4933 if (value < -255 || value > 255)
4935 inst.error = _("address offset too large");
4936 return FAIL;
4939 if (value < 0)
4941 value = -value;
4942 add = 0;
4945 /* Halfword and signextension instructions have the
4946 immediate value split across bits 11..8 and bits 3..0. */
4947 inst.instruction |= (add | HWOFFSET_IMM
4948 | ((value >> 4) << 8) | (value & 0xF));
4950 else
4952 inst.instruction |= HWOFFSET_IMM;
4953 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4954 inst.reloc.pc_rel = 0;
4956 return SUCCESS;
4958 case '-':
4959 add = 0;
4960 /* Fall through. */
4962 case '+':
4963 (*str)++;
4964 /* Fall through. */
4966 default:
4967 if (reg_required_here (str, 0) == FAIL)
4968 return FAIL;
4970 inst.instruction |= add;
4971 return SUCCESS;
4975 /* Halfword and signed-byte load/store operations. */
4976 static void
4977 do_ldstv4 (str)
4978 char * str;
4980 int pre_inc = 0;
4981 int conflict_reg;
4982 int value;
4984 skip_whitespace (str);
4986 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
4988 if (!inst.error)
4989 inst.error = BAD_ARGS;
4990 return;
4993 if (skip_past_comma (& str) == FAIL)
4995 inst.error = _("Address expected");
4996 return;
4999 if (*str == '[')
5001 int reg;
5003 str++;
5005 skip_whitespace (str);
5007 if ((reg = reg_required_here (&str, 16)) == FAIL)
5008 return;
5010 /* Conflicts can occur on stores as well as loads. */
5011 conflict_reg = (conflict_reg == reg);
5013 skip_whitespace (str);
5015 if (*str == ']')
5017 str ++;
5019 if (skip_past_comma (&str) == SUCCESS)
5021 /* [Rn],... (post inc) */
5022 if (ldst_extend_v4 (&str) == FAIL)
5023 return;
5024 if (conflict_reg)
5025 as_warn (_("%s register same as write-back base"),
5026 ((inst.instruction & LOAD_BIT)
5027 ? _("destination") : _("source")));
5029 else
5031 /* [Rn] */
5032 inst.instruction |= HWOFFSET_IMM;
5034 skip_whitespace (str);
5036 if (*str == '!')
5038 if (conflict_reg)
5039 as_warn (_("%s register same as write-back base"),
5040 ((inst.instruction & LOAD_BIT)
5041 ? _("destination") : _("source")));
5042 str++;
5043 inst.instruction |= WRITE_BACK;
5046 inst.instruction |= INDEX_UP;
5047 pre_inc = 1;
5050 else
5052 /* [Rn,...] */
5053 if (skip_past_comma (&str) == FAIL)
5055 inst.error = _("pre-indexed expression expected");
5056 return;
5059 pre_inc = 1;
5060 if (ldst_extend_v4 (&str) == FAIL)
5061 return;
5063 skip_whitespace (str);
5065 if (*str++ != ']')
5067 inst.error = _("missing ]");
5068 return;
5071 skip_whitespace (str);
5073 if (*str == '!')
5075 if (conflict_reg)
5076 as_warn (_("%s register same as write-back base"),
5077 ((inst.instruction & LOAD_BIT)
5078 ? _("destination") : _("source")));
5079 str++;
5080 inst.instruction |= WRITE_BACK;
5084 else if (*str == '=')
5086 /* XXX Does this work correctly for half-word/byte ops? */
5087 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5088 str++;
5090 skip_whitespace (str);
5092 if (my_get_expression (&inst.reloc.exp, &str))
5093 return;
5095 if (inst.reloc.exp.X_op != O_constant
5096 && inst.reloc.exp.X_op != O_symbol)
5098 inst.error = _("Constant expression expected");
5099 return;
5102 if (inst.reloc.exp.X_op == O_constant)
5104 value = validate_immediate (inst.reloc.exp.X_add_number);
5106 if (value != FAIL)
5108 /* This can be done with a mov instruction. */
5109 inst.instruction &= LITERAL_MASK;
5110 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
5111 inst.instruction |= value & 0xfff;
5112 end_of_line (str);
5113 return;
5116 value = validate_immediate (~ inst.reloc.exp.X_add_number);
5118 if (value != FAIL)
5120 /* This can be done with a mvn instruction. */
5121 inst.instruction &= LITERAL_MASK;
5122 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
5123 inst.instruction |= value & 0xfff;
5124 end_of_line (str);
5125 return;
5129 /* Insert into literal pool. */
5130 if (add_to_lit_pool () == FAIL)
5132 if (!inst.error)
5133 inst.error = _("literal pool insertion failed");
5134 return;
5137 /* Change the instruction exp to point to the pool. */
5138 inst.instruction |= HWOFFSET_IMM;
5139 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
5140 inst.reloc.pc_rel = 1;
5141 inst.instruction |= (REG_PC << 16);
5142 pre_inc = 1;
5144 else
5146 if (my_get_expression (&inst.reloc.exp, &str))
5147 return;
5149 inst.instruction |= HWOFFSET_IMM;
5150 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
5151 #ifndef TE_WINCE
5152 /* PC rel adjust. */
5153 inst.reloc.exp.X_add_number -= 8;
5154 #endif
5155 inst.reloc.pc_rel = 1;
5156 inst.instruction |= (REG_PC << 16);
5157 pre_inc = 1;
5160 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
5161 end_of_line (str);
5162 return;
5165 static long
5166 reg_list (strp)
5167 char ** strp;
5169 char * str = * strp;
5170 long range = 0;
5171 int another_range;
5173 /* We come back here if we get ranges concatenated by '+' or '|'. */
5176 another_range = 0;
5178 if (*str == '{')
5180 int in_range = 0;
5181 int cur_reg = -1;
5183 str++;
5186 int reg;
5188 skip_whitespace (str);
5190 if ((reg = reg_required_here (& str, -1)) == FAIL)
5191 return FAIL;
5193 if (in_range)
5195 int i;
5197 if (reg <= cur_reg)
5199 inst.error = _("Bad range in register list");
5200 return FAIL;
5203 for (i = cur_reg + 1; i < reg; i++)
5205 if (range & (1 << i))
5206 as_tsktsk
5207 (_("Warning: Duplicated register (r%d) in register list"),
5209 else
5210 range |= 1 << i;
5212 in_range = 0;
5215 if (range & (1 << reg))
5216 as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
5217 reg);
5218 else if (reg <= cur_reg)
5219 as_tsktsk (_("Warning: Register range not in ascending order"));
5221 range |= 1 << reg;
5222 cur_reg = reg;
5224 while (skip_past_comma (&str) != FAIL
5225 || (in_range = 1, *str++ == '-'));
5226 str--;
5227 skip_whitespace (str);
5229 if (*str++ != '}')
5231 inst.error = _("Missing `}'");
5232 return FAIL;
5235 else
5237 expressionS expr;
5239 if (my_get_expression (&expr, &str))
5240 return FAIL;
5242 if (expr.X_op == O_constant)
5244 if (expr.X_add_number
5245 != (expr.X_add_number & 0x0000ffff))
5247 inst.error = _("invalid register mask");
5248 return FAIL;
5251 if ((range & expr.X_add_number) != 0)
5253 int regno = range & expr.X_add_number;
5255 regno &= -regno;
5256 regno = (1 << regno) - 1;
5257 as_tsktsk
5258 (_("Warning: Duplicated register (r%d) in register list"),
5259 regno);
5262 range |= expr.X_add_number;
5264 else
5266 if (inst.reloc.type != 0)
5268 inst.error = _("expression too complex");
5269 return FAIL;
5272 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
5273 inst.reloc.type = BFD_RELOC_ARM_MULTI;
5274 inst.reloc.pc_rel = 0;
5278 skip_whitespace (str);
5280 if (*str == '|' || *str == '+')
5282 str++;
5283 another_range = 1;
5286 while (another_range);
5288 *strp = str;
5289 return range;
5292 static void
5293 do_ldmstm (str)
5294 char * str;
5296 int base_reg;
5297 long range;
5299 skip_whitespace (str);
5301 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
5302 return;
5304 if (base_reg == REG_PC)
5306 inst.error = _("r15 not allowed as base register");
5307 return;
5310 skip_whitespace (str);
5312 if (*str == '!')
5314 inst.instruction |= WRITE_BACK;
5315 str++;
5318 if (skip_past_comma (&str) == FAIL
5319 || (range = reg_list (&str)) == FAIL)
5321 if (! inst.error)
5322 inst.error = BAD_ARGS;
5323 return;
5326 if (*str == '^')
5328 str++;
5329 inst.instruction |= LDM_TYPE_2_OR_3;
5332 inst.instruction |= range;
5333 end_of_line (str);
5334 return;
5337 static void
5338 do_swi (str)
5339 char * str;
5341 skip_whitespace (str);
5343 /* Allow optional leading '#'. */
5344 if (is_immediate_prefix (*str))
5345 str++;
5347 if (my_get_expression (& inst.reloc.exp, & str))
5348 return;
5350 inst.reloc.type = BFD_RELOC_ARM_SWI;
5351 inst.reloc.pc_rel = 0;
5352 end_of_line (str);
5354 return;
5357 static void
5358 do_swap (str)
5359 char * str;
5361 int reg;
5363 skip_whitespace (str);
5365 if ((reg = reg_required_here (&str, 12)) == FAIL)
5366 return;
5368 if (reg == REG_PC)
5370 inst.error = _("r15 not allowed in swap");
5371 return;
5374 if (skip_past_comma (&str) == FAIL
5375 || (reg = reg_required_here (&str, 0)) == FAIL)
5377 if (!inst.error)
5378 inst.error = BAD_ARGS;
5379 return;
5382 if (reg == REG_PC)
5384 inst.error = _("r15 not allowed in swap");
5385 return;
5388 if (skip_past_comma (&str) == FAIL
5389 || *str++ != '[')
5391 inst.error = BAD_ARGS;
5392 return;
5395 skip_whitespace (str);
5397 if ((reg = reg_required_here (&str, 16)) == FAIL)
5398 return;
5400 if (reg == REG_PC)
5402 inst.error = BAD_PC;
5403 return;
5406 skip_whitespace (str);
5408 if (*str++ != ']')
5410 inst.error = _("missing ]");
5411 return;
5414 end_of_line (str);
5415 return;
5418 static void
5419 do_branch (str)
5420 char * str;
5422 if (my_get_expression (&inst.reloc.exp, &str))
5423 return;
5425 #ifdef OBJ_ELF
5427 char * save_in;
5429 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5430 required for the instruction. */
5432 /* arm_parse_reloc () works on input_line_pointer.
5433 We actually want to parse the operands to the branch instruction
5434 passed in 'str'. Save the input pointer and restore it later. */
5435 save_in = input_line_pointer;
5436 input_line_pointer = str;
5437 if (inst.reloc.exp.X_op == O_symbol
5438 && *str == '('
5439 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5441 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5442 inst.reloc.pc_rel = 0;
5443 /* Modify str to point to after parsed operands, otherwise
5444 end_of_line() will complain about the (PLT) left in str. */
5445 str = input_line_pointer;
5447 else
5449 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5450 inst.reloc.pc_rel = 1;
5452 input_line_pointer = save_in;
5454 #else
5455 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5456 inst.reloc.pc_rel = 1;
5457 #endif /* OBJ_ELF */
5459 end_of_line (str);
5460 return;
5463 static void
5464 do_bx (str)
5465 char * str;
5467 int reg;
5469 skip_whitespace (str);
5471 if ((reg = reg_required_here (&str, 0)) == FAIL)
5473 inst.error = BAD_ARGS;
5474 return;
5477 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5478 if (reg == REG_PC)
5479 as_tsktsk (_("Use of r15 in bx in ARM mode is not really useful"));
5481 end_of_line (str);
5484 static void
5485 do_cdp (str)
5486 char * str;
5488 /* Co-processor data operation.
5489 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5490 skip_whitespace (str);
5492 if (co_proc_number (&str) == FAIL)
5494 if (!inst.error)
5495 inst.error = BAD_ARGS;
5496 return;
5499 if (skip_past_comma (&str) == FAIL
5500 || cp_opc_expr (&str, 20,4) == FAIL)
5502 if (!inst.error)
5503 inst.error = BAD_ARGS;
5504 return;
5507 if (skip_past_comma (&str) == FAIL
5508 || cp_reg_required_here (&str, 12) == FAIL)
5510 if (!inst.error)
5511 inst.error = BAD_ARGS;
5512 return;
5515 if (skip_past_comma (&str) == FAIL
5516 || cp_reg_required_here (&str, 16) == FAIL)
5518 if (!inst.error)
5519 inst.error = BAD_ARGS;
5520 return;
5523 if (skip_past_comma (&str) == FAIL
5524 || cp_reg_required_here (&str, 0) == FAIL)
5526 if (!inst.error)
5527 inst.error = BAD_ARGS;
5528 return;
5531 if (skip_past_comma (&str) == SUCCESS)
5533 if (cp_opc_expr (&str, 5, 3) == FAIL)
5535 if (!inst.error)
5536 inst.error = BAD_ARGS;
5537 return;
5541 end_of_line (str);
5542 return;
5545 static void
5546 do_lstc (str)
5547 char * str;
5549 /* Co-processor register load/store.
5550 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5552 skip_whitespace (str);
5554 if (co_proc_number (&str) == FAIL)
5556 if (!inst.error)
5557 inst.error = BAD_ARGS;
5558 return;
5561 if (skip_past_comma (&str) == FAIL
5562 || cp_reg_required_here (&str, 12) == FAIL)
5564 if (!inst.error)
5565 inst.error = BAD_ARGS;
5566 return;
5569 if (skip_past_comma (&str) == FAIL
5570 || cp_address_required_here (&str) == FAIL)
5572 if (! inst.error)
5573 inst.error = BAD_ARGS;
5574 return;
5577 end_of_line (str);
5578 return;
5581 static void
5582 do_co_reg (str)
5583 char * str;
5585 /* Co-processor register transfer.
5586 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
5588 skip_whitespace (str);
5590 if (co_proc_number (&str) == FAIL)
5592 if (!inst.error)
5593 inst.error = BAD_ARGS;
5594 return;
5597 if (skip_past_comma (&str) == FAIL
5598 || cp_opc_expr (&str, 21, 3) == FAIL)
5600 if (!inst.error)
5601 inst.error = BAD_ARGS;
5602 return;
5605 if (skip_past_comma (&str) == FAIL
5606 || reg_required_here (&str, 12) == FAIL)
5608 if (!inst.error)
5609 inst.error = BAD_ARGS;
5610 return;
5613 if (skip_past_comma (&str) == FAIL
5614 || cp_reg_required_here (&str, 16) == FAIL)
5616 if (!inst.error)
5617 inst.error = BAD_ARGS;
5618 return;
5621 if (skip_past_comma (&str) == FAIL
5622 || cp_reg_required_here (&str, 0) == FAIL)
5624 if (!inst.error)
5625 inst.error = BAD_ARGS;
5626 return;
5629 if (skip_past_comma (&str) == SUCCESS)
5631 if (cp_opc_expr (&str, 5, 3) == FAIL)
5633 if (!inst.error)
5634 inst.error = BAD_ARGS;
5635 return;
5639 end_of_line (str);
5640 return;
5643 static void
5644 do_fpa_ctrl (str)
5645 char * str;
5647 /* FP control registers.
5648 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
5650 skip_whitespace (str);
5652 if (reg_required_here (&str, 12) == FAIL)
5654 if (!inst.error)
5655 inst.error = BAD_ARGS;
5656 return;
5659 end_of_line (str);
5660 return;
5663 static void
5664 do_fpa_ldst (str)
5665 char * str;
5667 skip_whitespace (str);
5669 if (fp_reg_required_here (&str, 12) == FAIL)
5671 if (!inst.error)
5672 inst.error = BAD_ARGS;
5673 return;
5676 if (skip_past_comma (&str) == FAIL
5677 || cp_address_required_here (&str) == FAIL)
5679 if (!inst.error)
5680 inst.error = BAD_ARGS;
5681 return;
5684 end_of_line (str);
5687 static void
5688 do_fpa_ldmstm (str)
5689 char * str;
5691 int num_regs;
5693 skip_whitespace (str);
5695 if (fp_reg_required_here (&str, 12) == FAIL)
5697 if (! inst.error)
5698 inst.error = BAD_ARGS;
5699 return;
5702 /* Get Number of registers to transfer. */
5703 if (skip_past_comma (&str) == FAIL
5704 || my_get_expression (&inst.reloc.exp, &str))
5706 if (! inst.error)
5707 inst.error = _("constant expression expected");
5708 return;
5711 if (inst.reloc.exp.X_op != O_constant)
5713 inst.error = _("Constant value required for number of registers");
5714 return;
5717 num_regs = inst.reloc.exp.X_add_number;
5719 if (num_regs < 1 || num_regs > 4)
5721 inst.error = _("number of registers must be in the range [1:4]");
5722 return;
5725 switch (num_regs)
5727 case 1:
5728 inst.instruction |= CP_T_X;
5729 break;
5730 case 2:
5731 inst.instruction |= CP_T_Y;
5732 break;
5733 case 3:
5734 inst.instruction |= CP_T_Y | CP_T_X;
5735 break;
5736 case 4:
5737 break;
5738 default:
5739 abort ();
5742 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ed/fd format. */
5744 int reg;
5745 int write_back;
5746 int offset;
5748 /* The instruction specified "ea" or "fd", so we can only accept
5749 [Rn]{!}. The instruction does not really support stacking or
5750 unstacking, so we have to emulate these by setting appropriate
5751 bits and offsets. */
5752 if (skip_past_comma (&str) == FAIL
5753 || *str != '[')
5755 if (! inst.error)
5756 inst.error = BAD_ARGS;
5757 return;
5760 str++;
5761 skip_whitespace (str);
5763 if ((reg = reg_required_here (&str, 16)) == FAIL)
5764 return;
5766 skip_whitespace (str);
5768 if (*str != ']')
5770 inst.error = BAD_ARGS;
5771 return;
5774 str++;
5775 if (*str == '!')
5777 write_back = 1;
5778 str++;
5779 if (reg == REG_PC)
5781 inst.error =
5782 _("R15 not allowed as base register with write-back");
5783 return;
5786 else
5787 write_back = 0;
5789 if (inst.instruction & CP_T_Pre)
5791 /* Pre-decrement. */
5792 offset = 3 * num_regs;
5793 if (write_back)
5794 inst.instruction |= CP_T_WB;
5796 else
5798 /* Post-increment. */
5799 if (write_back)
5801 inst.instruction |= CP_T_WB;
5802 offset = 3 * num_regs;
5804 else
5806 /* No write-back, so convert this into a standard pre-increment
5807 instruction -- aesthetically more pleasing. */
5808 inst.instruction |= CP_T_Pre | CP_T_UD;
5809 offset = 0;
5813 inst.instruction |= offset;
5815 else if (skip_past_comma (&str) == FAIL
5816 || cp_address_required_here (&str) == FAIL)
5818 if (! inst.error)
5819 inst.error = BAD_ARGS;
5820 return;
5823 end_of_line (str);
5826 static void
5827 do_fpa_dyadic (str)
5828 char * str;
5830 skip_whitespace (str);
5832 if (fp_reg_required_here (&str, 12) == FAIL)
5834 if (! inst.error)
5835 inst.error = BAD_ARGS;
5836 return;
5839 if (skip_past_comma (&str) == FAIL
5840 || fp_reg_required_here (&str, 16) == FAIL)
5842 if (! inst.error)
5843 inst.error = BAD_ARGS;
5844 return;
5847 if (skip_past_comma (&str) == FAIL
5848 || fp_op2 (&str) == FAIL)
5850 if (! inst.error)
5851 inst.error = BAD_ARGS;
5852 return;
5855 end_of_line (str);
5856 return;
5859 static void
5860 do_fpa_monadic (str)
5861 char * str;
5863 skip_whitespace (str);
5865 if (fp_reg_required_here (&str, 12) == FAIL)
5867 if (! inst.error)
5868 inst.error = BAD_ARGS;
5869 return;
5872 if (skip_past_comma (&str) == FAIL
5873 || fp_op2 (&str) == FAIL)
5875 if (! inst.error)
5876 inst.error = BAD_ARGS;
5877 return;
5880 end_of_line (str);
5881 return;
5884 static void
5885 do_fpa_cmp (str)
5886 char * str;
5888 skip_whitespace (str);
5890 if (fp_reg_required_here (&str, 16) == FAIL)
5892 if (! inst.error)
5893 inst.error = BAD_ARGS;
5894 return;
5897 if (skip_past_comma (&str) == FAIL
5898 || fp_op2 (&str) == FAIL)
5900 if (! inst.error)
5901 inst.error = BAD_ARGS;
5902 return;
5905 end_of_line (str);
5906 return;
5909 static void
5910 do_fpa_from_reg (str)
5911 char * str;
5913 skip_whitespace (str);
5915 if (fp_reg_required_here (&str, 16) == FAIL)
5917 if (! inst.error)
5918 inst.error = BAD_ARGS;
5919 return;
5922 if (skip_past_comma (&str) == FAIL
5923 || reg_required_here (&str, 12) == FAIL)
5925 if (! inst.error)
5926 inst.error = BAD_ARGS;
5927 return;
5930 end_of_line (str);
5931 return;
5934 static void
5935 do_fpa_to_reg (str)
5936 char * str;
5938 skip_whitespace (str);
5940 if (reg_required_here (&str, 12) == FAIL)
5941 return;
5943 if (skip_past_comma (&str) == FAIL
5944 || fp_reg_required_here (&str, 0) == FAIL)
5946 if (! inst.error)
5947 inst.error = BAD_ARGS;
5948 return;
5951 end_of_line (str);
5952 return;
5955 /* Thumb specific routines. */
5957 /* Parse and validate that a register is of the right form, this saves
5958 repeated checking of this information in many similar cases.
5959 Unlike the 32-bit case we do not insert the register into the opcode
5960 here, since the position is often unknown until the full instruction
5961 has been parsed. */
5963 static int
5964 thumb_reg (strp, hi_lo)
5965 char ** strp;
5966 int hi_lo;
5968 int reg;
5970 if ((reg = reg_required_here (strp, -1)) == FAIL)
5971 return FAIL;
5973 switch (hi_lo)
5975 case THUMB_REG_LO:
5976 if (reg > 7)
5978 inst.error = _("lo register required");
5979 return FAIL;
5981 break;
5983 case THUMB_REG_HI:
5984 if (reg < 8)
5986 inst.error = _("hi register required");
5987 return FAIL;
5989 break;
5991 default:
5992 break;
5995 return reg;
5998 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
5999 was SUB. */
6001 static void
6002 thumb_add_sub (str, subtract)
6003 char * str;
6004 int subtract;
6006 int Rd, Rs, Rn = FAIL;
6008 skip_whitespace (str);
6010 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
6011 || skip_past_comma (&str) == FAIL)
6013 if (! inst.error)
6014 inst.error = BAD_ARGS;
6015 return;
6018 if (is_immediate_prefix (*str))
6020 Rs = Rd;
6021 str++;
6022 if (my_get_expression (&inst.reloc.exp, &str))
6023 return;
6025 else
6027 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6028 return;
6030 if (skip_past_comma (&str) == FAIL)
6032 /* Two operand format, shuffle the registers
6033 and pretend there are 3. */
6034 Rn = Rs;
6035 Rs = Rd;
6037 else if (is_immediate_prefix (*str))
6039 str++;
6040 if (my_get_expression (&inst.reloc.exp, &str))
6041 return;
6043 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6044 return;
6047 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6048 for the latter case, EXPR contains the immediate that was found. */
6049 if (Rn != FAIL)
6051 /* All register format. */
6052 if (Rd > 7 || Rs > 7 || Rn > 7)
6054 if (Rs != Rd)
6056 inst.error = _("dest and source1 must be the same register");
6057 return;
6060 /* Can't do this for SUB. */
6061 if (subtract)
6063 inst.error = _("subtract valid only on lo regs");
6064 return;
6067 inst.instruction = (T_OPCODE_ADD_HI
6068 | (Rd > 7 ? THUMB_H1 : 0)
6069 | (Rn > 7 ? THUMB_H2 : 0));
6070 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
6072 else
6074 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
6075 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
6078 else
6080 /* Immediate expression, now things start to get nasty. */
6082 /* First deal with HI regs, only very restricted cases allowed:
6083 Adjusting SP, and using PC or SP to get an address. */
6084 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
6085 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
6087 inst.error = _("invalid Hi register with immediate");
6088 return;
6091 if (inst.reloc.exp.X_op != O_constant)
6093 /* Value isn't known yet, all we can do is store all the fragments
6094 we know about in the instruction and let the reloc hacking
6095 work it all out. */
6096 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
6097 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
6099 else
6101 int offset = inst.reloc.exp.X_add_number;
6103 if (subtract)
6104 offset = -offset;
6106 if (offset < 0)
6108 offset = -offset;
6109 subtract = 1;
6111 /* Quick check, in case offset is MIN_INT. */
6112 if (offset < 0)
6114 inst.error = _("immediate value out of range");
6115 return;
6118 else
6119 subtract = 0;
6121 if (Rd == REG_SP)
6123 if (offset & ~0x1fc)
6125 inst.error = _("invalid immediate value for stack adjust");
6126 return;
6128 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
6129 inst.instruction |= offset >> 2;
6131 else if (Rs == REG_PC || Rs == REG_SP)
6133 if (subtract
6134 || (offset & ~0x3fc))
6136 inst.error = _("invalid immediate for address calculation");
6137 return;
6139 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
6140 : T_OPCODE_ADD_SP);
6141 inst.instruction |= (Rd << 8) | (offset >> 2);
6143 else if (Rs == Rd)
6145 if (offset & ~0xff)
6147 inst.error = _("immediate value out of range");
6148 return;
6150 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
6151 inst.instruction |= (Rd << 8) | offset;
6153 else
6155 if (offset & ~0x7)
6157 inst.error = _("immediate value out of range");
6158 return;
6160 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
6161 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
6166 end_of_line (str);
6169 static void
6170 thumb_shift (str, shift)
6171 char * str;
6172 int shift;
6174 int Rd, Rs, Rn = FAIL;
6176 skip_whitespace (str);
6178 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6179 || skip_past_comma (&str) == FAIL)
6181 if (! inst.error)
6182 inst.error = BAD_ARGS;
6183 return;
6186 if (is_immediate_prefix (*str))
6188 /* Two operand immediate format, set Rs to Rd. */
6189 Rs = Rd;
6190 str ++;
6191 if (my_get_expression (&inst.reloc.exp, &str))
6192 return;
6194 else
6196 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6197 return;
6199 if (skip_past_comma (&str) == FAIL)
6201 /* Two operand format, shuffle the registers
6202 and pretend there are 3. */
6203 Rn = Rs;
6204 Rs = Rd;
6206 else if (is_immediate_prefix (*str))
6208 str++;
6209 if (my_get_expression (&inst.reloc.exp, &str))
6210 return;
6212 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6213 return;
6216 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
6217 for the latter case, EXPR contains the immediate that was found. */
6219 if (Rn != FAIL)
6221 if (Rs != Rd)
6223 inst.error = _("source1 and dest must be same register");
6224 return;
6227 switch (shift)
6229 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
6230 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
6231 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
6234 inst.instruction |= Rd | (Rn << 3);
6236 else
6238 switch (shift)
6240 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
6241 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
6242 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
6245 if (inst.reloc.exp.X_op != O_constant)
6247 /* Value isn't known yet, create a dummy reloc and let reloc
6248 hacking fix it up. */
6249 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
6251 else
6253 unsigned shift_value = inst.reloc.exp.X_add_number;
6255 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
6257 inst.error = _("Invalid immediate for shift");
6258 return;
6261 /* Shifts of zero are handled by converting to LSL. */
6262 if (shift_value == 0)
6263 inst.instruction = T_OPCODE_LSL_I;
6265 /* Shifts of 32 are encoded as a shift of zero. */
6266 if (shift_value == 32)
6267 shift_value = 0;
6269 inst.instruction |= shift_value << 6;
6272 inst.instruction |= Rd | (Rs << 3);
6275 end_of_line (str);
6278 static void
6279 thumb_mov_compare (str, move)
6280 char * str;
6281 int move;
6283 int Rd, Rs = FAIL;
6285 skip_whitespace (str);
6287 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
6288 || skip_past_comma (&str) == FAIL)
6290 if (! inst.error)
6291 inst.error = BAD_ARGS;
6292 return;
6295 if (is_immediate_prefix (*str))
6297 str++;
6298 if (my_get_expression (&inst.reloc.exp, &str))
6299 return;
6301 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6302 return;
6304 if (Rs != FAIL)
6306 if (Rs < 8 && Rd < 8)
6308 if (move == THUMB_MOVE)
6309 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
6310 since a MOV instruction produces unpredictable results. */
6311 inst.instruction = T_OPCODE_ADD_I3;
6312 else
6313 inst.instruction = T_OPCODE_CMP_LR;
6314 inst.instruction |= Rd | (Rs << 3);
6316 else
6318 if (move == THUMB_MOVE)
6319 inst.instruction = T_OPCODE_MOV_HR;
6320 else
6321 inst.instruction = T_OPCODE_CMP_HR;
6323 if (Rd > 7)
6324 inst.instruction |= THUMB_H1;
6326 if (Rs > 7)
6327 inst.instruction |= THUMB_H2;
6329 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
6332 else
6334 if (Rd > 7)
6336 inst.error = _("only lo regs allowed with immediate");
6337 return;
6340 if (move == THUMB_MOVE)
6341 inst.instruction = T_OPCODE_MOV_I8;
6342 else
6343 inst.instruction = T_OPCODE_CMP_I8;
6345 inst.instruction |= Rd << 8;
6347 if (inst.reloc.exp.X_op != O_constant)
6348 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
6349 else
6351 unsigned value = inst.reloc.exp.X_add_number;
6353 if (value > 255)
6355 inst.error = _("invalid immediate");
6356 return;
6359 inst.instruction |= value;
6363 end_of_line (str);
6366 static void
6367 thumb_load_store (str, load_store, size)
6368 char * str;
6369 int load_store;
6370 int size;
6372 int Rd, Rb, Ro = FAIL;
6374 skip_whitespace (str);
6376 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6377 || skip_past_comma (&str) == FAIL)
6379 if (! inst.error)
6380 inst.error = BAD_ARGS;
6381 return;
6384 if (*str == '[')
6386 str++;
6387 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6388 return;
6390 if (skip_past_comma (&str) != FAIL)
6392 if (is_immediate_prefix (*str))
6394 str++;
6395 if (my_get_expression (&inst.reloc.exp, &str))
6396 return;
6398 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6399 return;
6401 else
6403 inst.reloc.exp.X_op = O_constant;
6404 inst.reloc.exp.X_add_number = 0;
6407 if (*str != ']')
6409 inst.error = _("expected ']'");
6410 return;
6412 str++;
6414 else if (*str == '=')
6416 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6417 str++;
6419 skip_whitespace (str);
6421 if (my_get_expression (& inst.reloc.exp, & str))
6422 return;
6424 end_of_line (str);
6426 if ( inst.reloc.exp.X_op != O_constant
6427 && inst.reloc.exp.X_op != O_symbol)
6429 inst.error = "Constant expression expected";
6430 return;
6433 if (inst.reloc.exp.X_op == O_constant
6434 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
6436 /* This can be done with a mov instruction. */
6438 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
6439 inst.instruction |= inst.reloc.exp.X_add_number;
6440 return;
6443 /* Insert into literal pool. */
6444 if (add_to_lit_pool () == FAIL)
6446 if (!inst.error)
6447 inst.error = "literal pool insertion failed";
6448 return;
6451 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6452 inst.reloc.pc_rel = 1;
6453 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6454 /* Adjust ARM pipeline offset to Thumb. */
6455 inst.reloc.exp.X_add_number += 4;
6457 return;
6459 else
6461 if (my_get_expression (&inst.reloc.exp, &str))
6462 return;
6464 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6465 inst.reloc.pc_rel = 1;
6466 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
6467 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6468 end_of_line (str);
6469 return;
6472 if (Rb == REG_PC || Rb == REG_SP)
6474 if (size != THUMB_WORD)
6476 inst.error = _("byte or halfword not valid for base register");
6477 return;
6479 else if (Rb == REG_PC && load_store != THUMB_LOAD)
6481 inst.error = _("R15 based store not allowed");
6482 return;
6484 else if (Ro != FAIL)
6486 inst.error = _("Invalid base register for register offset");
6487 return;
6490 if (Rb == REG_PC)
6491 inst.instruction = T_OPCODE_LDR_PC;
6492 else if (load_store == THUMB_LOAD)
6493 inst.instruction = T_OPCODE_LDR_SP;
6494 else
6495 inst.instruction = T_OPCODE_STR_SP;
6497 inst.instruction |= Rd << 8;
6498 if (inst.reloc.exp.X_op == O_constant)
6500 unsigned offset = inst.reloc.exp.X_add_number;
6502 if (offset & ~0x3fc)
6504 inst.error = _("invalid offset");
6505 return;
6508 inst.instruction |= offset >> 2;
6510 else
6511 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6513 else if (Rb > 7)
6515 inst.error = _("invalid base register in load/store");
6516 return;
6518 else if (Ro == FAIL)
6520 /* Immediate offset. */
6521 if (size == THUMB_WORD)
6522 inst.instruction = (load_store == THUMB_LOAD
6523 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
6524 else if (size == THUMB_HALFWORD)
6525 inst.instruction = (load_store == THUMB_LOAD
6526 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
6527 else
6528 inst.instruction = (load_store == THUMB_LOAD
6529 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
6531 inst.instruction |= Rd | (Rb << 3);
6533 if (inst.reloc.exp.X_op == O_constant)
6535 unsigned offset = inst.reloc.exp.X_add_number;
6537 if (offset & ~(0x1f << size))
6539 inst.error = _("Invalid offset");
6540 return;
6542 inst.instruction |= (offset >> size) << 6;
6544 else
6545 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6547 else
6549 /* Register offset. */
6550 if (size == THUMB_WORD)
6551 inst.instruction = (load_store == THUMB_LOAD
6552 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
6553 else if (size == THUMB_HALFWORD)
6554 inst.instruction = (load_store == THUMB_LOAD
6555 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
6556 else
6557 inst.instruction = (load_store == THUMB_LOAD
6558 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
6560 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
6563 end_of_line (str);
6566 /* Given a register and a register type, return 1 if
6567 the register is of the given type, else return 0. */
6569 static int
6570 cirrus_valid_reg (reg, regtype)
6571 int reg;
6572 enum cirrus_regtype regtype;
6574 switch (regtype)
6576 case CIRRUS_REGTYPE_ANY:
6577 return 1;
6579 case CIRRUS_REGTYPE_MVF:
6580 return cirrus_mvf_register (reg);
6582 case CIRRUS_REGTYPE_MVFX:
6583 return cirrus_mvfx_register (reg);
6585 case CIRRUS_REGTYPE_MVD:
6586 return cirrus_mvd_register (reg);
6588 case CIRRUS_REGTYPE_MVDX:
6589 return cirrus_mvdx_register (reg);
6591 case CIRRUS_REGTYPE_MVAX:
6592 return cirrus_mvax_register (reg);
6594 case CIRRUS_REGTYPE_DSPSC:
6595 return ARM_EXT_MAVERICKsc_register (reg);
6598 return 0;
6601 /* A register must be given at this point.
6603 If the register is a Cirrus register, convert it's reg# appropriately.
6605 Shift is the place to put it in inst.instruction.
6607 regtype is type register type expected, and is:
6608 CIRRUS_REGTYPE_MVF
6609 CIRRUS_REGTYPE_MVFX
6610 CIRRUS_REGTYPE_MVD
6611 CIRRUS_REGTYPE_MVDX
6612 CIRRUS_REGTYPE_MVAX
6613 CIRRUS_REGTYPE_DSPSC
6615 Restores input start point on err.
6616 Returns the reg#, or FAIL. */
6618 static int
6619 cirrus_reg_required_here (str, shift, regtype)
6620 char ** str;
6621 int shift;
6622 enum cirrus_regtype regtype;
6624 static char buff [135]; /* XXX */
6625 int reg;
6626 char * start = * str;
6628 if ((reg = arm_reg_parse (str)) != FAIL
6629 && (int_register (reg)
6630 || cirrus_register (reg)))
6632 int orig_reg = reg;
6634 /* Calculate actual register # for opcode. */
6635 if (cirrus_register (reg)
6636 && !ARM_EXT_MAVERICKsc_register (reg)) /* Leave this one as is. */
6638 if (reg >= 130)
6639 reg -= 130;
6640 else if (reg >= 110)
6641 reg -= 110;
6642 else if (reg >= 90)
6643 reg -= 90;
6644 else if (reg >= 70)
6645 reg -= 70;
6646 else if (reg >= 50)
6647 reg -= 50;
6650 if (!cirrus_valid_reg (orig_reg, regtype))
6652 sprintf (buff, _("invalid register type at '%.100s'"), start);
6653 inst.error = buff;
6654 return FAIL;
6657 if (shift >= 0)
6658 inst.instruction |= reg << shift;
6660 return orig_reg;
6663 /* Restore the start point, we may have got a reg of the wrong class. */
6664 *str = start;
6666 /* In the few cases where we might be able to accept something else
6667 this error can be overridden. */
6668 sprintf (buff, _("Cirrus register expected, not '%.100s'"), start);
6669 inst.error = buff;
6671 return FAIL;
6674 /* Cirrus Instructions. */
6676 /* Wrapper functions. */
6678 static void
6679 do_c_binops_1 (str)
6680 char * str;
6682 do_c_binops (str, CIRRUS_MODE1);
6685 static void
6686 do_c_binops_2 (str)
6687 char * str;
6689 do_c_binops (str, CIRRUS_MODE2);
6692 static void
6693 do_c_binops_3 (str)
6694 char * str;
6696 do_c_binops (str, CIRRUS_MODE3);
6699 static void
6700 do_c_triple_4 (str)
6701 char * str;
6703 do_c_triple (str, CIRRUS_MODE4);
6706 static void
6707 do_c_triple_5 (str)
6708 char * str;
6710 do_c_triple (str, CIRRUS_MODE5);
6713 static void
6714 do_c_quad_6 (str)
6715 char * str;
6717 do_c_quad (str, CIRRUS_MODE6);
6720 static void
6721 do_c_dspsc_1 (str)
6722 char * str;
6724 do_c_dspsc (str, CIRRUS_MODE1);
6727 static void
6728 do_c_dspsc_2 (str)
6729 char * str;
6731 do_c_dspsc (str, CIRRUS_MODE2);
6734 static void
6735 do_c_shift_1 (str)
6736 char * str;
6738 do_c_shift (str, CIRRUS_MODE1);
6741 static void
6742 do_c_shift_2 (str)
6743 char * str;
6745 do_c_shift (str, CIRRUS_MODE2);
6748 static void
6749 do_c_ldst_1 (str)
6750 char * str;
6752 do_c_ldst (str, CIRRUS_MODE1);
6755 static void
6756 do_c_ldst_2 (str)
6757 char * str;
6759 do_c_ldst (str, CIRRUS_MODE2);
6762 static void
6763 do_c_ldst_3 (str)
6764 char * str;
6766 do_c_ldst (str, CIRRUS_MODE3);
6769 static void
6770 do_c_ldst_4 (str)
6771 char * str;
6773 do_c_ldst (str, CIRRUS_MODE4);
6776 /* Isnsn like "foo X,Y". */
6778 static void
6779 do_c_binops (str, mode)
6780 char * str;
6781 int mode;
6783 int shift1, shift2;
6785 shift1 = mode & 0xff;
6786 shift2 = (mode >> 8) & 0xff;
6788 skip_whitespace (str);
6790 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
6791 || skip_past_comma (&str) == FAIL
6792 || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL)
6794 if (!inst.error)
6795 inst.error = BAD_ARGS;
6797 else
6798 end_of_line (str);
6801 /* Isnsn like "foo X,Y,Z". */
6803 static void
6804 do_c_triple (str, mode)
6805 char * str;
6806 int mode;
6808 int shift1, shift2, shift3;
6810 shift1 = mode & 0xff;
6811 shift2 = (mode >> 8) & 0xff;
6812 shift3 = (mode >> 16) & 0xff;
6814 skip_whitespace (str);
6816 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
6817 || skip_past_comma (&str) == FAIL
6818 || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL
6819 || skip_past_comma (&str) == FAIL
6820 || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_ANY) == FAIL)
6822 if (!inst.error)
6823 inst.error = BAD_ARGS;
6825 else
6826 end_of_line (str);
6829 /* Isnsn like "foo W,X,Y,Z".
6830 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
6832 static void
6833 do_c_quad (str, mode)
6834 char * str;
6835 int mode;
6837 int shift1, shift2, shift3, shift4;
6838 enum cirrus_regtype rt;
6840 rt = (inst.instruction << 4 == 0xe2006000
6841 || inst.instruction << 4 == 0xe3006000) ? CIRRUS_REGTYPE_MVAX
6842 : CIRRUS_REGTYPE_MVFX;
6844 shift1 = mode & 0xff;
6845 shift2 = (mode >> 8) & 0xff;
6846 shift3 = (mode >> 16) & 0xff;
6847 shift4 = (mode >> 24) & 0xff;
6849 skip_whitespace (str);
6851 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_MVAX) == FAIL
6852 || skip_past_comma (&str) == FAIL
6853 || cirrus_reg_required_here (&str, shift2, rt) == FAIL
6854 || skip_past_comma (&str) == FAIL
6855 || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_MVFX) == FAIL
6856 || skip_past_comma (&str) == FAIL
6857 || cirrus_reg_required_here (&str, shift4, CIRRUS_REGTYPE_MVFX) == FAIL)
6859 if (!inst.error)
6860 inst.error = BAD_ARGS;
6862 else
6863 end_of_line (str);
6866 /* cfmvsc32<cond> DSPSC,MVFX[15:0].
6867 cfmv32sc<cond> MVFX[15:0],DSPSC. */
6869 static void
6870 do_c_dspsc (str, mode)
6871 char * str;
6872 int mode;
6874 int error;
6876 skip_whitespace (str);
6878 error = 0;
6880 if (mode == CIRRUS_MODE1)
6882 /* cfmvsc32. */
6883 if (cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL
6884 || skip_past_comma (&str) == FAIL
6885 || cirrus_reg_required_here (&str, 16, CIRRUS_REGTYPE_MVFX) == FAIL)
6886 error = 1;
6888 else
6890 /* cfmv32sc. */
6891 if (cirrus_reg_required_here (&str, 0, CIRRUS_REGTYPE_MVFX) == FAIL
6892 || skip_past_comma (&str) == FAIL
6893 || cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL)
6894 error = 1;
6897 if (error)
6899 if (!inst.error)
6900 inst.error = BAD_ARGS;
6902 else
6904 end_of_line (str);
6908 /* Cirrus shift immediate instructions.
6909 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
6910 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
6912 static void
6913 do_c_shift (str, mode)
6914 char * str;
6915 int mode;
6917 int error;
6918 int imm, neg = 0;
6920 skip_whitespace (str);
6922 error = 0;
6924 if (cirrus_reg_required_here (&str, 12,
6925 (mode == CIRRUS_MODE1)
6926 ? CIRRUS_REGTYPE_MVFX
6927 : CIRRUS_REGTYPE_MVDX) == FAIL
6928 || skip_past_comma (&str) == FAIL
6929 || cirrus_reg_required_here (&str, 16,
6930 (mode == CIRRUS_MODE1)
6931 ? CIRRUS_REGTYPE_MVFX
6932 : CIRRUS_REGTYPE_MVDX) == FAIL
6933 || skip_past_comma (&str) == FAIL)
6935 if (!inst.error)
6936 inst.error = BAD_ARGS;
6937 return;
6940 /* Calculate the immediate operand.
6941 The operand is a 7bit signed number. */
6942 skip_whitespace (str);
6944 if (*str == '#')
6945 ++str;
6947 if (!ISDIGIT (*str) && *str != '-')
6949 inst.error = _("expecting immediate, 7bit operand");
6950 return;
6953 if (*str == '-')
6955 neg = 1;
6956 ++str;
6959 for (imm = 0; *str && ISDIGIT (*str); ++str)
6960 imm = imm * 10 + *str - '0';
6962 if (imm > 64)
6964 inst.error = _("immediate out of range");
6965 return;
6968 /* Make negative imm's into 7bit signed numbers. */
6969 if (neg)
6971 imm = -imm;
6972 imm &= 0x0000007f;
6975 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
6976 Bits 5-7 of the insn should have bits 4-6 of the immediate.
6977 Bit 4 should be 0. */
6978 imm = (imm & 0xf) | ((imm & 0x70) << 1);
6980 inst.instruction |= imm;
6981 end_of_line (str);
6984 static int
6985 cirrus_parse_offset (str, negative)
6986 char ** str;
6987 int *negative;
6989 char * p = *str;
6990 int offset;
6992 *negative = 0;
6994 skip_whitespace (p);
6996 if (*p == '#')
6997 ++p;
6999 if (*p == '-')
7001 *negative = 1;
7002 ++p;
7005 if (!ISDIGIT (*p))
7007 inst.error = _("offset expected");
7008 return 0;
7011 for (offset = 0; *p && ISDIGIT (*p); ++p)
7012 offset = offset * 10 + *p - '0';
7014 if (offset > 0xff)
7016 inst.error = _("offset out of range");
7017 return 0;
7020 *str = p;
7022 return *negative ? -offset : offset;
7025 /* Cirrus load/store instructions.
7026 <insn><cond> CRd,[Rn,<offset>]{!}.
7027 <insn><cond> CRd,[Rn],<offset>. */
7029 static void
7030 do_c_ldst (str, mode)
7031 char * str;
7032 int mode;
7034 int offset, negative;
7035 enum cirrus_regtype rt;
7037 rt = mode == CIRRUS_MODE1 ? CIRRUS_REGTYPE_MVF
7038 : mode == CIRRUS_MODE2 ? CIRRUS_REGTYPE_MVD
7039 : mode == CIRRUS_MODE3 ? CIRRUS_REGTYPE_MVFX
7040 : mode == CIRRUS_MODE4 ? CIRRUS_REGTYPE_MVDX : CIRRUS_REGTYPE_MVF;
7042 skip_whitespace (str);
7044 if (cirrus_reg_required_here (& str, 12, rt) == FAIL
7045 || skip_past_comma (& str) == FAIL
7046 || *str++ != '['
7047 || reg_required_here (& str, 16) == FAIL)
7048 goto fail_ldst;
7050 if (skip_past_comma (& str) == SUCCESS)
7052 /* You are here: "<offset>]{!}". */
7053 inst.instruction |= PRE_INDEX;
7055 offset = cirrus_parse_offset (&str, &negative);
7057 if (inst.error)
7058 return;
7060 if (*str++ != ']')
7062 inst.error = _("missing ]");
7063 return;
7066 if (*str == '!')
7068 inst.instruction |= WRITE_BACK;
7069 ++str;
7072 else
7074 /* You are here: "], <offset>". */
7075 if (*str++ != ']')
7077 inst.error = _("missing ]");
7078 return;
7081 if (skip_past_comma (&str) == FAIL
7082 || (offset = cirrus_parse_offset (&str, &negative), inst.error))
7083 goto fail_ldst;
7085 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
7088 if (negative)
7089 offset = -offset;
7090 else
7091 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
7093 inst.instruction |= offset >> 2;
7094 end_of_line (str);
7095 return;
7097 fail_ldst:
7098 if (!inst.error)
7099 inst.error = BAD_ARGS;
7100 return;
7103 static void
7104 do_t_nop (str)
7105 char * str;
7107 /* Do nothing. */
7108 end_of_line (str);
7109 return;
7112 /* Handle the Format 4 instructions that do not have equivalents in other
7113 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
7114 BIC and MVN. */
7116 static void
7117 do_t_arit (str)
7118 char * str;
7120 int Rd, Rs, Rn;
7122 skip_whitespace (str);
7124 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7125 || skip_past_comma (&str) == FAIL
7126 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7128 inst.error = BAD_ARGS;
7129 return;
7132 if (skip_past_comma (&str) != FAIL)
7134 /* Three operand format not allowed for TST, CMN, NEG and MVN.
7135 (It isn't allowed for CMP either, but that isn't handled by this
7136 function.) */
7137 if (inst.instruction == T_OPCODE_TST
7138 || inst.instruction == T_OPCODE_CMN
7139 || inst.instruction == T_OPCODE_NEG
7140 || inst.instruction == T_OPCODE_MVN)
7142 inst.error = BAD_ARGS;
7143 return;
7146 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7147 return;
7149 if (Rs != Rd)
7151 inst.error = _("dest and source1 must be the same register");
7152 return;
7154 Rs = Rn;
7157 if (inst.instruction == T_OPCODE_MUL
7158 && Rs == Rd)
7159 as_tsktsk (_("Rs and Rd must be different in MUL"));
7161 inst.instruction |= Rd | (Rs << 3);
7162 end_of_line (str);
7165 static void
7166 do_t_add (str)
7167 char * str;
7169 thumb_add_sub (str, 0);
7172 static void
7173 do_t_asr (str)
7174 char * str;
7176 thumb_shift (str, THUMB_ASR);
7179 static void
7180 do_t_branch9 (str)
7181 char * str;
7183 if (my_get_expression (&inst.reloc.exp, &str))
7184 return;
7185 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
7186 inst.reloc.pc_rel = 1;
7187 end_of_line (str);
7190 static void
7191 do_t_branch12 (str)
7192 char * str;
7194 if (my_get_expression (&inst.reloc.exp, &str))
7195 return;
7196 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
7197 inst.reloc.pc_rel = 1;
7198 end_of_line (str);
7201 /* Find the real, Thumb encoded start of a Thumb function. */
7203 static symbolS *
7204 find_real_start (symbolP)
7205 symbolS * symbolP;
7207 char * real_start;
7208 const char * name = S_GET_NAME (symbolP);
7209 symbolS * new_target;
7211 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
7212 #define STUB_NAME ".real_start_of"
7214 if (name == NULL)
7215 abort ();
7217 /* Names that start with '.' are local labels, not function entry points.
7218 The compiler may generate BL instructions to these labels because it
7219 needs to perform a branch to a far away location. */
7220 if (name[0] == '.')
7221 return symbolP;
7223 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
7224 sprintf (real_start, "%s%s", STUB_NAME, name);
7226 new_target = symbol_find (real_start);
7228 if (new_target == NULL)
7230 as_warn ("Failed to find real start of function: %s\n", name);
7231 new_target = symbolP;
7234 free (real_start);
7236 return new_target;
7239 static void
7240 do_t_branch23 (str)
7241 char * str;
7243 if (my_get_expression (& inst.reloc.exp, & str))
7244 return;
7246 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
7247 inst.reloc.pc_rel = 1;
7248 end_of_line (str);
7250 /* If the destination of the branch is a defined symbol which does not have
7251 the THUMB_FUNC attribute, then we must be calling a function which has
7252 the (interfacearm) attribute. We look for the Thumb entry point to that
7253 function and change the branch to refer to that function instead. */
7254 if ( inst.reloc.exp.X_op == O_symbol
7255 && inst.reloc.exp.X_add_symbol != NULL
7256 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
7257 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
7258 inst.reloc.exp.X_add_symbol =
7259 find_real_start (inst.reloc.exp.X_add_symbol);
7262 static void
7263 do_t_bx (str)
7264 char * str;
7266 int reg;
7268 skip_whitespace (str);
7270 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7271 return;
7273 /* This sets THUMB_H2 from the top bit of reg. */
7274 inst.instruction |= reg << 3;
7276 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
7277 should cause the alignment to be checked once it is known. This is
7278 because BX PC only works if the instruction is word aligned. */
7280 end_of_line (str);
7283 static void
7284 do_t_compare (str)
7285 char * str;
7287 thumb_mov_compare (str, THUMB_COMPARE);
7290 static void
7291 do_t_ldmstm (str)
7292 char * str;
7294 int Rb;
7295 long range;
7297 skip_whitespace (str);
7299 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7300 return;
7302 if (*str != '!')
7303 as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
7304 else
7305 str++;
7307 if (skip_past_comma (&str) == FAIL
7308 || (range = reg_list (&str)) == FAIL)
7310 if (! inst.error)
7311 inst.error = BAD_ARGS;
7312 return;
7315 if (inst.reloc.type != BFD_RELOC_NONE)
7317 /* This really doesn't seem worth it. */
7318 inst.reloc.type = BFD_RELOC_NONE;
7319 inst.error = _("Expression too complex");
7320 return;
7323 if (range & ~0xff)
7325 inst.error = _("only lo-regs valid in load/store multiple");
7326 return;
7329 inst.instruction |= (Rb << 8) | range;
7330 end_of_line (str);
7333 static void
7334 do_t_ldr (str)
7335 char * str;
7337 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
7340 static void
7341 do_t_ldrb (str)
7342 char * str;
7344 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
7347 static void
7348 do_t_ldrh (str)
7349 char * str;
7351 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
7354 static void
7355 do_t_lds (str)
7356 char * str;
7358 int Rd, Rb, Ro;
7360 skip_whitespace (str);
7362 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7363 || skip_past_comma (&str) == FAIL
7364 || *str++ != '['
7365 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7366 || skip_past_comma (&str) == FAIL
7367 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7368 || *str++ != ']')
7370 if (! inst.error)
7371 inst.error = _("Syntax: ldrs[b] Rd, [Rb, Ro]");
7372 return;
7375 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
7376 end_of_line (str);
7379 static void
7380 do_t_lsl (str)
7381 char * str;
7383 thumb_shift (str, THUMB_LSL);
7386 static void
7387 do_t_lsr (str)
7388 char * str;
7390 thumb_shift (str, THUMB_LSR);
7393 static void
7394 do_t_mov (str)
7395 char * str;
7397 thumb_mov_compare (str, THUMB_MOVE);
7400 static void
7401 do_t_push_pop (str)
7402 char * str;
7404 long range;
7406 skip_whitespace (str);
7408 if ((range = reg_list (&str)) == FAIL)
7410 if (! inst.error)
7411 inst.error = BAD_ARGS;
7412 return;
7415 if (inst.reloc.type != BFD_RELOC_NONE)
7417 /* This really doesn't seem worth it. */
7418 inst.reloc.type = BFD_RELOC_NONE;
7419 inst.error = _("Expression too complex");
7420 return;
7423 if (range & ~0xff)
7425 if ((inst.instruction == T_OPCODE_PUSH
7426 && (range & ~0xff) == 1 << REG_LR)
7427 || (inst.instruction == T_OPCODE_POP
7428 && (range & ~0xff) == 1 << REG_PC))
7430 inst.instruction |= THUMB_PP_PC_LR;
7431 range &= 0xff;
7433 else
7435 inst.error = _("invalid register list to push/pop instruction");
7436 return;
7440 inst.instruction |= range;
7441 end_of_line (str);
7444 static void
7445 do_t_str (str)
7446 char * str;
7448 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
7451 static void
7452 do_t_strb (str)
7453 char * str;
7455 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
7458 static void
7459 do_t_strh (str)
7460 char * str;
7462 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
7465 static void
7466 do_t_sub (str)
7467 char * str;
7469 thumb_add_sub (str, 1);
7472 static void
7473 do_t_swi (str)
7474 char * str;
7476 skip_whitespace (str);
7478 if (my_get_expression (&inst.reloc.exp, &str))
7479 return;
7481 inst.reloc.type = BFD_RELOC_ARM_SWI;
7482 end_of_line (str);
7483 return;
7486 static void
7487 do_t_adr (str)
7488 char * str;
7490 int reg;
7492 /* This is a pseudo-op of the form "adr rd, label" to be converted
7493 into a relative address of the form "add rd, pc, #label-.-4". */
7494 skip_whitespace (str);
7496 /* Store Rd in temporary location inside instruction. */
7497 if ((reg = reg_required_here (&str, 4)) == FAIL
7498 || (reg > 7) /* For Thumb reg must be r0..r7. */
7499 || skip_past_comma (&str) == FAIL
7500 || my_get_expression (&inst.reloc.exp, &str))
7502 if (!inst.error)
7503 inst.error = BAD_ARGS;
7504 return;
7507 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
7508 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
7509 inst.reloc.pc_rel = 1;
7510 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
7512 end_of_line (str);
7515 static void
7516 insert_reg (entry)
7517 int entry;
7519 int len = strlen (reg_table[entry].name) + 2;
7520 char * buf = (char *) xmalloc (len);
7521 char * buf2 = (char *) xmalloc (len);
7522 int i = 0;
7524 #ifdef REGISTER_PREFIX
7525 buf[i++] = REGISTER_PREFIX;
7526 #endif
7528 strcpy (buf + i, reg_table[entry].name);
7530 for (i = 0; buf[i]; i++)
7531 buf2[i] = TOUPPER (buf[i]);
7533 buf2[i] = '\0';
7535 hash_insert (arm_reg_hsh, buf, (PTR) & reg_table[entry]);
7536 hash_insert (arm_reg_hsh, buf2, (PTR) & reg_table[entry]);
7539 static void
7540 insert_reg_alias (str, regnum)
7541 char *str;
7542 int regnum;
7544 struct reg_entry *new =
7545 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
7546 char *name = xmalloc (strlen (str) + 1);
7547 strcpy (name, str);
7549 new->name = name;
7550 new->number = regnum;
7552 hash_insert (arm_reg_hsh, name, (PTR) new);
7555 static void
7556 set_constant_flonums ()
7558 int i;
7560 for (i = 0; i < NUM_FLOAT_VALS; i++)
7561 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
7562 abort ();
7565 /* Iterate over the base tables to create the instruction patterns. */
7566 static void
7567 build_arm_ops_hsh ()
7569 unsigned int i;
7570 unsigned int j;
7571 static struct obstack insn_obstack;
7573 obstack_begin (&insn_obstack, 4000);
7575 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
7577 CONST struct asm_opcode *insn = insns + i;
7579 if (insn->cond_offset != 0)
7581 /* Insn supports conditional execution. Build the varaints
7582 and insert them in the hash table. */
7583 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
7585 unsigned len = strlen (insn->template);
7586 struct asm_opcode *new;
7587 char *template;
7589 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
7590 /* All condition codes are two characters. */
7591 template = obstack_alloc (&insn_obstack, len + 3);
7593 strncpy (template, insn->template, insn->cond_offset);
7594 strcpy (template + insn->cond_offset, conds[j].template);
7595 if (len > insn->cond_offset)
7596 strcpy (template + insn->cond_offset + 2,
7597 insn->template + insn->cond_offset);
7598 new->template = template;
7599 new->cond_offset = 0;
7600 new->variant = insn->variant;
7601 new->parms = insn->parms;
7602 new->value = (insn->value & ~COND_MASK) | conds[j].value;
7604 hash_insert (arm_ops_hsh, new->template, (PTR) new);
7607 /* Finally, insert the unconditional insn in the table directly;
7608 no need to build a copy. */
7609 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
7613 void
7614 md_begin ()
7616 unsigned mach;
7617 unsigned int i;
7619 if ( (arm_ops_hsh = hash_new ()) == NULL
7620 || (arm_tops_hsh = hash_new ()) == NULL
7621 || (arm_cond_hsh = hash_new ()) == NULL
7622 || (arm_shift_hsh = hash_new ()) == NULL
7623 || (arm_reg_hsh = hash_new ()) == NULL
7624 || (arm_psr_hsh = hash_new ()) == NULL)
7625 as_fatal (_("Virtual memory exhausted"));
7627 build_arm_ops_hsh ();
7628 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
7629 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
7630 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
7631 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
7632 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
7633 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
7634 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
7635 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
7637 for (i = 0; reg_table[i].name; i++)
7638 insert_reg (i);
7640 set_constant_flonums ();
7642 #if defined OBJ_COFF || defined OBJ_ELF
7644 unsigned int flags = 0;
7646 /* Set the flags in the private structure. */
7647 if (uses_apcs_26) flags |= F_APCS26;
7648 if (support_interwork) flags |= F_INTERWORK;
7649 if (uses_apcs_float) flags |= F_APCS_FLOAT;
7650 if (pic_code) flags |= F_PIC;
7651 if ((cpu_variant & FPU_ANY) == FPU_NONE) flags |= F_SOFT_FLOAT;
7653 bfd_set_private_flags (stdoutput, flags);
7655 /* We have run out flags in the COFF header to encode the
7656 status of ATPCS support, so instead we create a dummy,
7657 empty, debug section called .arm.atpcs. */
7658 if (atpcs)
7660 asection * sec;
7662 sec = bfd_make_section (stdoutput, ".arm.atpcs");
7664 if (sec != NULL)
7666 bfd_set_section_flags
7667 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
7668 bfd_set_section_size (stdoutput, sec, 0);
7669 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
7673 #endif
7675 /* Record the CPU type as well. */
7676 switch (cpu_variant & ARM_CPU_MASK)
7678 case ARM_2:
7679 mach = bfd_mach_arm_2;
7680 break;
7682 case ARM_3: /* Also ARM_250. */
7683 mach = bfd_mach_arm_2a;
7684 break;
7686 case ARM_6: /* Also ARM_7. */
7687 mach = bfd_mach_arm_3;
7688 break;
7690 default:
7691 mach = bfd_mach_arm_4;
7692 break;
7696 /* Catch special cases. */
7697 if (cpu_variant & ARM_EXT_XSCALE)
7698 mach = bfd_mach_arm_XScale;
7699 else if (cpu_variant & ARM_EXT_V5E)
7700 mach = bfd_mach_arm_5TE;
7701 else if (cpu_variant & ARM_EXT_V5)
7703 if (cpu_variant & ARM_EXT_V4T)
7704 mach = bfd_mach_arm_5T;
7705 else
7706 mach = bfd_mach_arm_5;
7708 else if (cpu_variant & ARM_EXT_V4)
7710 if (cpu_variant & ARM_EXT_V4T)
7711 mach = bfd_mach_arm_4T;
7712 else
7713 mach = bfd_mach_arm_4;
7715 else if (cpu_variant & ARM_EXT_V3M)
7716 mach = bfd_mach_arm_3M;
7718 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
7721 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7722 for use in the a.out file, and stores them in the array pointed to by buf.
7723 This knows about the endian-ness of the target machine and does
7724 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
7725 2 (short) and 4 (long) Floating numbers are put out as a series of
7726 LITTLENUMS (shorts, here at least). */
7728 void
7729 md_number_to_chars (buf, val, n)
7730 char * buf;
7731 valueT val;
7732 int n;
7734 if (target_big_endian)
7735 number_to_chars_bigendian (buf, val, n);
7736 else
7737 number_to_chars_littleendian (buf, val, n);
7740 static valueT
7741 md_chars_to_number (buf, n)
7742 char * buf;
7743 int n;
7745 valueT result = 0;
7746 unsigned char * where = (unsigned char *) buf;
7748 if (target_big_endian)
7750 while (n--)
7752 result <<= 8;
7753 result |= (*where++ & 255);
7756 else
7758 while (n--)
7760 result <<= 8;
7761 result |= (where[n] & 255);
7765 return result;
7768 /* Turn a string in input_line_pointer into a floating point constant
7769 of type TYPE, and store the appropriate bytes in *LITP. The number
7770 of LITTLENUMS emitted is stored in *SIZEP. An error message is
7771 returned, or NULL on OK.
7773 Note that fp constants aren't represent in the normal way on the ARM.
7774 In big endian mode, things are as expected. However, in little endian
7775 mode fp constants are big-endian word-wise, and little-endian byte-wise
7776 within the words. For example, (double) 1.1 in big endian mode is
7777 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7778 the byte sequence 99 99 f1 3f 9a 99 99 99.
7780 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
7782 char *
7783 md_atof (type, litP, sizeP)
7784 char type;
7785 char * litP;
7786 int * sizeP;
7788 int prec;
7789 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7790 char *t;
7791 int i;
7793 switch (type)
7795 case 'f':
7796 case 'F':
7797 case 's':
7798 case 'S':
7799 prec = 2;
7800 break;
7802 case 'd':
7803 case 'D':
7804 case 'r':
7805 case 'R':
7806 prec = 4;
7807 break;
7809 case 'x':
7810 case 'X':
7811 prec = 6;
7812 break;
7814 case 'p':
7815 case 'P':
7816 prec = 6;
7817 break;
7819 default:
7820 *sizeP = 0;
7821 return _("Bad call to MD_ATOF()");
7824 t = atof_ieee (input_line_pointer, type, words);
7825 if (t)
7826 input_line_pointer = t;
7827 *sizeP = prec * 2;
7829 if (target_big_endian)
7831 for (i = 0; i < prec; i++)
7833 md_number_to_chars (litP, (valueT) words[i], 2);
7834 litP += 2;
7837 else
7839 /* For a 4 byte float the order of elements in `words' is 1 0. For an
7840 8 byte float the order is 1 0 3 2. */
7841 for (i = 0; i < prec; i += 2)
7843 md_number_to_chars (litP, (valueT) words[i + 1], 2);
7844 md_number_to_chars (litP + 2, (valueT) words[i], 2);
7845 litP += 4;
7849 return 0;
7852 /* The knowledge of the PC's pipeline offset is built into the insns
7853 themselves. */
7855 long
7856 md_pcrel_from (fixP)
7857 fixS * fixP;
7859 if (fixP->fx_addsy
7860 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
7861 && fixP->fx_subsy == NULL)
7862 return 0;
7864 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
7866 /* PC relative addressing on the Thumb is slightly odd
7867 as the bottom two bits of the PC are forced to zero
7868 for the calculation. */
7869 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
7872 #ifdef TE_WINCE
7873 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
7874 so we un-adjust here to compensate for the accomodation. */
7875 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
7876 #else
7877 return fixP->fx_where + fixP->fx_frag->fr_address;
7878 #endif
7881 /* Round up a section size to the appropriate boundary. */
7883 valueT
7884 md_section_align (segment, size)
7885 segT segment ATTRIBUTE_UNUSED;
7886 valueT size;
7888 #ifdef OBJ_ELF
7889 return size;
7890 #else
7891 /* Round all sects to multiple of 4. */
7892 return (size + 3) & ~3;
7893 #endif
7896 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
7897 Otherwise we have no need to default values of symbols. */
7899 symbolS *
7900 md_undefined_symbol (name)
7901 char * name ATTRIBUTE_UNUSED;
7903 #ifdef OBJ_ELF
7904 if (name[0] == '_' && name[1] == 'G'
7905 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
7907 if (!GOT_symbol)
7909 if (symbol_find (name))
7910 as_bad ("GOT already in the symbol table");
7912 GOT_symbol = symbol_new (name, undefined_section,
7913 (valueT) 0, & zero_address_frag);
7916 return GOT_symbol;
7918 #endif
7920 return 0;
7923 /* arm_reg_parse () := if it looks like a register, return its token and
7924 advance the pointer. */
7926 static int
7927 arm_reg_parse (ccp)
7928 register char ** ccp;
7930 char * start = * ccp;
7931 char c;
7932 char * p;
7933 struct reg_entry * reg;
7935 #ifdef REGISTER_PREFIX
7936 if (*start != REGISTER_PREFIX)
7937 return FAIL;
7938 p = start + 1;
7939 #else
7940 p = start;
7941 #ifdef OPTIONAL_REGISTER_PREFIX
7942 if (*p == OPTIONAL_REGISTER_PREFIX)
7943 p++, start++;
7944 #endif
7945 #endif
7946 if (!ISALPHA (*p) || !is_name_beginner (*p))
7947 return FAIL;
7949 c = *p++;
7950 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
7951 c = *p++;
7953 *--p = 0;
7954 reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
7955 *p = c;
7957 if (reg)
7959 *ccp = p;
7960 return reg->number;
7963 return FAIL;
7966 void
7967 md_apply_fix3 (fixP, valP, seg)
7968 fixS * fixP;
7969 valueT * valP;
7970 segT seg;
7972 offsetT value = * valP;
7973 offsetT newval;
7974 unsigned int newimm;
7975 unsigned long temp;
7976 int sign;
7977 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
7978 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
7980 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
7982 /* Note whether this will delete the relocation. */
7983 #if 0
7984 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
7985 doesn't work fully.) */
7986 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
7987 && !fixP->fx_pcrel)
7988 #else
7989 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
7990 #endif
7991 fixP->fx_done = 1;
7993 /* If this symbol is in a different section then we need to leave it for
7994 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
7995 so we have to undo it's effects here. */
7996 if (fixP->fx_pcrel)
7998 if (fixP->fx_addsy != NULL
7999 && S_IS_DEFINED (fixP->fx_addsy)
8000 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
8002 if (target_oabi
8003 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
8004 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
8006 value = 0;
8007 else
8008 value += md_pcrel_from (fixP);
8012 /* Remember value for emit_reloc. */
8013 fixP->fx_addnumber = value;
8015 switch (fixP->fx_r_type)
8017 case BFD_RELOC_ARM_IMMEDIATE:
8018 newimm = validate_immediate (value);
8019 temp = md_chars_to_number (buf, INSN_SIZE);
8021 /* If the instruction will fail, see if we can fix things up by
8022 changing the opcode. */
8023 if (newimm == (unsigned int) FAIL
8024 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
8026 as_bad_where (fixP->fx_file, fixP->fx_line,
8027 _("invalid constant (%lx) after fixup"),
8028 (unsigned long) value);
8029 break;
8032 newimm |= (temp & 0xfffff000);
8033 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
8034 break;
8036 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
8038 unsigned int highpart = 0;
8039 unsigned int newinsn = 0xe1a00000; /* nop. */
8040 newimm = validate_immediate (value);
8041 temp = md_chars_to_number (buf, INSN_SIZE);
8043 /* If the instruction will fail, see if we can fix things up by
8044 changing the opcode. */
8045 if (newimm == (unsigned int) FAIL
8046 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
8048 /* No ? OK - try using two ADD instructions to generate
8049 the value. */
8050 newimm = validate_immediate_twopart (value, & highpart);
8052 /* Yes - then make sure that the second instruction is
8053 also an add. */
8054 if (newimm != (unsigned int) FAIL)
8055 newinsn = temp;
8056 /* Still No ? Try using a negated value. */
8057 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
8058 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
8059 /* Otherwise - give up. */
8060 else
8062 as_bad_where (fixP->fx_file, fixP->fx_line,
8063 _("Unable to compute ADRL instructions for PC offset of 0x%lx"),
8064 value);
8065 break;
8068 /* Replace the first operand in the 2nd instruction (which
8069 is the PC) with the destination register. We have
8070 already added in the PC in the first instruction and we
8071 do not want to do it again. */
8072 newinsn &= ~ 0xf0000;
8073 newinsn |= ((newinsn & 0x0f000) << 4);
8076 newimm |= (temp & 0xfffff000);
8077 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
8079 highpart |= (newinsn & 0xfffff000);
8080 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
8082 break;
8084 case BFD_RELOC_ARM_OFFSET_IMM:
8085 sign = value >= 0;
8087 if (value < 0)
8088 value = - value;
8090 if (validate_offset_imm (value, 0) == FAIL)
8092 as_bad_where (fixP->fx_file, fixP->fx_line,
8093 _("bad immediate value for offset (%ld)"),
8094 (long) value);
8095 break;
8098 newval = md_chars_to_number (buf, INSN_SIZE);
8099 newval &= 0xff7ff000;
8100 newval |= value | (sign ? INDEX_UP : 0);
8101 md_number_to_chars (buf, newval, INSN_SIZE);
8102 break;
8104 case BFD_RELOC_ARM_OFFSET_IMM8:
8105 case BFD_RELOC_ARM_HWLITERAL:
8106 sign = value >= 0;
8108 if (value < 0)
8109 value = - value;
8111 if (validate_offset_imm (value, 1) == FAIL)
8113 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
8114 as_bad_where (fixP->fx_file, fixP->fx_line,
8115 _("invalid literal constant: pool needs to be closer"));
8116 else
8117 as_bad (_("bad immediate value for half-word offset (%ld)"),
8118 (long) value);
8119 break;
8122 newval = md_chars_to_number (buf, INSN_SIZE);
8123 newval &= 0xff7ff0f0;
8124 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
8125 md_number_to_chars (buf, newval, INSN_SIZE);
8126 break;
8128 case BFD_RELOC_ARM_LITERAL:
8129 sign = value >= 0;
8131 if (value < 0)
8132 value = - value;
8134 if (validate_offset_imm (value, 0) == FAIL)
8136 as_bad_where (fixP->fx_file, fixP->fx_line,
8137 _("invalid literal constant: pool needs to be closer"));
8138 break;
8141 newval = md_chars_to_number (buf, INSN_SIZE);
8142 newval &= 0xff7ff000;
8143 newval |= value | (sign ? INDEX_UP : 0);
8144 md_number_to_chars (buf, newval, INSN_SIZE);
8145 break;
8147 case BFD_RELOC_ARM_SHIFT_IMM:
8148 newval = md_chars_to_number (buf, INSN_SIZE);
8149 if (((unsigned long) value) > 32
8150 || (value == 32
8151 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
8153 as_bad_where (fixP->fx_file, fixP->fx_line,
8154 _("shift expression is too large"));
8155 break;
8158 if (value == 0)
8159 /* Shifts of zero must be done as lsl. */
8160 newval &= ~0x60;
8161 else if (value == 32)
8162 value = 0;
8163 newval &= 0xfffff07f;
8164 newval |= (value & 0x1f) << 7;
8165 md_number_to_chars (buf, newval, INSN_SIZE);
8166 break;
8168 case BFD_RELOC_ARM_SWI:
8169 if (arm_data->thumb_mode)
8171 if (((unsigned long) value) > 0xff)
8172 as_bad_where (fixP->fx_file, fixP->fx_line,
8173 _("Invalid swi expression"));
8174 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
8175 newval |= value;
8176 md_number_to_chars (buf, newval, THUMB_SIZE);
8178 else
8180 if (((unsigned long) value) > 0x00ffffff)
8181 as_bad_where (fixP->fx_file, fixP->fx_line,
8182 _("Invalid swi expression"));
8183 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
8184 newval |= value;
8185 md_number_to_chars (buf, newval, INSN_SIZE);
8187 break;
8189 case BFD_RELOC_ARM_MULTI:
8190 if (((unsigned long) value) > 0xffff)
8191 as_bad_where (fixP->fx_file, fixP->fx_line,
8192 _("Invalid expression in load/store multiple"));
8193 newval = value | md_chars_to_number (buf, INSN_SIZE);
8194 md_number_to_chars (buf, newval, INSN_SIZE);
8195 break;
8197 case BFD_RELOC_ARM_PCREL_BRANCH:
8198 newval = md_chars_to_number (buf, INSN_SIZE);
8200 /* Sign-extend a 24-bit number. */
8201 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
8203 #ifdef OBJ_ELF
8204 if (! target_oabi)
8205 value = fixP->fx_offset;
8206 #endif
8208 /* We are going to store value (shifted right by two) in the
8209 instruction, in a 24 bit, signed field. Thus we need to check
8210 that none of the top 8 bits of the shifted value (top 7 bits of
8211 the unshifted, unsigned value) are set, or that they are all set. */
8212 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
8213 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
8215 #ifdef OBJ_ELF
8216 /* Normally we would be stuck at this point, since we cannot store
8217 the absolute address that is the destination of the branch in the
8218 24 bits of the branch instruction. If however, we happen to know
8219 that the destination of the branch is in the same section as the
8220 branch instruciton itself, then we can compute the relocation for
8221 ourselves and not have to bother the linker with it.
8223 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
8224 because I have not worked out how to do this for OBJ_COFF or
8225 target_oabi. */
8226 if (! target_oabi
8227 && fixP->fx_addsy != NULL
8228 && S_IS_DEFINED (fixP->fx_addsy)
8229 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
8231 /* Get pc relative value to go into the branch. */
8232 value = * valP;
8234 /* Permit a backward branch provided that enough bits
8235 are set. Allow a forwards branch, provided that
8236 enough bits are clear. */
8237 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
8238 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
8239 fixP->fx_done = 1;
8242 if (! fixP->fx_done)
8243 #endif
8244 as_bad_where (fixP->fx_file, fixP->fx_line,
8245 _("gas can't handle same-section branch dest >= 0x04000000"));
8248 value >>= 2;
8249 value += SEXT24 (newval);
8251 if ( (value & ~ ((offsetT) 0xffffff)) != 0
8252 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
8253 as_bad_where (fixP->fx_file, fixP->fx_line,
8254 _("out of range branch"));
8256 newval = (value & 0x00ffffff) | (newval & 0xff000000);
8257 md_number_to_chars (buf, newval, INSN_SIZE);
8258 break;
8260 case BFD_RELOC_ARM_PCREL_BLX:
8262 offsetT hbit;
8263 newval = md_chars_to_number (buf, INSN_SIZE);
8265 #ifdef OBJ_ELF
8266 if (! target_oabi)
8267 value = fixP->fx_offset;
8268 #endif
8269 hbit = (value >> 1) & 1;
8270 value = (value >> 2) & 0x00ffffff;
8271 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
8272 newval = value | (newval & 0xfe000000) | (hbit << 24);
8273 md_number_to_chars (buf, newval, INSN_SIZE);
8275 break;
8277 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
8278 newval = md_chars_to_number (buf, THUMB_SIZE);
8280 addressT diff = (newval & 0xff) << 1;
8281 if (diff & 0x100)
8282 diff |= ~0xff;
8284 value += diff;
8285 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
8286 as_bad_where (fixP->fx_file, fixP->fx_line,
8287 _("Branch out of range"));
8288 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
8290 md_number_to_chars (buf, newval, THUMB_SIZE);
8291 break;
8293 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
8294 newval = md_chars_to_number (buf, THUMB_SIZE);
8296 addressT diff = (newval & 0x7ff) << 1;
8297 if (diff & 0x800)
8298 diff |= ~0x7ff;
8300 value += diff;
8301 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
8302 as_bad_where (fixP->fx_file, fixP->fx_line,
8303 _("Branch out of range"));
8304 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
8306 md_number_to_chars (buf, newval, THUMB_SIZE);
8307 break;
8309 case BFD_RELOC_THUMB_PCREL_BLX:
8310 case BFD_RELOC_THUMB_PCREL_BRANCH23:
8312 offsetT newval2;
8313 addressT diff;
8315 newval = md_chars_to_number (buf, THUMB_SIZE);
8316 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
8317 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
8318 if (diff & 0x400000)
8319 diff |= ~0x3fffff;
8320 #ifdef OBJ_ELF
8321 value = fixP->fx_offset;
8322 #endif
8323 value += diff;
8324 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
8325 as_bad_where (fixP->fx_file, fixP->fx_line,
8326 _("Branch with link out of range"));
8328 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
8329 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
8330 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
8331 /* Remove bit zero of the adjusted offset. Bit zero can only be
8332 set if the upper insn is at a half-word boundary, since the
8333 destination address, an ARM instruction, must always be on a
8334 word boundary. The semantics of the BLX (1) instruction, however,
8335 are that bit zero in the offset must always be zero, and the
8336 corresponding bit one in the target address will be set from bit
8337 one of the source address. */
8338 newval2 &= ~1;
8339 md_number_to_chars (buf, newval, THUMB_SIZE);
8340 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
8342 break;
8344 case BFD_RELOC_8:
8345 if (fixP->fx_done || fixP->fx_pcrel)
8346 md_number_to_chars (buf, value, 1);
8347 #ifdef OBJ_ELF
8348 else if (!target_oabi)
8350 value = fixP->fx_offset;
8351 md_number_to_chars (buf, value, 1);
8353 #endif
8354 break;
8356 case BFD_RELOC_16:
8357 if (fixP->fx_done || fixP->fx_pcrel)
8358 md_number_to_chars (buf, value, 2);
8359 #ifdef OBJ_ELF
8360 else if (!target_oabi)
8362 value = fixP->fx_offset;
8363 md_number_to_chars (buf, value, 2);
8365 #endif
8366 break;
8368 #ifdef OBJ_ELF
8369 case BFD_RELOC_ARM_GOT32:
8370 case BFD_RELOC_ARM_GOTOFF:
8371 md_number_to_chars (buf, 0, 4);
8372 break;
8373 #endif
8375 case BFD_RELOC_RVA:
8376 case BFD_RELOC_32:
8377 if (fixP->fx_done || fixP->fx_pcrel)
8378 md_number_to_chars (buf, value, 4);
8379 #ifdef OBJ_ELF
8380 else if (!target_oabi)
8382 value = fixP->fx_offset;
8383 md_number_to_chars (buf, value, 4);
8385 #endif
8386 break;
8388 #ifdef OBJ_ELF
8389 case BFD_RELOC_ARM_PLT32:
8390 /* It appears the instruction is fully prepared at this point. */
8391 break;
8392 #endif
8394 case BFD_RELOC_ARM_GOTPC:
8395 md_number_to_chars (buf, value, 4);
8396 break;
8398 case BFD_RELOC_ARM_CP_OFF_IMM:
8399 sign = value >= 0;
8400 if (value < -1023 || value > 1023 || (value & 3))
8401 as_bad_where (fixP->fx_file, fixP->fx_line,
8402 _("Illegal value for co-processor offset"));
8403 if (value < 0)
8404 value = -value;
8405 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
8406 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
8407 md_number_to_chars (buf, newval, INSN_SIZE);
8408 break;
8410 case BFD_RELOC_ARM_THUMB_OFFSET:
8411 newval = md_chars_to_number (buf, THUMB_SIZE);
8412 /* Exactly what ranges, and where the offset is inserted depends
8413 on the type of instruction, we can establish this from the
8414 top 4 bits. */
8415 switch (newval >> 12)
8417 case 4: /* PC load. */
8418 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
8419 forced to zero for these loads, so we will need to round
8420 up the offset if the instruction address is not word
8421 aligned (since the final address produced must be, and
8422 we can only describe word-aligned immediate offsets). */
8424 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
8425 as_bad_where (fixP->fx_file, fixP->fx_line,
8426 _("Invalid offset, target not word aligned (0x%08X)"),
8427 (unsigned int) (fixP->fx_frag->fr_address
8428 + fixP->fx_where + value));
8430 if ((value + 2) & ~0x3fe)
8431 as_bad_where (fixP->fx_file, fixP->fx_line,
8432 _("Invalid offset, value too big (0x%08lX)"), value);
8434 /* Round up, since pc will be rounded down. */
8435 newval |= (value + 2) >> 2;
8436 break;
8438 case 9: /* SP load/store. */
8439 if (value & ~0x3fc)
8440 as_bad_where (fixP->fx_file, fixP->fx_line,
8441 _("Invalid offset, value too big (0x%08lX)"), value);
8442 newval |= value >> 2;
8443 break;
8445 case 6: /* Word load/store. */
8446 if (value & ~0x7c)
8447 as_bad_where (fixP->fx_file, fixP->fx_line,
8448 _("Invalid offset, value too big (0x%08lX)"), value);
8449 newval |= value << 4; /* 6 - 2. */
8450 break;
8452 case 7: /* Byte load/store. */
8453 if (value & ~0x1f)
8454 as_bad_where (fixP->fx_file, fixP->fx_line,
8455 _("Invalid offset, value too big (0x%08lX)"), value);
8456 newval |= value << 6;
8457 break;
8459 case 8: /* Halfword load/store. */
8460 if (value & ~0x3e)
8461 as_bad_where (fixP->fx_file, fixP->fx_line,
8462 _("Invalid offset, value too big (0x%08lX)"), value);
8463 newval |= value << 5; /* 6 - 1. */
8464 break;
8466 default:
8467 as_bad_where (fixP->fx_file, fixP->fx_line,
8468 "Unable to process relocation for thumb opcode: %lx",
8469 (unsigned long) newval);
8470 break;
8472 md_number_to_chars (buf, newval, THUMB_SIZE);
8473 break;
8475 case BFD_RELOC_ARM_THUMB_ADD:
8476 /* This is a complicated relocation, since we use it for all of
8477 the following immediate relocations:
8479 3bit ADD/SUB
8480 8bit ADD/SUB
8481 9bit ADD/SUB SP word-aligned
8482 10bit ADD PC/SP word-aligned
8484 The type of instruction being processed is encoded in the
8485 instruction field:
8487 0x8000 SUB
8488 0x00F0 Rd
8489 0x000F Rs
8491 newval = md_chars_to_number (buf, THUMB_SIZE);
8493 int rd = (newval >> 4) & 0xf;
8494 int rs = newval & 0xf;
8495 int subtract = newval & 0x8000;
8497 if (rd == REG_SP)
8499 if (value & ~0x1fc)
8500 as_bad_where (fixP->fx_file, fixP->fx_line,
8501 _("Invalid immediate for stack address calculation"));
8502 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8503 newval |= value >> 2;
8505 else if (rs == REG_PC || rs == REG_SP)
8507 if (subtract ||
8508 value & ~0x3fc)
8509 as_bad_where (fixP->fx_file, fixP->fx_line,
8510 _("Invalid immediate for address calculation (value = 0x%08lX)"),
8511 (unsigned long) value);
8512 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
8513 newval |= rd << 8;
8514 newval |= value >> 2;
8516 else if (rs == rd)
8518 if (value & ~0xff)
8519 as_bad_where (fixP->fx_file, fixP->fx_line,
8520 _("Invalid 8bit immediate"));
8521 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8522 newval |= (rd << 8) | value;
8524 else
8526 if (value & ~0x7)
8527 as_bad_where (fixP->fx_file, fixP->fx_line,
8528 _("Invalid 3bit immediate"));
8529 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8530 newval |= rd | (rs << 3) | (value << 6);
8533 md_number_to_chars (buf, newval, THUMB_SIZE);
8534 break;
8536 case BFD_RELOC_ARM_THUMB_IMM:
8537 newval = md_chars_to_number (buf, THUMB_SIZE);
8538 switch (newval >> 11)
8540 case 0x04: /* 8bit immediate MOV. */
8541 case 0x05: /* 8bit immediate CMP. */
8542 if (value < 0 || value > 255)
8543 as_bad_where (fixP->fx_file, fixP->fx_line,
8544 _("Invalid immediate: %ld is too large"),
8545 (long) value);
8546 newval |= value;
8547 break;
8549 default:
8550 abort ();
8552 md_number_to_chars (buf, newval, THUMB_SIZE);
8553 break;
8555 case BFD_RELOC_ARM_THUMB_SHIFT:
8556 /* 5bit shift value (0..31). */
8557 if (value < 0 || value > 31)
8558 as_bad_where (fixP->fx_file, fixP->fx_line,
8559 _("Illegal Thumb shift value: %ld"), (long) value);
8560 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
8561 newval |= value << 6;
8562 md_number_to_chars (buf, newval, THUMB_SIZE);
8563 break;
8565 case BFD_RELOC_VTABLE_INHERIT:
8566 case BFD_RELOC_VTABLE_ENTRY:
8567 fixP->fx_done = 0;
8568 return;
8570 case BFD_RELOC_NONE:
8571 default:
8572 as_bad_where (fixP->fx_file, fixP->fx_line,
8573 _("Bad relocation fixup type (%d)"), fixP->fx_r_type);
8577 /* Translate internal representation of relocation info to BFD target
8578 format. */
8580 arelent *
8581 tc_gen_reloc (section, fixp)
8582 asection * section ATTRIBUTE_UNUSED;
8583 fixS * fixp;
8585 arelent * reloc;
8586 bfd_reloc_code_real_type code;
8588 reloc = (arelent *) xmalloc (sizeof (arelent));
8590 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
8591 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
8592 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
8594 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
8595 #ifndef OBJ_ELF
8596 if (fixp->fx_pcrel == 0)
8597 reloc->addend = fixp->fx_offset;
8598 else
8599 reloc->addend = fixp->fx_offset = reloc->address;
8600 #else /* OBJ_ELF */
8601 reloc->addend = fixp->fx_offset;
8602 #endif
8604 switch (fixp->fx_r_type)
8606 case BFD_RELOC_8:
8607 if (fixp->fx_pcrel)
8609 code = BFD_RELOC_8_PCREL;
8610 break;
8613 case BFD_RELOC_16:
8614 if (fixp->fx_pcrel)
8616 code = BFD_RELOC_16_PCREL;
8617 break;
8620 case BFD_RELOC_32:
8621 if (fixp->fx_pcrel)
8623 code = BFD_RELOC_32_PCREL;
8624 break;
8627 case BFD_RELOC_ARM_PCREL_BRANCH:
8628 case BFD_RELOC_ARM_PCREL_BLX:
8629 case BFD_RELOC_RVA:
8630 case BFD_RELOC_THUMB_PCREL_BRANCH9:
8631 case BFD_RELOC_THUMB_PCREL_BRANCH12:
8632 case BFD_RELOC_THUMB_PCREL_BRANCH23:
8633 case BFD_RELOC_THUMB_PCREL_BLX:
8634 case BFD_RELOC_VTABLE_ENTRY:
8635 case BFD_RELOC_VTABLE_INHERIT:
8636 code = fixp->fx_r_type;
8637 break;
8639 case BFD_RELOC_ARM_LITERAL:
8640 case BFD_RELOC_ARM_HWLITERAL:
8641 /* If this is called then the a literal has been referenced across
8642 a section boundary - possibly due to an implicit dump. */
8643 as_bad_where (fixp->fx_file, fixp->fx_line,
8644 _("Literal referenced across section boundary (Implicit dump?)"));
8645 return NULL;
8647 #ifdef OBJ_ELF
8648 case BFD_RELOC_ARM_GOT32:
8649 case BFD_RELOC_ARM_GOTOFF:
8650 case BFD_RELOC_ARM_PLT32:
8651 code = fixp->fx_r_type;
8652 break;
8653 #endif
8655 case BFD_RELOC_ARM_IMMEDIATE:
8656 as_bad_where (fixp->fx_file, fixp->fx_line,
8657 _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
8658 fixp->fx_r_type);
8659 return NULL;
8661 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
8662 as_bad_where (fixp->fx_file, fixp->fx_line,
8663 _("ADRL used for a symbol not defined in the same file"));
8664 return NULL;
8666 case BFD_RELOC_ARM_OFFSET_IMM:
8667 as_bad_where (fixp->fx_file, fixp->fx_line,
8668 _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
8669 fixp->fx_r_type);
8670 return NULL;
8672 default:
8674 char * type;
8676 switch (fixp->fx_r_type)
8678 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
8679 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
8680 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
8681 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
8682 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
8683 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
8684 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
8685 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
8686 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
8687 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
8688 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
8689 default: type = _("<unknown>"); break;
8691 as_bad_where (fixp->fx_file, fixp->fx_line,
8692 _("Cannot represent %s relocation in this object file format"),
8693 type);
8694 return NULL;
8698 #ifdef OBJ_ELF
8699 if (code == BFD_RELOC_32_PCREL
8700 && GOT_symbol
8701 && fixp->fx_addsy == GOT_symbol)
8703 code = BFD_RELOC_ARM_GOTPC;
8704 reloc->addend = fixp->fx_offset = reloc->address;
8706 #endif
8708 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
8710 if (reloc->howto == NULL)
8712 as_bad_where (fixp->fx_file, fixp->fx_line,
8713 _("Can not represent %s relocation in this object file format"),
8714 bfd_get_reloc_code_name (code));
8715 return NULL;
8718 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
8719 vtable entry to be used in the relocation's section offset. */
8720 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
8721 reloc->address = fixp->fx_offset;
8723 return reloc;
8727 md_estimate_size_before_relax (fragP, segtype)
8728 fragS * fragP ATTRIBUTE_UNUSED;
8729 segT segtype ATTRIBUTE_UNUSED;
8731 as_fatal (_("md_estimate_size_before_relax\n"));
8732 return 1;
8735 static void
8736 output_inst PARAMS ((void))
8738 char * to = NULL;
8740 if (inst.error)
8742 as_bad (inst.error);
8743 return;
8746 to = frag_more (inst.size);
8748 if (thumb_mode && (inst.size > THUMB_SIZE))
8750 assert (inst.size == (2 * THUMB_SIZE));
8751 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
8752 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
8754 else if (inst.size > INSN_SIZE)
8756 assert (inst.size == (2 * INSN_SIZE));
8757 md_number_to_chars (to, inst.instruction, INSN_SIZE);
8758 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
8760 else
8761 md_number_to_chars (to, inst.instruction, inst.size);
8763 if (inst.reloc.type != BFD_RELOC_NONE)
8764 fix_new_arm (frag_now, to - frag_now->fr_literal,
8765 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
8766 inst.reloc.type);
8768 #ifdef OBJ_ELF
8769 dwarf2_emit_insn (inst.size);
8770 #endif
8773 void
8774 md_assemble (str)
8775 char * str;
8777 char c;
8778 char * p;
8779 char * q;
8780 char * start;
8782 /* Align the instruction.
8783 This may not be the right thing to do but ... */
8784 #if 0
8785 arm_align (2, 0);
8786 #endif
8787 listing_prev_line (); /* Defined in listing.h. */
8789 /* Align the previous label if needed. */
8790 if (last_label_seen != NULL)
8792 symbol_set_frag (last_label_seen, frag_now);
8793 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
8794 S_SET_SEGMENT (last_label_seen, now_seg);
8797 memset (&inst, '\0', sizeof (inst));
8798 inst.reloc.type = BFD_RELOC_NONE;
8800 skip_whitespace (str);
8802 /* Scan up to the end of the op-code, which must end in white space or
8803 end of string. */
8804 for (start = p = str; *p != '\0'; p++)
8805 if (*p == ' ')
8806 break;
8808 if (p == str)
8810 as_bad (_("No operator -- statement `%s'\n"), str);
8811 return;
8814 if (thumb_mode)
8816 const struct thumb_opcode * opcode;
8818 c = *p;
8819 *p = '\0';
8820 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
8821 *p = c;
8823 if (opcode)
8825 /* Check that this instruction is supported for this CPU. */
8826 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
8828 as_bad (_("selected processor does not support this opcode"));
8829 return;
8832 inst.instruction = opcode->value;
8833 inst.size = opcode->size;
8834 (*opcode->parms) (p);
8835 output_inst ();
8836 return;
8839 else
8841 const struct asm_opcode * opcode;
8843 c = *p;
8844 *p = '\0';
8845 opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
8846 *p = c;
8848 if (opcode)
8850 /* Check that this instruction is supported for this CPU. */
8851 if ((opcode->variant & cpu_variant) == 0)
8853 as_bad (_("selected processor does not support this opcode"));
8854 return;
8857 inst.instruction = opcode->value;
8858 inst.size = INSN_SIZE;
8859 (*opcode->parms) (p);
8860 output_inst ();
8861 return;
8865 /* It wasn't an instruction, but it might be a register alias of the form
8866 alias .req reg. */
8867 q = p;
8868 skip_whitespace (q);
8870 c = *p;
8871 *p = '\0';
8873 if (*q && !strncmp (q, ".req ", 4))
8875 int reg;
8876 char * copy_of_str;
8877 char * r;
8879 #ifdef IGNORE_OPCODE_CASE
8880 str = original_case_string;
8881 #endif
8882 copy_of_str = str;
8884 q += 4;
8885 skip_whitespace (q);
8887 for (r = q; *r != '\0'; r++)
8888 if (*r == ' ')
8889 break;
8891 if (r != q)
8893 int regnum;
8894 char d = *r;
8896 *r = '\0';
8897 regnum = arm_reg_parse (& q);
8898 *r = d;
8900 reg = arm_reg_parse (& str);
8902 if (reg == FAIL)
8904 if (regnum != FAIL)
8905 insert_reg_alias (str, regnum);
8906 else
8907 as_warn (_("register '%s' does not exist\n"), q);
8909 else if (regnum != FAIL)
8911 if (reg != regnum)
8912 as_warn (_("ignoring redefinition of register alias '%s'"),
8913 copy_of_str);
8915 /* Do not warn about redefinitions to the same alias. */
8917 else
8918 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
8919 copy_of_str, q);
8921 else
8922 as_warn (_("ignoring incomplete .req pseuso op"));
8924 *p = c;
8925 return;
8928 *p = c;
8929 as_bad (_("bad instruction `%s'"), start);
8932 /* md_parse_option
8933 Invocation line includes a switch not recognized by the base assembler.
8934 See if it's a processor-specific option. These are:
8935 Cpu variants, the arm part is optional:
8936 -m[arm]1 Currently not supported.
8937 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
8938 -m[arm]3 Arm 3 processor
8939 -m[arm]6[xx], Arm 6 processors
8940 -m[arm]7[xx][t][[d]m] Arm 7 processors
8941 -m[arm]8[10] Arm 8 processors
8942 -m[arm]9[20][tdmi] Arm 9 processors
8943 -marm9e Allow Cirrus/DSP instructions
8944 -mstrongarm[110[0]] StrongARM processors
8945 -mxscale XScale processors
8946 -m[arm]v[2345[t[e]]] Arm architectures
8947 -mall All (except the ARM1)
8948 FP variants:
8949 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
8950 -mfpe-old (No float load/store multiples)
8951 -mno-fpu Disable all floating point instructions
8952 Run-time endian selection:
8953 -EB big endian cpu
8954 -EL little endian cpu
8955 ARM Procedure Calling Standard:
8956 -mapcs-32 32 bit APCS
8957 -mapcs-26 26 bit APCS
8958 -mapcs-float Pass floats in float regs
8959 -mapcs-reentrant Position independent code
8960 -mthumb-interwork Code supports Arm/Thumb interworking
8961 -matpcs ARM/Thumb Procedure Call Standard
8962 -moabi Old ELF ABI */
8964 const char * md_shortopts = "m:k";
8966 struct option md_longopts[] =
8968 #ifdef ARM_BI_ENDIAN
8969 #define OPTION_EB (OPTION_MD_BASE + 0)
8970 {"EB", no_argument, NULL, OPTION_EB},
8971 #define OPTION_EL (OPTION_MD_BASE + 1)
8972 {"EL", no_argument, NULL, OPTION_EL},
8973 #ifdef OBJ_ELF
8974 #define OPTION_OABI (OPTION_MD_BASE +2)
8975 {"oabi", no_argument, NULL, OPTION_OABI},
8976 #endif
8977 #endif
8978 {NULL, no_argument, NULL, 0}
8981 size_t md_longopts_size = sizeof (md_longopts);
8984 md_parse_option (c, arg)
8985 int c;
8986 char * arg;
8988 char * str = arg;
8990 switch (c)
8992 #ifdef ARM_BI_ENDIAN
8993 case OPTION_EB:
8994 target_big_endian = 1;
8995 break;
8996 case OPTION_EL:
8997 target_big_endian = 0;
8998 break;
8999 #endif
9001 case 'm':
9002 switch (*str)
9004 case 'f':
9005 if (streq (str, "fpa10") || streq (str, "fpa11"))
9006 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_FPA;
9007 else if (streq (str, "fpe-old"))
9008 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_FPE;
9009 else
9010 goto bad;
9011 break;
9013 case 'n':
9014 if (streq (str, "no-fpu"))
9015 cpu_variant &= ~FPU_ANY;
9016 break;
9018 #ifdef OBJ_ELF
9019 case 'o':
9020 if (streq (str, "oabi"))
9021 target_oabi = true;
9022 break;
9023 #endif
9025 case 't':
9026 /* Limit assembler to generating only Thumb instructions: */
9027 if (streq (str, "thumb"))
9029 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_EXT_V4T;
9030 cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_NONE;
9031 thumb_mode = 1;
9033 else if (streq (str, "thumb-interwork"))
9035 if ((cpu_variant & ARM_EXT_V4T) == 0)
9036 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T;
9037 #if defined OBJ_COFF || defined OBJ_ELF
9038 support_interwork = true;
9039 #endif
9041 else
9042 goto bad;
9043 break;
9045 default:
9046 if (streq (str, "all"))
9048 cpu_variant = ARM_ALL | FPU_DEFAULT;
9049 return 1;
9051 #if defined OBJ_COFF || defined OBJ_ELF
9052 if (! strncmp (str, "apcs-", 5))
9054 /* GCC passes on all command line options starting "-mapcs-..."
9055 to us, so we must parse them here. */
9057 str += 5;
9059 if (streq (str, "32"))
9061 uses_apcs_26 = false;
9062 return 1;
9064 else if (streq (str, "26"))
9066 uses_apcs_26 = true;
9067 return 1;
9069 else if (streq (str, "frame"))
9071 /* Stack frames are being generated - does not affect
9072 linkage of code. */
9073 return 1;
9075 else if (streq (str, "stack-check"))
9077 /* Stack checking is being performed - does not affect
9078 linkage, but does require that the functions
9079 __rt_stkovf_split_small and __rt_stkovf_split_big be
9080 present in the final link. */
9082 return 1;
9084 else if (streq (str, "float"))
9086 /* Floating point arguments are being passed in the floating
9087 point registers. This does affect linking, since this
9088 version of the APCS is incompatible with the version that
9089 passes floating points in the integer registers. */
9091 uses_apcs_float = true;
9092 return 1;
9094 else if (streq (str, "reentrant"))
9096 /* Reentrant code has been generated. This does affect
9097 linking, since there is no point in linking reentrant/
9098 position independent code with absolute position code. */
9099 pic_code = true;
9100 return 1;
9103 as_bad (_("Unrecognised APCS switch -m%s"), arg);
9104 return 0;
9107 if (! strcmp (str, "atpcs"))
9109 atpcs = true;
9110 return 1;
9112 #endif
9113 /* Strip off optional "arm". */
9114 if (! strncmp (str, "arm", 3))
9115 str += 3;
9117 switch (*str)
9119 case '1':
9120 if (streq (str, "1"))
9121 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
9122 else
9123 goto bad;
9124 break;
9126 case '2':
9127 if (streq (str, "2"))
9128 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
9129 else if (streq (str, "250"))
9130 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
9131 else
9132 goto bad;
9133 break;
9135 case '3':
9136 if (streq (str, "3"))
9137 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
9138 else
9139 goto bad;
9140 break;
9142 case '6':
9143 switch (strtol (str, NULL, 10))
9145 case 6:
9146 case 60:
9147 case 600:
9148 case 610:
9149 case 620:
9150 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
9151 break;
9152 default:
9153 goto bad;
9155 break;
9157 case '7':
9158 /* Eat the processor name. */
9159 switch (strtol (str, & str, 10))
9161 case 7:
9162 case 70:
9163 case 700:
9164 case 710:
9165 case 720:
9166 case 7100:
9167 case 7500:
9168 break;
9169 default:
9170 goto bad;
9172 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
9173 for (; *str; str++)
9175 switch (*str)
9177 case 't':
9178 cpu_variant |= ARM_ARCH_V4T;
9179 break;
9181 case 'm':
9182 cpu_variant |= ARM_EXT_V3M;
9183 break;
9185 case 'f': /* fe => fp enabled cpu. */
9186 if (str[1] == 'e')
9187 ++ str;
9188 else
9189 goto bad;
9191 case 'c': /* Left over from 710c processor name. */
9192 case 'd': /* Debug. */
9193 case 'i': /* Embedded ICE. */
9194 /* Included for completeness in ARM processor naming. */
9195 break;
9197 default:
9198 goto bad;
9201 break;
9203 case '8':
9204 if (streq (str, "8") || streq (str, "810"))
9205 cpu_variant = (cpu_variant & ~ARM_ANY)
9206 | ARM_8 | ARM_ARCH_V4;
9207 else
9208 goto bad;
9209 break;
9211 case '9':
9212 if (streq (str, "9"))
9213 cpu_variant = (cpu_variant & ~ARM_ANY)
9214 | ARM_9 | ARM_ARCH_V4T;
9215 else if (streq (str, "920"))
9216 cpu_variant = (cpu_variant & ~ARM_ANY)
9217 | ARM_9 | ARM_ARCH_V4;
9218 else if (streq (str, "920t"))
9219 cpu_variant = (cpu_variant & ~ARM_ANY)
9220 | ARM_9 | ARM_ARCH_V4T;
9221 else if (streq (str, "9tdmi"))
9222 cpu_variant = (cpu_variant & ~ARM_ANY)
9223 | ARM_9 | ARM_ARCH_V4T;
9224 else if (streq (str, "9e"))
9225 cpu_variant = (cpu_variant & ~ARM_ANY)
9226 | ARM_9 | ARM_ARCH_V4T | ARM_EXT_MAVERICK;
9227 else
9228 goto bad;
9229 break;
9231 case 's':
9232 if (streq (str, "strongarm")
9233 || streq (str, "strongarm110")
9234 || streq (str, "strongarm1100"))
9235 cpu_variant = (cpu_variant & ~ARM_ANY)
9236 | ARM_8 | ARM_ARCH_V4;
9237 else
9238 goto bad;
9239 break;
9241 case 'x':
9242 if (streq (str, "xscale"))
9243 cpu_variant = (cpu_variant & ~ARM_ANY)
9244 | ARM_9 | ARM_ARCH_XSCALE;
9245 else
9246 goto bad;
9247 break;
9249 case 'v':
9250 /* Select variant based on architecture rather than
9251 processor. */
9252 switch (*++str)
9254 case '2':
9255 switch (*++str)
9257 case 'a':
9258 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
9259 break;
9260 case 0:
9261 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
9262 break;
9263 default:
9264 as_bad (_("Invalid architecture variant -m%s"), arg);
9265 break;
9267 break;
9269 case '3':
9270 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
9272 switch (*++str)
9274 case 'm': cpu_variant |= ARM_EXT_V3M; break;
9275 case 0: break;
9276 default:
9277 as_bad (_("Invalid architecture variant -m%s"), arg);
9278 break;
9280 break;
9282 case '4':
9283 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCH_V4;
9285 switch (*++str)
9287 case 't': cpu_variant |= ARM_EXT_V4T; break;
9288 case 0: break;
9289 default:
9290 as_bad (_("Invalid architecture variant -m%s"), arg);
9291 break;
9293 break;
9295 case '5':
9296 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V5;
9297 switch (*++str)
9299 case 't': cpu_variant |= ARM_EXT_V4T; break;
9300 case 'e': cpu_variant |= ARM_EXT_V5E; break;
9301 case 0: break;
9302 default:
9303 as_bad (_("Invalid architecture variant -m%s"), arg);
9304 break;
9306 break;
9308 default:
9309 as_bad (_("Invalid architecture variant -m%s"), arg);
9310 break;
9312 break;
9314 default:
9315 bad:
9316 as_bad (_("Invalid processor variant -m%s"), arg);
9317 return 0;
9320 break;
9322 #if defined OBJ_ELF || defined OBJ_COFF
9323 case 'k':
9324 pic_code = 1;
9325 break;
9326 #endif
9328 default:
9329 return 0;
9332 return 1;
9335 void
9336 md_show_usage (fp)
9337 FILE * fp;
9339 fprintf (fp, _("\
9340 ARM Specific Assembler Options:\n\
9341 -m[arm][<processor name>] select processor variant\n\
9342 -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
9343 -marm9e allow Cirrus/DSP instructions\n\
9344 -mthumb only allow Thumb instructions\n\
9345 -mthumb-interwork mark the assembled code as supporting interworking\n\
9346 -mall allow any instruction\n\
9347 -mfpa10, -mfpa11 select floating point architecture\n\
9348 -mfpe-old don't allow floating-point multiple instructions\n\
9349 -mno-fpu don't allow any floating-point instructions.\n\
9350 -k generate PIC code.\n"));
9351 #if defined OBJ_COFF || defined OBJ_ELF
9352 fprintf (fp, _("\
9353 -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n\
9354 -matpcs use ARM/Thumb Procedure Calling Standard\n\
9355 -mapcs-float floating point args are passed in FP regs\n\
9356 -mapcs-reentrant the code is position independent/reentrant\n"));
9357 #endif
9358 #ifdef OBJ_ELF
9359 fprintf (fp, _("\
9360 -moabi support the old ELF ABI\n"));
9361 #endif
9362 #ifdef ARM_BI_ENDIAN
9363 fprintf (fp, _("\
9364 -EB assemble code for a big endian cpu\n\
9365 -EL assemble code for a little endian cpu\n"));
9366 #endif
9369 /* We need to be able to fix up arbitrary expressions in some statements.
9370 This is so that we can handle symbols that are an arbitrary distance from
9371 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
9372 which returns part of an address in a form which will be valid for
9373 a data instruction. We do this by pushing the expression into a symbol
9374 in the expr_section, and creating a fix for that. */
9376 static void
9377 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
9378 fragS * frag;
9379 int where;
9380 short int size;
9381 expressionS * exp;
9382 int pc_rel;
9383 int reloc;
9385 fixS * new_fix;
9386 arm_fix_data * arm_data;
9388 switch (exp->X_op)
9390 case O_constant:
9391 case O_symbol:
9392 case O_add:
9393 case O_subtract:
9394 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
9395 break;
9397 default:
9398 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
9399 pc_rel, reloc);
9400 break;
9403 /* Mark whether the fix is to a THUMB instruction, or an ARM
9404 instruction. */
9405 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
9406 new_fix->tc_fix_data = (PTR) arm_data;
9407 arm_data->thumb_mode = thumb_mode;
9409 return;
9412 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
9414 void
9415 cons_fix_new_arm (frag, where, size, exp)
9416 fragS * frag;
9417 int where;
9418 int size;
9419 expressionS * exp;
9421 bfd_reloc_code_real_type type;
9422 int pcrel = 0;
9424 /* Pick a reloc.
9425 FIXME: @@ Should look at CPU word size. */
9426 switch (size)
9428 case 1:
9429 type = BFD_RELOC_8;
9430 break;
9431 case 2:
9432 type = BFD_RELOC_16;
9433 break;
9434 case 4:
9435 default:
9436 type = BFD_RELOC_32;
9437 break;
9438 case 8:
9439 type = BFD_RELOC_64;
9440 break;
9443 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
9446 /* A good place to do this, although this was probably not intended
9447 for this kind of use. We need to dump the literal pool before
9448 references are made to a null symbol pointer. */
9450 void
9451 arm_cleanup ()
9453 if (current_poolP == NULL)
9454 return;
9456 /* Put it at the end of text section. */
9457 subseg_set (text_section, 0);
9458 s_ltorg (0);
9459 listing_prev_line ();
9462 void
9463 arm_start_line_hook ()
9465 last_label_seen = NULL;
9468 void
9469 arm_frob_label (sym)
9470 symbolS * sym;
9472 last_label_seen = sym;
9474 ARM_SET_THUMB (sym, thumb_mode);
9476 #if defined OBJ_COFF || defined OBJ_ELF
9477 ARM_SET_INTERWORK (sym, support_interwork);
9478 #endif
9480 /* Note - do not allow local symbols (.Lxxx) to be labeled
9481 as Thumb functions. This is because these labels, whilst
9482 they exist inside Thumb code, are not the entry points for
9483 possible ARM->Thumb calls. Also, these labels can be used
9484 as part of a computed goto or switch statement. eg gcc
9485 can generate code that looks like this:
9487 ldr r2, [pc, .Laaa]
9488 lsl r3, r3, #2
9489 ldr r2, [r3, r2]
9490 mov pc, r2
9492 .Lbbb: .word .Lxxx
9493 .Lccc: .word .Lyyy
9494 ..etc...
9495 .Laaa: .word Lbbb
9497 The first instruction loads the address of the jump table.
9498 The second instruction converts a table index into a byte offset.
9499 The third instruction gets the jump address out of the table.
9500 The fourth instruction performs the jump.
9502 If the address stored at .Laaa is that of a symbol which has the
9503 Thumb_Func bit set, then the linker will arrange for this address
9504 to have the bottom bit set, which in turn would mean that the
9505 address computation performed by the third instruction would end
9506 up with the bottom bit set. Since the ARM is capable of unaligned
9507 word loads, the instruction would then load the incorrect address
9508 out of the jump table, and chaos would ensue. */
9509 if (label_is_thumb_function_name
9510 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
9511 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
9513 /* When the address of a Thumb function is taken the bottom
9514 bit of that address should be set. This will allow
9515 interworking between Arm and Thumb functions to work
9516 correctly. */
9518 THUMB_SET_FUNC (sym, 1);
9520 label_is_thumb_function_name = false;
9524 /* Adjust the symbol table. This marks Thumb symbols as distinct from
9525 ARM ones. */
9527 void
9528 arm_adjust_symtab ()
9530 #ifdef OBJ_COFF
9531 symbolS * sym;
9533 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9535 if (ARM_IS_THUMB (sym))
9537 if (THUMB_IS_FUNC (sym))
9539 /* Mark the symbol as a Thumb function. */
9540 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
9541 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
9542 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
9544 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
9545 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
9546 else
9547 as_bad (_("%s: unexpected function type: %d"),
9548 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
9550 else switch (S_GET_STORAGE_CLASS (sym))
9552 case C_EXT:
9553 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
9554 break;
9555 case C_STAT:
9556 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
9557 break;
9558 case C_LABEL:
9559 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
9560 break;
9561 default:
9562 /* Do nothing. */
9563 break;
9567 if (ARM_IS_INTERWORK (sym))
9568 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
9570 #endif
9571 #ifdef OBJ_ELF
9572 symbolS * sym;
9573 char bind;
9575 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9577 if (ARM_IS_THUMB (sym))
9579 elf_symbol_type * elf_sym;
9581 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
9582 bind = ELF_ST_BIND (elf_sym);
9584 /* If it's a .thumb_func, declare it as so,
9585 otherwise tag label as .code 16. */
9586 if (THUMB_IS_FUNC (sym))
9587 elf_sym->internal_elf_sym.st_info =
9588 ELF_ST_INFO (bind, STT_ARM_TFUNC);
9589 else
9590 elf_sym->internal_elf_sym.st_info =
9591 ELF_ST_INFO (bind, STT_ARM_16BIT);
9594 #endif
9598 arm_data_in_code ()
9600 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
9602 *input_line_pointer = '/';
9603 input_line_pointer += 5;
9604 *input_line_pointer = 0;
9605 return 1;
9608 return 0;
9611 char *
9612 arm_canonicalize_symbol_name (name)
9613 char * name;
9615 int len;
9617 if (thumb_mode && (len = strlen (name)) > 5
9618 && streq (name + len - 5, "/data"))
9619 *(name + len - 5) = 0;
9621 return name;
9624 boolean
9625 arm_validate_fix (fixP)
9626 fixS * fixP;
9628 /* If the destination of the branch is a defined symbol which does not have
9629 the THUMB_FUNC attribute, then we must be calling a function which has
9630 the (interfacearm) attribute. We look for the Thumb entry point to that
9631 function and change the branch to refer to that function instead. */
9632 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
9633 && fixP->fx_addsy != NULL
9634 && S_IS_DEFINED (fixP->fx_addsy)
9635 && ! THUMB_IS_FUNC (fixP->fx_addsy))
9637 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
9638 return true;
9641 return false;
9644 #ifdef OBJ_COFF
9645 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
9646 local labels from being added to the output symbol table when they
9647 are used with the ADRL pseudo op. The ADRL relocation should always
9648 be resolved before the binbary is emitted, so it is safe to say that
9649 it is adjustable. */
9651 boolean
9652 arm_fix_adjustable (fixP)
9653 fixS * fixP;
9655 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
9656 return 1;
9657 return 0;
9659 #endif
9660 #ifdef OBJ_ELF
9661 /* Relocations against Thumb function names must be left unadjusted,
9662 so that the linker can use this information to correctly set the
9663 bottom bit of their addresses. The MIPS version of this function
9664 also prevents relocations that are mips-16 specific, but I do not
9665 know why it does this.
9667 FIXME:
9668 There is one other problem that ought to be addressed here, but
9669 which currently is not: Taking the address of a label (rather
9670 than a function) and then later jumping to that address. Such
9671 addresses also ought to have their bottom bit set (assuming that
9672 they reside in Thumb code), but at the moment they will not. */
9674 boolean
9675 arm_fix_adjustable (fixP)
9676 fixS * fixP;
9678 if (fixP->fx_addsy == NULL)
9679 return 1;
9681 /* Prevent all adjustments to global symbols. */
9682 if (S_IS_EXTERN (fixP->fx_addsy))
9683 return 0;
9685 if (S_IS_WEAK (fixP->fx_addsy))
9686 return 0;
9688 if (THUMB_IS_FUNC (fixP->fx_addsy)
9689 && fixP->fx_subsy == NULL)
9690 return 0;
9692 /* We need the symbol name for the VTABLE entries. */
9693 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
9694 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
9695 return 0;
9697 return 1;
9700 const char *
9701 elf32_arm_target_format ()
9703 if (target_big_endian)
9705 if (target_oabi)
9706 return "elf32-bigarm-oabi";
9707 else
9708 return "elf32-bigarm";
9710 else
9712 if (target_oabi)
9713 return "elf32-littlearm-oabi";
9714 else
9715 return "elf32-littlearm";
9719 void
9720 armelf_frob_symbol (symp, puntp)
9721 symbolS * symp;
9722 int * puntp;
9724 elf_frob_symbol (symp, puntp);
9728 arm_force_relocation (fixp)
9729 struct fix * fixp;
9731 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
9732 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
9733 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
9734 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
9735 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
9736 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
9737 return 1;
9739 return 0;
9742 static bfd_reloc_code_real_type
9743 arm_parse_reloc ()
9745 char id [16];
9746 char * ip;
9747 unsigned int i;
9748 static struct
9750 char * str;
9751 int len;
9752 bfd_reloc_code_real_type reloc;
9754 reloc_map[] =
9756 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
9757 MAP ("(got)", BFD_RELOC_ARM_GOT32),
9758 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
9759 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
9760 branch instructions generated by GCC for PLT relocs. */
9761 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
9762 { NULL, 0, BFD_RELOC_UNUSED }
9763 #undef MAP
9766 for (i = 0, ip = input_line_pointer;
9767 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
9768 i++, ip++)
9769 id[i] = TOLOWER (*ip);
9771 for (i = 0; reloc_map[i].str; i++)
9772 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
9773 break;
9775 input_line_pointer += reloc_map[i].len;
9777 return reloc_map[i].reloc;
9780 static void
9781 s_arm_elf_cons (nbytes)
9782 int nbytes;
9784 expressionS exp;
9786 #ifdef md_flush_pending_output
9787 md_flush_pending_output ();
9788 #endif
9790 if (is_it_end_of_statement ())
9792 demand_empty_rest_of_line ();
9793 return;
9796 #ifdef md_cons_align
9797 md_cons_align (nbytes);
9798 #endif
9802 bfd_reloc_code_real_type reloc;
9804 expression (& exp);
9806 if (exp.X_op == O_symbol
9807 && * input_line_pointer == '('
9808 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
9810 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
9811 int size = bfd_get_reloc_size (howto);
9813 if (size > nbytes)
9814 as_bad ("%s relocations do not fit in %d bytes",
9815 howto->name, nbytes);
9816 else
9818 register char *p = frag_more ((int) nbytes);
9819 int offset = nbytes - size;
9821 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
9822 &exp, 0, reloc);
9825 else
9826 emit_expr (&exp, (unsigned int) nbytes);
9828 while (*input_line_pointer++ == ',');
9830 /* Put terminator back into stream. */
9831 input_line_pointer --;
9832 demand_empty_rest_of_line ();
9835 #endif /* OBJ_ELF */
9837 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
9838 of an rs_align_code fragment. */
9840 void
9841 arm_handle_align (fragP)
9842 fragS *fragP;
9844 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
9845 static char const thumb_noop[2] = { 0xc0, 0x46 };
9846 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
9847 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
9849 int bytes, fix, noop_size;
9850 char * p;
9851 const char * noop;
9853 if (fragP->fr_type != rs_align_code)
9854 return;
9856 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
9857 p = fragP->fr_literal + fragP->fr_fix;
9858 fix = 0;
9860 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
9861 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
9863 if (fragP->tc_frag_data)
9865 if (target_big_endian)
9866 noop = thumb_bigend_noop;
9867 else
9868 noop = thumb_noop;
9869 noop_size = sizeof (thumb_noop);
9871 else
9873 if (target_big_endian)
9874 noop = arm_bigend_noop;
9875 else
9876 noop = arm_noop;
9877 noop_size = sizeof (arm_noop);
9880 if (bytes & (noop_size - 1))
9882 fix = bytes & (noop_size - 1);
9883 memset (p, 0, fix);
9884 p += fix;
9885 bytes -= fix;
9888 while (bytes >= noop_size)
9890 memcpy (p, noop, noop_size);
9891 p += noop_size;
9892 bytes -= noop_size;
9893 fix += noop_size;
9896 fragP->fr_fix += fix;
9897 fragP->fr_var = noop_size;
9900 /* Called from md_do_align. Used to create an alignment
9901 frag in a code section. */
9903 void
9904 arm_frag_align_code (n, max)
9905 int n;
9906 int max;
9908 char * p;
9910 /* We assume that there will never be a requirment
9911 to support alignments greater than 32 bytes. */
9912 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
9913 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
9915 p = frag_var (rs_align_code,
9916 MAX_MEM_FOR_RS_ALIGN_CODE,
9918 (relax_substateT) max,
9919 (symbolS *) NULL,
9920 (offsetT) n,
9921 (char *) NULL);
9922 *p = 0;
9926 /* Perform target specific initialisation of a frag. */
9928 void
9929 arm_init_frag (fragP)
9930 fragS *fragP;
9932 /* Record whether this frag is in an ARM or a THUMB area. */
9933 fragP->tc_frag_data = thumb_mode;