]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
Fix formatting
[thirdparty/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef
NC
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)
22d9c8c5 6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
b99bd4ef
NC
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
b99bd4ef
NC
25#include <string.h>
26#define NO_RELOC 0
27#include "as.h"
3882b010 28#include "safe-ctype.h"
b99bd4ef
NC
29
30/* Need TARGET_CPU. */
31#include "config.h"
32#include "subsegs.h"
33#include "obstack.h"
34#include "symbols.h"
35#include "listing.h"
36
37#ifdef OBJ_ELF
38#include "elf/arm.h"
39#include "dwarf2dbg.h"
40#endif
41
42/* Types of processor to assemble for. */
43#define ARM_1 0x00000001
44#define ARM_2 0x00000002
45#define ARM_3 0x00000004
46#define ARM_250 ARM_3
47#define ARM_6 0x00000008
48#define ARM_7 ARM_6 /* Same core instruction set. */
49#define ARM_8 ARM_6 /* Same core instruction set. */
50#define ARM_9 ARM_6 /* Same core instruction set. */
51#define ARM_CPU_MASK 0x0000000f
52
53/* The following bitmasks control CPU extensions (ARM7 onwards): */
54#define ARM_EXT_LONGMUL 0x00000010 /* Allow long multiplies. */
55#define ARM_EXT_HALFWORD 0x00000020 /* Allow half word loads. */
56#define ARM_EXT_THUMB 0x00000040 /* Allow BX instruction. */
57#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
58#define ARM_EXT_V5E 0x00000100 /* "El Segundo". */
59#define ARM_EXT_XSCALE 0x00000200 /* Allow MIA etc. */
90f9b791 60#define ARM_EXT_MAVERICK 0x00000400 /* Use Cirrus/DSP coprocessor. */
b99bd4ef
NC
61
62/* Architectures are the sum of the base and extensions. */
63#define ARM_ARCH_V3M ARM_EXT_LONGMUL
64#define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_HALFWORD)
65#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_THUMB)
66#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
67#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_THUMB)
68#define ARM_ARCH_V5TE (ARM_ARCH_V5T | ARM_EXT_V5E)
69#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_EXT_XSCALE)
70
71/* Some useful combinations: */
72#define ARM_ANY 0x00ffffff
73#define ARM_2UP (ARM_ANY - ARM_1)
74#define ARM_ALL ARM_2UP /* Not arm1 only. */
75#define ARM_3UP 0x00fffffc
76#define ARM_6UP 0x00fffff8 /* Includes ARM7. */
77
78#define FPU_CORE 0x80000000
79#define FPU_FPA10 0x40000000
80#define FPU_FPA11 0x40000000
81#define FPU_NONE 0
82
83/* Some useful combinations. */
84#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY. */
85#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core. */
86
87#ifndef CPU_DEFAULT
88#if defined __XSCALE__
89#define CPU_DEFAULT (ARM_9 | ARM_ARCH_XSCALE)
90#else
91#if defined __thumb__
92#define CPU_DEFAULT (ARM_7 | ARM_ARCH_V4T)
93#else
94#define CPU_DEFAULT ARM_ALL
95#endif
96#endif
97#endif
98
99#ifndef FPU_DEFAULT
100#define FPU_DEFAULT FPU_ALL
101#endif
102
103#define streq(a, b) (strcmp (a, b) == 0)
104#define skip_whitespace(str) while (*(str) == ' ') ++(str)
105
106static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
107static int target_oabi = 0;
108
109#if defined OBJ_COFF || defined OBJ_ELF
110/* Flags stored in private area of BFD structure. */
111static boolean uses_apcs_26 = false;
112static boolean atpcs = false;
113static boolean support_interwork = false;
114static boolean uses_apcs_float = false;
115static boolean pic_code = false;
116#endif
117
118/* This array holds the chars that always start a comment. If the
119 pre-processor is disabled, these aren't very useful. */
120CONST char comment_chars[] = "@";
121
122/* This array holds the chars that only start a comment at the beginning of
123 a line. If the line seems to have the form '# 123 filename'
124 .line and .file directives will appear in the pre-processed output. */
125/* Note that input_file.c hand checks for '#' at the beginning of the
126 first line of the input file. This is because the compiler outputs
127 #NO_APP at the beginning of its output. */
128/* Also note that comments like this one will always work. */
129CONST char line_comment_chars[] = "#";
130
131CONST char line_separator_chars[] = ";";
132
133/* Chars that can be used to separate mant
134 from exp in floating point numbers. */
135CONST char EXP_CHARS[] = "eE";
136
137/* Chars that mean this number is a floating point constant. */
138/* As in 0f12.456 */
139/* or 0d1.2345e12 */
140
141CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
142
143/* Prefix characters that indicate the start of an immediate
144 value. */
145#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
146
147#ifdef OBJ_ELF
148/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
149symbolS * GOT_symbol;
150#endif
151
152/* Size of relocation record. */
153CONST int md_reloc_size = 8;
154
155/* 0: assemble for ARM,
156 1: assemble for Thumb,
157 2: assemble for Thumb even though target CPU does not support thumb
158 instructions. */
159static int thumb_mode = 0;
160
161typedef struct arm_fix
162{
163 int thumb_mode;
164} arm_fix_data;
165
166struct arm_it
167{
168 CONST char * error;
169 unsigned long instruction;
170 int suffix;
171 int size;
172 struct
173 {
174 bfd_reloc_code_real_type type;
175 expressionS exp;
176 int pc_rel;
177 } reloc;
178};
179
180struct arm_it inst;
181
182enum asm_shift_index
183{
184 SHIFT_LSL = 0,
185 SHIFT_LSR,
186 SHIFT_ASR,
187 SHIFT_ROR,
188 SHIFT_RRX
189};
190
191struct asm_shift_properties
192{
193 enum asm_shift_index index;
194 unsigned long bit_field;
195 unsigned int allows_0 : 1;
196 unsigned int allows_32 : 1;
197};
198
199static const struct asm_shift_properties shift_properties [] =
200{
201 { SHIFT_LSL, 0, 1, 0},
202 { SHIFT_LSR, 0x20, 0, 1},
203 { SHIFT_ASR, 0x40, 0, 1},
204 { SHIFT_ROR, 0x60, 0, 0},
205 { SHIFT_RRX, 0x60, 0, 0}
206};
207
208struct asm_shift_name
209{
210 const char * name;
211 const struct asm_shift_properties * properties;
212};
213
214static const struct asm_shift_name shift_names [] =
215{
216 { "asl", shift_properties + SHIFT_LSL },
217 { "lsl", shift_properties + SHIFT_LSL },
218 { "lsr", shift_properties + SHIFT_LSR },
219 { "asr", shift_properties + SHIFT_ASR },
220 { "ror", shift_properties + SHIFT_ROR },
221 { "rrx", shift_properties + SHIFT_RRX },
222 { "ASL", shift_properties + SHIFT_LSL },
223 { "LSL", shift_properties + SHIFT_LSL },
224 { "LSR", shift_properties + SHIFT_LSR },
225 { "ASR", shift_properties + SHIFT_ASR },
226 { "ROR", shift_properties + SHIFT_ROR },
227 { "RRX", shift_properties + SHIFT_RRX }
228};
229
230#define NO_SHIFT_RESTRICT 1
231#define SHIFT_RESTRICT 0
232
233#define NUM_FLOAT_VALS 8
234
235CONST char * fp_const[] =
236{
237 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
238};
239
240/* Number of littlenums required to hold an extended precision number. */
241#define MAX_LITTLENUMS 6
242
243LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
244
245#define FAIL (-1)
246#define SUCCESS (0)
247
248#define SUFF_S 1
249#define SUFF_D 2
250#define SUFF_E 3
251#define SUFF_P 4
252
253#define CP_T_X 0x00008000
254#define CP_T_Y 0x00400000
255#define CP_T_Pre 0x01000000
256#define CP_T_UD 0x00800000
257#define CP_T_WB 0x00200000
258
259#define CONDS_BIT 0x00100000
260#define LOAD_BIT 0x00100000
261#define TRANS_BIT 0x00200000
262
263#define DOUBLE_LOAD_FLAG 0x00000001
264
265struct asm_cond
266{
267 CONST char * template;
268 unsigned long value;
269};
270
271/* This is to save a hash look-up in the common case. */
272#define COND_ALWAYS 0xe0000000
273
274static CONST struct asm_cond conds[] =
275{
276 {"eq", 0x00000000},
277 {"ne", 0x10000000},
278 {"cs", 0x20000000}, {"hs", 0x20000000},
279 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
280 {"mi", 0x40000000},
281 {"pl", 0x50000000},
282 {"vs", 0x60000000},
283 {"vc", 0x70000000},
284 {"hi", 0x80000000},
285 {"ls", 0x90000000},
286 {"ge", 0xa0000000},
287 {"lt", 0xb0000000},
288 {"gt", 0xc0000000},
289 {"le", 0xd0000000},
290 {"al", 0xe0000000},
291 {"nv", 0xf0000000}
292};
293
294/* Warning: If the top bit of the set_bits is set, then the standard
295 instruction bitmask is ignored, and the new bitmask is taken from
296 the set_bits: */
297struct asm_flg
298{
299 CONST char * template; /* Basic flag string. */
300 unsigned long set_bits; /* Bits to set. */
301};
302
303static CONST struct asm_flg s_flag[] =
304{
305 {"s", CONDS_BIT},
306 {NULL, 0}
307};
308
309static CONST struct asm_flg ldr_flags[] =
310{
311 {"d", DOUBLE_LOAD_FLAG},
312 {"b", 0x00400000},
313 {"t", TRANS_BIT},
314 {"bt", 0x00400000 | TRANS_BIT},
315 {"h", 0x801000b0},
316 {"sh", 0x801000f0},
317 {"sb", 0x801000d0},
318 {NULL, 0}
319};
320
321static CONST struct asm_flg str_flags[] =
322{
323 {"d", DOUBLE_LOAD_FLAG},
324 {"b", 0x00400000},
325 {"t", TRANS_BIT},
326 {"bt", 0x00400000 | TRANS_BIT},
327 {"h", 0x800000b0},
328 {NULL, 0}
329};
330
331static CONST struct asm_flg byte_flag[] =
332{
333 {"b", 0x00400000},
334 {NULL, 0}
335};
336
337static CONST struct asm_flg cmp_flags[] =
338{
339 {"s", CONDS_BIT},
340 {"p", 0x0010f000},
341 {NULL, 0}
342};
343
344static CONST struct asm_flg ldm_flags[] =
345{
346 {"ed", 0x01800000},
347 {"fd", 0x00800000},
348 {"ea", 0x01000000},
349 {"fa", 0x00000000},
350 {"ib", 0x01800000},
351 {"ia", 0x00800000},
352 {"db", 0x01000000},
353 {"da", 0x00000000},
354 {NULL, 0}
355};
356
357static CONST struct asm_flg stm_flags[] =
358{
359 {"ed", 0x00000000},
360 {"fd", 0x01000000},
361 {"ea", 0x00800000},
362 {"fa", 0x01800000},
363 {"ib", 0x01800000},
364 {"ia", 0x00800000},
365 {"db", 0x01000000},
366 {"da", 0x00000000},
367 {NULL, 0}
368};
369
370static CONST struct asm_flg lfm_flags[] =
371{
372 {"fd", 0x00800000},
373 {"ea", 0x01000000},
374 {NULL, 0}
375};
376
377static CONST struct asm_flg sfm_flags[] =
378{
379 {"fd", 0x01000000},
380 {"ea", 0x00800000},
381 {NULL, 0}
382};
383
384static CONST struct asm_flg round_flags[] =
385{
386 {"p", 0x00000020},
387 {"m", 0x00000040},
388 {"z", 0x00000060},
389 {NULL, 0}
390};
391
392/* The implementation of the FIX instruction is broken on some assemblers,
393 in that it accepts a precision specifier as well as a rounding specifier,
394 despite the fact that this is meaningless. To be more compatible, we
395 accept it as well, though of course it does not set any bits. */
396static CONST struct asm_flg fix_flags[] =
397{
398 {"p", 0x00000020},
399 {"m", 0x00000040},
400 {"z", 0x00000060},
401 {"sp", 0x00000020},
402 {"sm", 0x00000040},
403 {"sz", 0x00000060},
404 {"dp", 0x00000020},
405 {"dm", 0x00000040},
406 {"dz", 0x00000060},
407 {"ep", 0x00000020},
408 {"em", 0x00000040},
409 {"ez", 0x00000060},
410 {NULL, 0}
411};
412
413static CONST struct asm_flg except_flag[] =
414{
415 {"e", 0x00400000},
416 {NULL, 0}
417};
418
1cac9012 419static CONST struct asm_flg long_flag[] =
b99bd4ef
NC
420{
421 {"l", 0x00400000},
422 {NULL, 0}
423};
424
425struct asm_psr
426{
427 CONST char * template;
428 boolean cpsr;
429 unsigned long field;
430};
431
432/* The bit that distnguishes CPSR and SPSR. */
433#define SPSR_BIT (1 << 22)
434
435/* How many bits to shift the PSR_xxx bits up by. */
436#define PSR_SHIFT 16
437
438#define PSR_c (1 << 0)
439#define PSR_x (1 << 1)
440#define PSR_s (1 << 2)
441#define PSR_f (1 << 3)
442
443static CONST struct asm_psr psrs[] =
444{
445 {"CPSR", true, PSR_c | PSR_f},
446 {"CPSR_all", true, PSR_c | PSR_f},
447 {"SPSR", false, PSR_c | PSR_f},
448 {"SPSR_all", false, PSR_c | PSR_f},
449 {"CPSR_flg", true, PSR_f},
450 {"CPSR_f", true, PSR_f},
451 {"SPSR_flg", false, PSR_f},
452 {"SPSR_f", false, PSR_f},
453 {"CPSR_c", true, PSR_c},
454 {"CPSR_ctl", true, PSR_c},
455 {"SPSR_c", false, PSR_c},
456 {"SPSR_ctl", false, PSR_c},
457 {"CPSR_x", true, PSR_x},
458 {"CPSR_s", true, PSR_s},
459 {"SPSR_x", false, PSR_x},
460 {"SPSR_s", false, PSR_s},
461 /* Combinations of flags. */
462 {"CPSR_fs", true, PSR_f | PSR_s},
463 {"CPSR_fx", true, PSR_f | PSR_x},
464 {"CPSR_fc", true, PSR_f | PSR_c},
465 {"CPSR_sf", true, PSR_s | PSR_f},
466 {"CPSR_sx", true, PSR_s | PSR_x},
467 {"CPSR_sc", true, PSR_s | PSR_c},
468 {"CPSR_xf", true, PSR_x | PSR_f},
469 {"CPSR_xs", true, PSR_x | PSR_s},
470 {"CPSR_xc", true, PSR_x | PSR_c},
471 {"CPSR_cf", true, PSR_c | PSR_f},
472 {"CPSR_cs", true, PSR_c | PSR_s},
473 {"CPSR_cx", true, PSR_c | PSR_x},
474 {"CPSR_fsx", true, PSR_f | PSR_s | PSR_x},
475 {"CPSR_fsc", true, PSR_f | PSR_s | PSR_c},
476 {"CPSR_fxs", true, PSR_f | PSR_x | PSR_s},
477 {"CPSR_fxc", true, PSR_f | PSR_x | PSR_c},
478 {"CPSR_fcs", true, PSR_f | PSR_c | PSR_s},
479 {"CPSR_fcx", true, PSR_f | PSR_c | PSR_x},
480 {"CPSR_sfx", true, PSR_s | PSR_f | PSR_x},
481 {"CPSR_sfc", true, PSR_s | PSR_f | PSR_c},
482 {"CPSR_sxf", true, PSR_s | PSR_x | PSR_f},
483 {"CPSR_sxc", true, PSR_s | PSR_x | PSR_c},
484 {"CPSR_scf", true, PSR_s | PSR_c | PSR_f},
485 {"CPSR_scx", true, PSR_s | PSR_c | PSR_x},
486 {"CPSR_xfs", true, PSR_x | PSR_f | PSR_s},
487 {"CPSR_xfc", true, PSR_x | PSR_f | PSR_c},
488 {"CPSR_xsf", true, PSR_x | PSR_s | PSR_f},
489 {"CPSR_xsc", true, PSR_x | PSR_s | PSR_c},
490 {"CPSR_xcf", true, PSR_x | PSR_c | PSR_f},
491 {"CPSR_xcs", true, PSR_x | PSR_c | PSR_s},
492 {"CPSR_cfs", true, PSR_c | PSR_f | PSR_s},
493 {"CPSR_cfx", true, PSR_c | PSR_f | PSR_x},
494 {"CPSR_csf", true, PSR_c | PSR_s | PSR_f},
495 {"CPSR_csx", true, PSR_c | PSR_s | PSR_x},
496 {"CPSR_cxf", true, PSR_c | PSR_x | PSR_f},
497 {"CPSR_cxs", true, PSR_c | PSR_x | PSR_s},
498 {"CPSR_fsxc", true, PSR_f | PSR_s | PSR_x | PSR_c},
499 {"CPSR_fscx", true, PSR_f | PSR_s | PSR_c | PSR_x},
500 {"CPSR_fxsc", true, PSR_f | PSR_x | PSR_s | PSR_c},
501 {"CPSR_fxcs", true, PSR_f | PSR_x | PSR_c | PSR_s},
502 {"CPSR_fcsx", true, PSR_f | PSR_c | PSR_s | PSR_x},
503 {"CPSR_fcxs", true, PSR_f | PSR_c | PSR_x | PSR_s},
504 {"CPSR_sfxc", true, PSR_s | PSR_f | PSR_x | PSR_c},
505 {"CPSR_sfcx", true, PSR_s | PSR_f | PSR_c | PSR_x},
506 {"CPSR_sxfc", true, PSR_s | PSR_x | PSR_f | PSR_c},
507 {"CPSR_sxcf", true, PSR_s | PSR_x | PSR_c | PSR_f},
508 {"CPSR_scfx", true, PSR_s | PSR_c | PSR_f | PSR_x},
509 {"CPSR_scxf", true, PSR_s | PSR_c | PSR_x | PSR_f},
510 {"CPSR_xfsc", true, PSR_x | PSR_f | PSR_s | PSR_c},
511 {"CPSR_xfcs", true, PSR_x | PSR_f | PSR_c | PSR_s},
512 {"CPSR_xsfc", true, PSR_x | PSR_s | PSR_f | PSR_c},
513 {"CPSR_xscf", true, PSR_x | PSR_s | PSR_c | PSR_f},
514 {"CPSR_xcfs", true, PSR_x | PSR_c | PSR_f | PSR_s},
515 {"CPSR_xcsf", true, PSR_x | PSR_c | PSR_s | PSR_f},
516 {"CPSR_cfsx", true, PSR_c | PSR_f | PSR_s | PSR_x},
517 {"CPSR_cfxs", true, PSR_c | PSR_f | PSR_x | PSR_s},
518 {"CPSR_csfx", true, PSR_c | PSR_s | PSR_f | PSR_x},
519 {"CPSR_csxf", true, PSR_c | PSR_s | PSR_x | PSR_f},
520 {"CPSR_cxfs", true, PSR_c | PSR_x | PSR_f | PSR_s},
521 {"CPSR_cxsf", true, PSR_c | PSR_x | PSR_s | PSR_f},
522 {"SPSR_fs", false, PSR_f | PSR_s},
523 {"SPSR_fx", false, PSR_f | PSR_x},
524 {"SPSR_fc", false, PSR_f | PSR_c},
525 {"SPSR_sf", false, PSR_s | PSR_f},
526 {"SPSR_sx", false, PSR_s | PSR_x},
527 {"SPSR_sc", false, PSR_s | PSR_c},
528 {"SPSR_xf", false, PSR_x | PSR_f},
529 {"SPSR_xs", false, PSR_x | PSR_s},
530 {"SPSR_xc", false, PSR_x | PSR_c},
531 {"SPSR_cf", false, PSR_c | PSR_f},
532 {"SPSR_cs", false, PSR_c | PSR_s},
533 {"SPSR_cx", false, PSR_c | PSR_x},
534 {"SPSR_fsx", false, PSR_f | PSR_s | PSR_x},
535 {"SPSR_fsc", false, PSR_f | PSR_s | PSR_c},
536 {"SPSR_fxs", false, PSR_f | PSR_x | PSR_s},
537 {"SPSR_fxc", false, PSR_f | PSR_x | PSR_c},
538 {"SPSR_fcs", false, PSR_f | PSR_c | PSR_s},
539 {"SPSR_fcx", false, PSR_f | PSR_c | PSR_x},
540 {"SPSR_sfx", false, PSR_s | PSR_f | PSR_x},
541 {"SPSR_sfc", false, PSR_s | PSR_f | PSR_c},
542 {"SPSR_sxf", false, PSR_s | PSR_x | PSR_f},
543 {"SPSR_sxc", false, PSR_s | PSR_x | PSR_c},
544 {"SPSR_scf", false, PSR_s | PSR_c | PSR_f},
545 {"SPSR_scx", false, PSR_s | PSR_c | PSR_x},
546 {"SPSR_xfs", false, PSR_x | PSR_f | PSR_s},
547 {"SPSR_xfc", false, PSR_x | PSR_f | PSR_c},
548 {"SPSR_xsf", false, PSR_x | PSR_s | PSR_f},
549 {"SPSR_xsc", false, PSR_x | PSR_s | PSR_c},
550 {"SPSR_xcf", false, PSR_x | PSR_c | PSR_f},
551 {"SPSR_xcs", false, PSR_x | PSR_c | PSR_s},
552 {"SPSR_cfs", false, PSR_c | PSR_f | PSR_s},
553 {"SPSR_cfx", false, PSR_c | PSR_f | PSR_x},
554 {"SPSR_csf", false, PSR_c | PSR_s | PSR_f},
555 {"SPSR_csx", false, PSR_c | PSR_s | PSR_x},
556 {"SPSR_cxf", false, PSR_c | PSR_x | PSR_f},
557 {"SPSR_cxs", false, PSR_c | PSR_x | PSR_s},
558 {"SPSR_fsxc", false, PSR_f | PSR_s | PSR_x | PSR_c},
559 {"SPSR_fscx", false, PSR_f | PSR_s | PSR_c | PSR_x},
560 {"SPSR_fxsc", false, PSR_f | PSR_x | PSR_s | PSR_c},
561 {"SPSR_fxcs", false, PSR_f | PSR_x | PSR_c | PSR_s},
562 {"SPSR_fcsx", false, PSR_f | PSR_c | PSR_s | PSR_x},
563 {"SPSR_fcxs", false, PSR_f | PSR_c | PSR_x | PSR_s},
564 {"SPSR_sfxc", false, PSR_s | PSR_f | PSR_x | PSR_c},
565 {"SPSR_sfcx", false, PSR_s | PSR_f | PSR_c | PSR_x},
566 {"SPSR_sxfc", false, PSR_s | PSR_x | PSR_f | PSR_c},
567 {"SPSR_sxcf", false, PSR_s | PSR_x | PSR_c | PSR_f},
568 {"SPSR_scfx", false, PSR_s | PSR_c | PSR_f | PSR_x},
569 {"SPSR_scxf", false, PSR_s | PSR_c | PSR_x | PSR_f},
570 {"SPSR_xfsc", false, PSR_x | PSR_f | PSR_s | PSR_c},
571 {"SPSR_xfcs", false, PSR_x | PSR_f | PSR_c | PSR_s},
572 {"SPSR_xsfc", false, PSR_x | PSR_s | PSR_f | PSR_c},
573 {"SPSR_xscf", false, PSR_x | PSR_s | PSR_c | PSR_f},
574 {"SPSR_xcfs", false, PSR_x | PSR_c | PSR_f | PSR_s},
575 {"SPSR_xcsf", false, PSR_x | PSR_c | PSR_s | PSR_f},
576 {"SPSR_cfsx", false, PSR_c | PSR_f | PSR_s | PSR_x},
577 {"SPSR_cfxs", false, PSR_c | PSR_f | PSR_x | PSR_s},
578 {"SPSR_csfx", false, PSR_c | PSR_s | PSR_f | PSR_x},
579 {"SPSR_csxf", false, PSR_c | PSR_s | PSR_x | PSR_f},
580 {"SPSR_cxfs", false, PSR_c | PSR_x | PSR_f | PSR_s},
581 {"SPSR_cxsf", false, PSR_c | PSR_x | PSR_s | PSR_f},
582};
583
404ff6b5
AH
584enum cirrus_regtype
585 {
586 CIRRUS_REGTYPE_MVF = 1,
587 CIRRUS_REGTYPE_MVFX = 2,
588 CIRRUS_REGTYPE_MVD = 3,
589 CIRRUS_REGTYPE_MVDX = 4,
590 CIRRUS_REGTYPE_MVAX = 5,
591 CIRRUS_REGTYPE_DSPSC = 6,
592 CIRRUS_REGTYPE_ANY = 7
593 };
594
b99bd4ef
NC
595/* Functions called by parser. */
596/* ARM instructions. */
597static void do_arit PARAMS ((char *, unsigned long));
598static void do_cmp PARAMS ((char *, unsigned long));
599static void do_mov PARAMS ((char *, unsigned long));
600static void do_ldst PARAMS ((char *, unsigned long));
601static void do_ldmstm PARAMS ((char *, unsigned long));
602static void do_branch PARAMS ((char *, unsigned long));
603static void do_swi PARAMS ((char *, unsigned long));
604/* Pseudo Op codes. */
605static void do_adr PARAMS ((char *, unsigned long));
b99bd4ef
NC
606static void do_nop PARAMS ((char *, unsigned long));
607/* ARM 2. */
608static void do_mul PARAMS ((char *, unsigned long));
609static void do_mla PARAMS ((char *, unsigned long));
610/* ARM 3. */
611static void do_swap PARAMS ((char *, unsigned long));
612/* ARM 6. */
613static void do_msr PARAMS ((char *, unsigned long));
614static void do_mrs PARAMS ((char *, unsigned long));
615/* ARM 7M. */
616static void do_mull PARAMS ((char *, unsigned long));
617/* ARM THUMB. */
618static void do_bx PARAMS ((char *, unsigned long));
619
620/* ARM_EXT_XScale. */
621static void do_mia PARAMS ((char *, unsigned long));
622static void do_mar PARAMS ((char *, unsigned long));
623static void do_mra PARAMS ((char *, unsigned long));
624static void do_pld PARAMS ((char *, unsigned long));
625static void do_ldrd PARAMS ((char *, unsigned long));
626
627/* ARM_EXT_V5. */
628static void do_blx PARAMS ((char *, unsigned long));
629static void do_bkpt PARAMS ((char *, unsigned long));
630static void do_clz PARAMS ((char *, unsigned long));
631static void do_lstc2 PARAMS ((char *, unsigned long));
632static void do_cdp2 PARAMS ((char *, unsigned long));
633static void do_co_reg2 PARAMS ((char *, unsigned long));
634
635static void do_t_blx PARAMS ((char *));
636static void do_t_bkpt PARAMS ((char *));
637
638/* ARM_EXT_V5E. */
639static void do_smla PARAMS ((char *, unsigned long));
640static void do_smlal PARAMS ((char *, unsigned long));
641static void do_smul PARAMS ((char *, unsigned long));
642static void do_qadd PARAMS ((char *, unsigned long));
643static void do_co_reg2c PARAMS ((char *, unsigned long));
644
645/* Coprocessor Instructions. */
646static void do_cdp PARAMS ((char *, unsigned long));
647static void do_lstc PARAMS ((char *, unsigned long));
648static void do_co_reg PARAMS ((char *, unsigned long));
649static void do_fp_ctrl PARAMS ((char *, unsigned long));
650static void do_fp_ldst PARAMS ((char *, unsigned long));
651static void do_fp_ldmstm PARAMS ((char *, unsigned long));
652static void do_fp_dyadic PARAMS ((char *, unsigned long));
653static void do_fp_monadic PARAMS ((char *, unsigned long));
654static void do_fp_cmp PARAMS ((char *, unsigned long));
655static void do_fp_from_reg PARAMS ((char *, unsigned long));
656static void do_fp_to_reg PARAMS ((char *, unsigned long));
657
90f9b791 658/* ARM_EXT_MAVERICK. */
404ff6b5
AH
659static void do_c_binops PARAMS ((char *, unsigned long, int));
660static void do_c_binops_1 PARAMS ((char *, unsigned long));
661static void do_c_binops_2 PARAMS ((char *, unsigned long));
662static void do_c_binops_3 PARAMS ((char *, unsigned long));
663static void do_c_triple PARAMS ((char *, unsigned long, int));
664static void do_c_triple_4 PARAMS ((char *, unsigned long));
665static void do_c_triple_5 PARAMS ((char *, unsigned long));
666static void do_c_quad PARAMS ((char *, unsigned long, int));
667static void do_c_quad_6 PARAMS ((char *, unsigned long));
668static void do_c_dspsc PARAMS ((char *, unsigned long, int));
669static void do_c_dspsc_1 PARAMS ((char *, unsigned long));
670static void do_c_dspsc_2 PARAMS ((char *, unsigned long));
671static void do_c_shift PARAMS ((char *, unsigned long, int));
672static void do_c_shift_1 PARAMS ((char *, unsigned long));
673static void do_c_shift_2 PARAMS ((char *, unsigned long));
674static void do_c_ldst PARAMS ((char *, unsigned long, int));
675static void do_c_ldst_1 PARAMS ((char *, unsigned long));
676static void do_c_ldst_2 PARAMS ((char *, unsigned long));
677static void do_c_ldst_3 PARAMS ((char *, unsigned long));
678static void do_c_ldst_4 PARAMS ((char *, unsigned long));
679static int cirrus_reg_required_here PARAMS ((char **, int, enum cirrus_regtype));
680static int cirrus_valid_reg PARAMS ((int, enum cirrus_regtype));
681static int cirrus_parse_offset PARAMS ((char **, int *));
682
b99bd4ef
NC
683static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *, int, int));
684static int arm_reg_parse PARAMS ((char **));
685static CONST struct asm_psr * arm_psr_parse PARAMS ((char **));
686static void symbol_locate PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *));
687static int add_to_lit_pool PARAMS ((void));
688static unsigned validate_immediate PARAMS ((unsigned));
689static unsigned validate_immediate_twopart PARAMS ((unsigned int, unsigned int *));
690static int validate_offset_imm PARAMS ((unsigned int, int));
691static void opcode_select PARAMS ((int));
692static void end_of_line PARAMS ((char *));
693static int reg_required_here PARAMS ((char **, int));
694static int psr_required_here PARAMS ((char **));
695static int co_proc_number PARAMS ((char **));
696static int cp_opc_expr PARAMS ((char **, int, int));
697static int cp_reg_required_here PARAMS ((char **, int));
698static int fp_reg_required_here PARAMS ((char **, int));
699static int cp_address_offset PARAMS ((char **));
700static int cp_address_required_here PARAMS ((char **));
701static int my_get_float_expression PARAMS ((char **));
702static int skip_past_comma PARAMS ((char **));
703static int walk_no_bignums PARAMS ((symbolS *));
704static int negate_data_op PARAMS ((unsigned long *, unsigned long));
705static int data_op2 PARAMS ((char **));
706static int fp_op2 PARAMS ((char **));
707static long reg_list PARAMS ((char **));
708static void thumb_load_store PARAMS ((char *, int, int));
709static int decode_shift PARAMS ((char **, int));
710static int ldst_extend PARAMS ((char **, int));
711static void thumb_add_sub PARAMS ((char *, int));
712static void insert_reg PARAMS ((int));
713static void thumb_shift PARAMS ((char *, int));
714static void thumb_mov_compare PARAMS ((char *, int));
715static void set_constant_flonums PARAMS ((void));
716static valueT md_chars_to_number PARAMS ((char *, int));
717static void insert_reg_alias PARAMS ((char *, int));
718static void output_inst PARAMS ((void));
2c20dfb2
NC
719static int accum0_required_here PARAMS ((char **));
720static int ld_mode_required_here PARAMS ((char **));
721static void do_branch25 PARAMS ((char *, unsigned long));
722static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
723#ifdef OBJ_ELF
724static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
725#endif
726
727/* ARM instructions take 4bytes in the object file, Thumb instructions
728 take 2: */
729#define INSN_SIZE 4
730
731/* LONGEST_INST is the longest basic instruction name without
732 conditions or flags. ARM7M has 4 of length 5. El Segundo
733 has one basic instruction name of length 7 (SMLALxy). */
404ff6b5
AH
734#define LONGEST_INST 10
735
736/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
737#define CIRRUS_MODE1 0x100c
738
739/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
740#define CIRRUS_MODE2 0x0c10
741
742/* "INSN<cond> X,Y" where X:0, Y:bit16. */
743#define CIRRUS_MODE3 0x1000
744
745/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
746#define CIRRUS_MODE4 0x0c0010
747
748/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
749#define CIRRUS_MODE5 0x00100c
750
751/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
752#define CIRRUS_MODE6 0x00100c05
b99bd4ef
NC
753
754struct asm_opcode
755{
756 /* Basic string to match. */
757 CONST char * template;
758
759 /* Basic instruction code. */
760 unsigned long value;
761
762 /* Compulsory suffix that must follow conds. If "", then the
763 instruction is not conditional and must have no suffix. */
764 CONST char * comp_suffix;
765
766 /* Bits to toggle if flag 'n' set. */
767 CONST struct asm_flg * flags;
768
769 /* Which CPU variants this exists for. */
770 unsigned long variants;
771
772 /* Function to call to parse args. */
773 void (* parms) PARAMS ((char *, unsigned long));
774};
775
776static CONST struct asm_opcode insns[] =
777{
778/* Intel XScale extensions to ARM V5 ISA. */
779 {"mia", 0x0e200010, NULL, NULL, ARM_EXT_XSCALE, do_mia},
780 {"miaph", 0x0e280010, NULL, NULL, ARM_EXT_XSCALE, do_mia},
781 {"miabb", 0x0e2c0010, NULL, NULL, ARM_EXT_XSCALE, do_mia},
782 {"miabt", 0x0e2d0010, NULL, NULL, ARM_EXT_XSCALE, do_mia},
783 {"miatb", 0x0e2e0010, NULL, NULL, ARM_EXT_XSCALE, do_mia},
784 {"miatt", 0x0e2f0010, NULL, NULL, ARM_EXT_XSCALE, do_mia},
785 {"mar", 0x0c400000, NULL, NULL, ARM_EXT_XSCALE, do_mar},
786 {"mra", 0x0c500000, NULL, NULL, ARM_EXT_XSCALE, do_mra},
787 {"pld", 0xf450f000, "", NULL, ARM_EXT_XSCALE, do_pld},
788 {"ldr", 0x000000d0, NULL, ldr_flags, ARM_ANY, do_ldrd},
789 {"str", 0x000000f0, NULL, str_flags, ARM_ANY, do_ldrd},
790
791/* ARM Instructions. */
792 {"and", 0x00000000, NULL, s_flag, ARM_ANY, do_arit},
793 {"eor", 0x00200000, NULL, s_flag, ARM_ANY, do_arit},
794 {"sub", 0x00400000, NULL, s_flag, ARM_ANY, do_arit},
795 {"rsb", 0x00600000, NULL, s_flag, ARM_ANY, do_arit},
796 {"add", 0x00800000, NULL, s_flag, ARM_ANY, do_arit},
797 {"adc", 0x00a00000, NULL, s_flag, ARM_ANY, do_arit},
798 {"sbc", 0x00c00000, NULL, s_flag, ARM_ANY, do_arit},
799 {"rsc", 0x00e00000, NULL, s_flag, ARM_ANY, do_arit},
800 {"orr", 0x01800000, NULL, s_flag, ARM_ANY, do_arit},
801 {"bic", 0x01c00000, NULL, s_flag, ARM_ANY, do_arit},
802 {"tst", 0x01000000, NULL, cmp_flags, ARM_ANY, do_cmp},
803 {"teq", 0x01200000, NULL, cmp_flags, ARM_ANY, do_cmp},
804 {"cmp", 0x01400000, NULL, cmp_flags, ARM_ANY, do_cmp},
805 {"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp},
806 {"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov},
807 {"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov},
808 {"str", 0x04000000, NULL, str_flags, ARM_ANY, do_ldst},
809 {"ldr", 0x04100000, NULL, ldr_flags, ARM_ANY, do_ldst},
810 {"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm},
811 {"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm},
812 {"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi},
813#ifdef TE_WINCE
814 {"bl", 0x0b000000, NULL, NULL, ARM_ANY, do_branch},
815 {"b", 0x0a000000, NULL, NULL, ARM_ANY, do_branch},
816#else
817 {"bl", 0x0bfffffe, NULL, NULL, ARM_ANY, do_branch},
818 {"b", 0x0afffffe, NULL, NULL, ARM_ANY, do_branch},
819#endif
820
821/* Pseudo ops. */
1cac9012 822 {"adr", 0x028f0000, NULL, long_flag, ARM_ANY, do_adr},
b99bd4ef
NC
823 {"nop", 0x01a00000, NULL, NULL, ARM_ANY, do_nop},
824
825/* ARM 2 multiplies. */
826 {"mul", 0x00000090, NULL, s_flag, ARM_2UP, do_mul},
827 {"mla", 0x00200090, NULL, s_flag, ARM_2UP, do_mla},
828
829/* ARM 3 - swp instructions. */
830 {"swp", 0x01000090, NULL, byte_flag, ARM_3UP, do_swap},
831
832/* ARM 6 Coprocessor instructions. */
833 {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
834 {"msr", 0x0120f000, NULL, NULL, ARM_6UP, do_msr},
835/* ScottB: our code uses 0x0128f000 for msr.
836 NickC: but this is wrong because the bits 16 through 19 are
837 handled by the PSR_xxx defines above. */
838
839/* ARM 7M long multiplies - need signed/unsigned flags! */
840 {"smull", 0x00c00090, NULL, s_flag, ARM_EXT_LONGMUL, do_mull},
841 {"umull", 0x00800090, NULL, s_flag, ARM_EXT_LONGMUL, do_mull},
842 {"smlal", 0x00e00090, NULL, s_flag, ARM_EXT_LONGMUL, do_mull},
843 {"umlal", 0x00a00090, NULL, s_flag, ARM_EXT_LONGMUL, do_mull},
844
845/* ARM THUMB interworking. */
846 {"bx", 0x012fff10, NULL, NULL, ARM_EXT_THUMB, do_bx},
847
848/* Floating point instructions. */
849 {"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl},
850 {"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl},
851 {"wfc", 0x0e400110, NULL, NULL, FPU_ALL, do_fp_ctrl},
852 {"rfc", 0x0e500110, NULL, NULL, FPU_ALL, do_fp_ctrl},
853 {"ldf", 0x0c100100, "sdep", NULL, FPU_ALL, do_fp_ldst},
854 {"stf", 0x0c000100, "sdep", NULL, FPU_ALL, do_fp_ldst},
855 {"lfm", 0x0c100200, NULL, lfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
856 {"sfm", 0x0c000200, NULL, sfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
857 {"mvf", 0x0e008100, "sde", round_flags, FPU_ALL, do_fp_monadic},
858 {"mnf", 0x0e108100, "sde", round_flags, FPU_ALL, do_fp_monadic},
859 {"abs", 0x0e208100, "sde", round_flags, FPU_ALL, do_fp_monadic},
860 {"rnd", 0x0e308100, "sde", round_flags, FPU_ALL, do_fp_monadic},
861 {"sqt", 0x0e408100, "sde", round_flags, FPU_ALL, do_fp_monadic},
862 {"log", 0x0e508100, "sde", round_flags, FPU_ALL, do_fp_monadic},
863 {"lgn", 0x0e608100, "sde", round_flags, FPU_ALL, do_fp_monadic},
864 {"exp", 0x0e708100, "sde", round_flags, FPU_ALL, do_fp_monadic},
865 {"sin", 0x0e808100, "sde", round_flags, FPU_ALL, do_fp_monadic},
866 {"cos", 0x0e908100, "sde", round_flags, FPU_ALL, do_fp_monadic},
867 {"tan", 0x0ea08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
868 {"asn", 0x0eb08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
869 {"acs", 0x0ec08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
870 {"atn", 0x0ed08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
871 {"urd", 0x0ee08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
872 {"nrm", 0x0ef08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
873 {"adf", 0x0e000100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
874 {"suf", 0x0e200100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
875 {"rsf", 0x0e300100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
876 {"muf", 0x0e100100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
877 {"dvf", 0x0e400100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
878 {"rdf", 0x0e500100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
879 {"pow", 0x0e600100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
880 {"rpw", 0x0e700100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
881 {"rmf", 0x0e800100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
882 {"fml", 0x0e900100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
883 {"fdv", 0x0ea00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
884 {"frd", 0x0eb00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
885 {"pol", 0x0ec00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
886 {"cmf", 0x0e90f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
887 {"cnf", 0x0eb0f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
888/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
889 be an optional suffix, but part of the instruction. To be compatible,
890 we accept either. */
891 {"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
892 {"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
893 {"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg},
894 {"fix", 0x0e100110, NULL, fix_flags, FPU_ALL, do_fp_to_reg},
895
896/* Generic copressor instructions. */
897 {"cdp", 0x0e000000, NULL, NULL, ARM_2UP, do_cdp},
1cac9012
NC
898 {"ldc", 0x0c100000, NULL, long_flag, ARM_2UP, do_lstc},
899 {"stc", 0x0c000000, NULL, long_flag, ARM_2UP, do_lstc},
b99bd4ef
NC
900 {"mcr", 0x0e000010, NULL, NULL, ARM_2UP, do_co_reg},
901 {"mrc", 0x0e100010, NULL, NULL, ARM_2UP, do_co_reg},
902
903/* ARM ISA extension 5. */
904/* Note: blx is actually 2 opcodes, so the .value is set dynamically.
905 And it's sometimes conditional and sometimes not. */
906 {"blx", 0, NULL, NULL, ARM_EXT_V5, do_blx},
907 {"clz", 0x016f0f10, NULL, NULL, ARM_EXT_V5, do_clz},
908 {"bkpt", 0xe1200070, "", NULL, ARM_EXT_V5, do_bkpt},
1cac9012
NC
909 {"ldc2", 0xfc100000, "", long_flag, ARM_EXT_V5, do_lstc2},
910 {"stc2", 0xfc000000, "", long_flag, ARM_EXT_V5, do_lstc2},
b99bd4ef
NC
911 {"cdp2", 0xfe000000, "", NULL, ARM_EXT_V5, do_cdp2},
912 {"mcr2", 0xfe000010, "", NULL, ARM_EXT_V5, do_co_reg2},
913 {"mrc2", 0xfe100010, "", NULL, ARM_EXT_V5, do_co_reg2},
914
915/* ARM ISA extension 5E, El Segundo. */
916 {"smlabb", 0x01000080, NULL, NULL, ARM_EXT_V5E, do_smla},
917 {"smlatb", 0x010000a0, NULL, NULL, ARM_EXT_V5E, do_smla},
918 {"smlabt", 0x010000c0, NULL, NULL, ARM_EXT_V5E, do_smla},
919 {"smlatt", 0x010000e0, NULL, NULL, ARM_EXT_V5E, do_smla},
920
921 {"smlawb", 0x01200080, NULL, NULL, ARM_EXT_V5E, do_smla},
922 {"smlawt", 0x012000c0, NULL, NULL, ARM_EXT_V5E, do_smla},
923
924 {"smlalbb",0x01400080, NULL, NULL, ARM_EXT_V5E, do_smlal},
925 {"smlaltb",0x014000a0, NULL, NULL, ARM_EXT_V5E, do_smlal},
926 {"smlalbt",0x014000c0, NULL, NULL, ARM_EXT_V5E, do_smlal},
927 {"smlaltt",0x014000e0, NULL, NULL, ARM_EXT_V5E, do_smlal},
928
929 {"smulbb", 0x01600080, NULL, NULL, ARM_EXT_V5E, do_smul},
930 {"smultb", 0x016000a0, NULL, NULL, ARM_EXT_V5E, do_smul},
931 {"smulbt", 0x016000c0, NULL, NULL, ARM_EXT_V5E, do_smul},
932 {"smultt", 0x016000e0, NULL, NULL, ARM_EXT_V5E, do_smul},
933
934 {"smulwb", 0x012000a0, NULL, NULL, ARM_EXT_V5E, do_smul},
935 {"smulwt", 0x012000e0, NULL, NULL, ARM_EXT_V5E, do_smul},
936
937 {"qadd", 0x01000050, NULL, NULL, ARM_EXT_V5E, do_qadd},
938 {"qdadd", 0x01400050, NULL, NULL, ARM_EXT_V5E, do_qadd},
939 {"qsub", 0x01200050, NULL, NULL, ARM_EXT_V5E, do_qadd},
940 {"qdsub", 0x01600050, NULL, NULL, ARM_EXT_V5E, do_qadd},
941
942 {"mcrr", 0x0c400000, NULL, NULL, ARM_EXT_V5E, do_co_reg2c},
943 {"mrrc", 0x0c500000, NULL, NULL, ARM_EXT_V5E, do_co_reg2c},
404ff6b5
AH
944
945 /* Cirrus DSP instructions. */
90f9b791
AH
946 {"cfldrs", 0x0c100400, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_1},
947 {"cfldrd", 0x0c500400, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_2},
948 {"cfldr32", 0x0c100500, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_3},
949 {"cfldr64", 0x0c500500, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_4},
950 {"cfstrs", 0x0c000400, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_1},
951 {"cfstrd", 0x0c400400, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_2},
952 {"cfstr32", 0x0c000500, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_3},
953 {"cfstr64", 0x0c400500, NULL, NULL, ARM_EXT_MAVERICK, do_c_ldst_4},
954 {"cfmvsr", 0x0e000450, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_2},
955 {"cfmvrs", 0x0e100450, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
956 {"cfmvdlr", 0x0e000410, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_2},
957 {"cfmvrdl", 0x0e100410, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
958 {"cfmvdhr", 0x0e000430, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_2},
959 {"cfmvrdh", 0x0e100430, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
960 {"cfmv64lr", 0x0e000510, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_2},
961 {"cfmvr64l", 0x0e100510, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
962 {"cfmv64hr", 0x0e000530, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_2},
963 {"cfmvr64h", 0x0e100530, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
964 {"cfmval32", 0x0e100610, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
965 {"cfmv32al", 0x0e000610, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
966 {"cfmvam32", 0x0e100630, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
967 {"cfmv32am", 0x0e000630, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
968 {"cfmvah32", 0x0e100650, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
969 {"cfmv32ah", 0x0e000650, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
970 {"cfmv32a", 0x0e000670, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
971 {"cfmva32", 0x0e100670, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
972 {"cfmv64a", 0x0e000690, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
973 {"cfmva64", 0x0e100690, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_3},
974 {"cfmvsc32", 0x0e1006b0, NULL, NULL, ARM_EXT_MAVERICK, do_c_dspsc_1},
975 {"cfmv32sc", 0x0e0006b0, NULL, NULL, ARM_EXT_MAVERICK, do_c_dspsc_2},
976 {"cfcpys", 0x0e000400, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
977 {"cfcpyd", 0x0e000420, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
978 {"cfcvtsd", 0x0e000460, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
979 {"cfcvtds", 0x0e000440, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
980 {"cfcvt32s", 0x0e000480, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
981 {"cfcvt32d", 0x0e0004a0, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
982 {"cfcvt64s", 0x0e0004c0, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
983 {"cfcvt64d", 0x0e0004e0, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
984 {"cfcvts32", 0x0e100580, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
985 {"cfcvtd32", 0x0e1005a0, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
986 {"cftruncs32",0x0e1005c0, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
987 {"cftruncd32",0x0e1005e0, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
988 {"cfrshl32", 0x0e000550, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_4},
989 {"cfrshl64", 0x0e000570, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_4},
990 {"cfsh32", 0x0e000500, NULL, NULL, ARM_EXT_MAVERICK, do_c_shift_1},
991 {"cfsh64", 0x0e200500, NULL, NULL, ARM_EXT_MAVERICK, do_c_shift_2},
992 {"cfcmps", 0x0e100490, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
993 {"cfcmpd", 0x0e1004b0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
994 {"cfcmp32", 0x0e100590, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
995 {"cfcmp64", 0x0e1005b0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
996 {"cfabss", 0x0e300400, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
997 {"cfabsd", 0x0e300420, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
998 {"cfnegs", 0x0e300440, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
999 {"cfnegd", 0x0e300460, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
1000 {"cfadds", 0x0e300480, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1001 {"cfaddd", 0x0e3004a0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1002 {"cfsubs", 0x0e3004c0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1003 {"cfsubd", 0x0e3004e0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1004 {"cfmuls", 0x0e100400, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1005 {"cfmuld", 0x0e100420, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1006 {"cfabs32", 0x0e300500, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
1007 {"cfabs64", 0x0e300520, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
1008 {"cfneg32", 0x0e300540, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
1009 {"cfneg64", 0x0e300560, NULL, NULL, ARM_EXT_MAVERICK, do_c_binops_1},
1010 {"cfadd32", 0x0e300580, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1011 {"cfadd64", 0x0e3005a0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1012 {"cfsub32", 0x0e3005c0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1013 {"cfsub64", 0x0e3005e0, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1014 {"cfmul32", 0x0e100500, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1015 {"cfmul64", 0x0e100520, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1016 {"cfmac32", 0x0e100540, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1017 {"cfmsc32", 0x0e100560, NULL, NULL, ARM_EXT_MAVERICK, do_c_triple_5},
1018 {"cfmadd32", 0x0e000600, NULL, NULL, ARM_EXT_MAVERICK, do_c_quad_6},
1019 {"cfmsub32", 0x0e100600, NULL, NULL, ARM_EXT_MAVERICK, do_c_quad_6},
1020 {"cfmadda32", 0x0e200600, NULL, NULL, ARM_EXT_MAVERICK, do_c_quad_6},
1021 {"cfmsuba32", 0x0e300600, NULL, NULL, ARM_EXT_MAVERICK, do_c_quad_6},
b99bd4ef
NC
1022};
1023
1024/* Defines for various bits that we will want to toggle. */
1025#define INST_IMMEDIATE 0x02000000
1026#define OFFSET_REG 0x02000000
1027#define HWOFFSET_IMM 0x00400000
1028#define SHIFT_BY_REG 0x00000010
1029#define PRE_INDEX 0x01000000
1030#define INDEX_UP 0x00800000
1031#define WRITE_BACK 0x00200000
1032#define LDM_TYPE_2_OR_3 0x00400000
1033
1034#define LITERAL_MASK 0xf000f000
1035#define COND_MASK 0xf0000000
1036#define OPCODE_MASK 0xfe1fffff
1037#define DATA_OP_SHIFT 21
1038
1039/* Codes to distinguish the arithmetic instructions. */
1040#define OPCODE_AND 0
1041#define OPCODE_EOR 1
1042#define OPCODE_SUB 2
1043#define OPCODE_RSB 3
1044#define OPCODE_ADD 4
1045#define OPCODE_ADC 5
1046#define OPCODE_SBC 6
1047#define OPCODE_RSC 7
1048#define OPCODE_TST 8
1049#define OPCODE_TEQ 9
1050#define OPCODE_CMP 10
1051#define OPCODE_CMN 11
1052#define OPCODE_ORR 12
1053#define OPCODE_MOV 13
1054#define OPCODE_BIC 14
1055#define OPCODE_MVN 15
1056
1057static void do_t_nop PARAMS ((char *));
1058static void do_t_arit PARAMS ((char *));
1059static void do_t_add PARAMS ((char *));
1060static void do_t_asr PARAMS ((char *));
1061static void do_t_branch9 PARAMS ((char *));
1062static void do_t_branch12 PARAMS ((char *));
1063static void do_t_branch23 PARAMS ((char *));
1064static void do_t_bx PARAMS ((char *));
1065static void do_t_compare PARAMS ((char *));
1066static void do_t_ldmstm PARAMS ((char *));
1067static void do_t_ldr PARAMS ((char *));
1068static void do_t_ldrb PARAMS ((char *));
1069static void do_t_ldrh PARAMS ((char *));
1070static void do_t_lds PARAMS ((char *));
1071static void do_t_lsl PARAMS ((char *));
1072static void do_t_lsr PARAMS ((char *));
1073static void do_t_mov PARAMS ((char *));
1074static void do_t_push_pop PARAMS ((char *));
1075static void do_t_str PARAMS ((char *));
1076static void do_t_strb PARAMS ((char *));
1077static void do_t_strh PARAMS ((char *));
1078static void do_t_sub PARAMS ((char *));
1079static void do_t_swi PARAMS ((char *));
1080static void do_t_adr PARAMS ((char *));
1081
1082#define T_OPCODE_MUL 0x4340
1083#define T_OPCODE_TST 0x4200
1084#define T_OPCODE_CMN 0x42c0
1085#define T_OPCODE_NEG 0x4240
1086#define T_OPCODE_MVN 0x43c0
1087
1088#define T_OPCODE_ADD_R3 0x1800
1089#define T_OPCODE_SUB_R3 0x1a00
1090#define T_OPCODE_ADD_HI 0x4400
1091#define T_OPCODE_ADD_ST 0xb000
1092#define T_OPCODE_SUB_ST 0xb080
1093#define T_OPCODE_ADD_SP 0xa800
1094#define T_OPCODE_ADD_PC 0xa000
1095#define T_OPCODE_ADD_I8 0x3000
1096#define T_OPCODE_SUB_I8 0x3800
1097#define T_OPCODE_ADD_I3 0x1c00
1098#define T_OPCODE_SUB_I3 0x1e00
1099
1100#define T_OPCODE_ASR_R 0x4100
1101#define T_OPCODE_LSL_R 0x4080
1102#define T_OPCODE_LSR_R 0x40c0
1103#define T_OPCODE_ASR_I 0x1000
1104#define T_OPCODE_LSL_I 0x0000
1105#define T_OPCODE_LSR_I 0x0800
1106
1107#define T_OPCODE_MOV_I8 0x2000
1108#define T_OPCODE_CMP_I8 0x2800
1109#define T_OPCODE_CMP_LR 0x4280
1110#define T_OPCODE_MOV_HR 0x4600
1111#define T_OPCODE_CMP_HR 0x4500
1112
1113#define T_OPCODE_LDR_PC 0x4800
1114#define T_OPCODE_LDR_SP 0x9800
1115#define T_OPCODE_STR_SP 0x9000
1116#define T_OPCODE_LDR_IW 0x6800
1117#define T_OPCODE_STR_IW 0x6000
1118#define T_OPCODE_LDR_IH 0x8800
1119#define T_OPCODE_STR_IH 0x8000
1120#define T_OPCODE_LDR_IB 0x7800
1121#define T_OPCODE_STR_IB 0x7000
1122#define T_OPCODE_LDR_RW 0x5800
1123#define T_OPCODE_STR_RW 0x5000
1124#define T_OPCODE_LDR_RH 0x5a00
1125#define T_OPCODE_STR_RH 0x5200
1126#define T_OPCODE_LDR_RB 0x5c00
1127#define T_OPCODE_STR_RB 0x5400
1128
1129#define T_OPCODE_PUSH 0xb400
1130#define T_OPCODE_POP 0xbc00
1131
1132#define T_OPCODE_BRANCH 0xe7fe
1133
1134static int thumb_reg PARAMS ((char ** str, int hi_lo));
1135
1136#define THUMB_SIZE 2 /* Size of thumb instruction. */
1137#define THUMB_REG_LO 0x1
1138#define THUMB_REG_HI 0x2
1139#define THUMB_REG_ANY 0x3
1140
1141#define THUMB_H1 0x0080
1142#define THUMB_H2 0x0040
1143
1144#define THUMB_ASR 0
1145#define THUMB_LSL 1
1146#define THUMB_LSR 2
1147
1148#define THUMB_MOVE 0
1149#define THUMB_COMPARE 1
1150
1151#define THUMB_LOAD 0
1152#define THUMB_STORE 1
1153
1154#define THUMB_PP_PC_LR 0x0100
1155
1156/* These three are used for immediate shifts, do not alter. */
1157#define THUMB_WORD 2
1158#define THUMB_HALFWORD 1
1159#define THUMB_BYTE 0
1160
1161struct thumb_opcode
1162{
1163 /* Basic string to match. */
1164 CONST char * template;
1165
1166 /* Basic instruction code. */
1167 unsigned long value;
1168
1169 int size;
1170
1171 /* Which CPU variants this exists for. */
1172 unsigned long variants;
1173
1174 /* Function to call to parse args. */
1175 void (* parms) PARAMS ((char *));
1176};
1177
1178static CONST struct thumb_opcode tinsns[] =
1179{
1180 {"adc", 0x4140, 2, ARM_EXT_THUMB, do_t_arit},
1181 {"add", 0x0000, 2, ARM_EXT_THUMB, do_t_add},
1182 {"and", 0x4000, 2, ARM_EXT_THUMB, do_t_arit},
1183 {"asr", 0x0000, 2, ARM_EXT_THUMB, do_t_asr},
1184 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_THUMB, do_t_branch12},
1185 {"beq", 0xd0fe, 2, ARM_EXT_THUMB, do_t_branch9},
1186 {"bne", 0xd1fe, 2, ARM_EXT_THUMB, do_t_branch9},
1187 {"bcs", 0xd2fe, 2, ARM_EXT_THUMB, do_t_branch9},
1188 {"bhs", 0xd2fe, 2, ARM_EXT_THUMB, do_t_branch9},
1189 {"bcc", 0xd3fe, 2, ARM_EXT_THUMB, do_t_branch9},
1190 {"bul", 0xd3fe, 2, ARM_EXT_THUMB, do_t_branch9},
1191 {"blo", 0xd3fe, 2, ARM_EXT_THUMB, do_t_branch9},
1192 {"bmi", 0xd4fe, 2, ARM_EXT_THUMB, do_t_branch9},
1193 {"bpl", 0xd5fe, 2, ARM_EXT_THUMB, do_t_branch9},
1194 {"bvs", 0xd6fe, 2, ARM_EXT_THUMB, do_t_branch9},
1195 {"bvc", 0xd7fe, 2, ARM_EXT_THUMB, do_t_branch9},
1196 {"bhi", 0xd8fe, 2, ARM_EXT_THUMB, do_t_branch9},
1197 {"bls", 0xd9fe, 2, ARM_EXT_THUMB, do_t_branch9},
1198 {"bge", 0xdafe, 2, ARM_EXT_THUMB, do_t_branch9},
1199 {"blt", 0xdbfe, 2, ARM_EXT_THUMB, do_t_branch9},
1200 {"bgt", 0xdcfe, 2, ARM_EXT_THUMB, do_t_branch9},
1201 {"ble", 0xddfe, 2, ARM_EXT_THUMB, do_t_branch9},
1202 {"bal", 0xdefe, 2, ARM_EXT_THUMB, do_t_branch9},
1203 {"bic", 0x4380, 2, ARM_EXT_THUMB, do_t_arit},
1204 {"bl", 0xf7fffffe, 4, ARM_EXT_THUMB, do_t_branch23},
1205 {"blx", 0, 0, ARM_EXT_V5, do_t_blx},
1206 {"bkpt", 0xbe00, 2, ARM_EXT_V5, do_t_bkpt},
1207 {"bx", 0x4700, 2, ARM_EXT_THUMB, do_t_bx},
1208 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_THUMB, do_t_arit},
1209 {"cmp", 0x0000, 2, ARM_EXT_THUMB, do_t_compare},
1210 {"eor", 0x4040, 2, ARM_EXT_THUMB, do_t_arit},
1211 {"ldmia", 0xc800, 2, ARM_EXT_THUMB, do_t_ldmstm},
1212 {"ldr", 0x0000, 2, ARM_EXT_THUMB, do_t_ldr},
1213 {"ldrb", 0x0000, 2, ARM_EXT_THUMB, do_t_ldrb},
1214 {"ldrh", 0x0000, 2, ARM_EXT_THUMB, do_t_ldrh},
1215 {"ldrsb", 0x5600, 2, ARM_EXT_THUMB, do_t_lds},
1216 {"ldrsh", 0x5e00, 2, ARM_EXT_THUMB, do_t_lds},
1217 {"ldsb", 0x5600, 2, ARM_EXT_THUMB, do_t_lds},
1218 {"ldsh", 0x5e00, 2, ARM_EXT_THUMB, do_t_lds},
1219 {"lsl", 0x0000, 2, ARM_EXT_THUMB, do_t_lsl},
1220 {"lsr", 0x0000, 2, ARM_EXT_THUMB, do_t_lsr},
1221 {"mov", 0x0000, 2, ARM_EXT_THUMB, do_t_mov},
1222 {"mul", T_OPCODE_MUL, 2, ARM_EXT_THUMB, do_t_arit},
1223 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_THUMB, do_t_arit},
1224 {"neg", T_OPCODE_NEG, 2, ARM_EXT_THUMB, do_t_arit},
1225 {"orr", 0x4300, 2, ARM_EXT_THUMB, do_t_arit},
1226 {"pop", 0xbc00, 2, ARM_EXT_THUMB, do_t_push_pop},
1227 {"push", 0xb400, 2, ARM_EXT_THUMB, do_t_push_pop},
1228 {"ror", 0x41c0, 2, ARM_EXT_THUMB, do_t_arit},
1229 {"sbc", 0x4180, 2, ARM_EXT_THUMB, do_t_arit},
1230 {"stmia", 0xc000, 2, ARM_EXT_THUMB, do_t_ldmstm},
1231 {"str", 0x0000, 2, ARM_EXT_THUMB, do_t_str},
1232 {"strb", 0x0000, 2, ARM_EXT_THUMB, do_t_strb},
1233 {"strh", 0x0000, 2, ARM_EXT_THUMB, do_t_strh},
1234 {"swi", 0xdf00, 2, ARM_EXT_THUMB, do_t_swi},
1235 {"sub", 0x0000, 2, ARM_EXT_THUMB, do_t_sub},
1236 {"tst", T_OPCODE_TST, 2, ARM_EXT_THUMB, do_t_arit},
1237 /* Pseudo ops: */
1238 {"adr", 0x0000, 2, ARM_EXT_THUMB, do_t_adr},
1239 {"nop", 0x46C0, 2, ARM_EXT_THUMB, do_t_nop}, /* mov r8,r8 */
1240};
1241
1242struct reg_entry
1243{
1244 CONST char * name;
1245 int number;
1246};
1247
1248#define int_register(reg) ((reg) >= 0 && (reg) <= 15)
1249#define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
1250#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
1251
90f9b791 1252#define ARM_EXT_MAVERICKSC_REG 134
404ff6b5
AH
1253
1254#define cirrus_register(reg) ((reg) >= 50 && (reg) <= 134)
1255#define cirrus_mvf_register(reg) ((reg) >= 50 && (reg) <= 65)
1256#define cirrus_mvd_register(reg) ((reg) >= 70 && (reg) <= 85)
1257#define cirrus_mvfx_register(reg) ((reg) >= 90 && (reg) <= 105)
1258#define cirrus_mvdx_register(reg) ((reg) >= 110 && (reg) <= 125)
1259#define cirrus_mvax_register(reg) ((reg) >= 130 && (reg) <= 133)
90f9b791 1260#define ARM_EXT_MAVERICKsc_register(reg) ((reg) == ARM_EXT_MAVERICKSC_REG)
404ff6b5 1261
b99bd4ef
NC
1262#define REG_PC 15
1263#define REG_LR 14
1264#define REG_SP 13
1265
1266/* These are the standard names. Users can add aliases with .req. */
1267static CONST struct reg_entry reg_table[] =
1268{
1269 /* Processor Register Numbers. */
1270 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
1271 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
1272 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
1273 {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
1274 /* APCS conventions. */
1275 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
1276 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
1277 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
1278 {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
1279 /* ATPCS additions to APCS conventions. */
1280 {"wr", 7}, {"v8", 11},
1281 /* FP Registers. */
1282 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
1283 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
1284 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
1285 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
1286 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
1287 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
1288 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
1289 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
1290 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
1291 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
1292 /* ATPCS additions to float register names. */
1293 {"s0",16}, {"s1",17}, {"s2",18}, {"s3",19},
1294 {"s4",20}, {"s5",21}, {"s6",22}, {"s7",23},
1295 {"d0",16}, {"d1",17}, {"d2",18}, {"d3",19},
1296 {"d4",20}, {"d5",21}, {"d6",22}, {"d7",23},
404ff6b5
AH
1297 /* Cirrus DSP coprocessor registers. */
1298 {"mvf0", 50}, {"mvf1", 51}, {"mvf2", 52}, {"mvf3", 53},
1299 {"mvf4", 54}, {"mvf5", 55}, {"mvf6", 56}, {"mvf7", 57},
1300 {"mvf8", 58}, {"mvf9", 59}, {"mvf10", 60}, {"mvf11", 61},
1301 {"mvf12", 62},{"mvf13", 63}, {"mvf14", 64}, {"mvf15", 65},
1302 {"mvd0", 70}, {"mvd1", 71}, {"mvd2", 72}, {"mvd3", 73},
1303 {"mvd4", 74}, {"mvd5", 75}, {"mvd6", 76}, {"mvd7", 77},
1304 {"mvd8", 78}, {"mvd9", 79}, {"mvd10", 80}, {"mvd11", 81},
1305 {"mvd12", 82},{"mvd13", 83}, {"mvd14", 84}, {"mvd15", 85},
1306 {"mvfx0", 90},{"mvfx1", 91}, {"mvfx2", 92}, {"mvfx3", 93},
1307 {"mvfx4", 94},{"mvfx5", 95}, {"mvfx6", 96}, {"mvfx7", 97},
1308 {"mvfx8", 98},{"mvfx9", 99}, {"mvfx10", 100},{"mvfx11", 101},
1309 {"mvfx12", 102},{"mvfx13", 103},{"mvfx14", 104},{"mvfx15", 105},
1310 {"mvdx0", 110}, {"mvdx1", 111}, {"mvdx2", 112}, {"mvdx3", 113},
1311 {"mvdx4", 114}, {"mvdx5", 115}, {"mvdx6", 116}, {"mvdx7", 117},
1312 {"mvdx8", 118}, {"mvdx9", 119}, {"mvdx10", 120},{"mvdx11", 121},
1313 {"mvdx12", 122},{"mvdx13", 123},{"mvdx14", 124},{"mvdx15", 125},
1314 {"mvax0", 130}, {"mvax1", 131}, {"mvax2", 132}, {"mvax3", 133},
90f9b791 1315 {"dspsc", ARM_EXT_MAVERICKSC_REG},
b99bd4ef
NC
1316 /* FIXME: At some point we need to add VFP register names. */
1317 /* Array terminator. */
1318 {NULL, 0}
1319};
1320
1321#define BAD_ARGS _("Bad arguments to instruction")
1322#define BAD_PC _("r15 not allowed here")
1323#define BAD_FLAGS _("Instruction should not have flags")
1324#define BAD_COND _("Instruction is not conditional")
1325#define ERR_NO_ACCUM _("acc0 expected")
1326
1327static struct hash_control * arm_ops_hsh = NULL;
1328static struct hash_control * arm_tops_hsh = NULL;
1329static struct hash_control * arm_cond_hsh = NULL;
1330static struct hash_control * arm_shift_hsh = NULL;
1331static struct hash_control * arm_reg_hsh = NULL;
1332static struct hash_control * arm_psr_hsh = NULL;
1333
1334/* This table describes all the machine specific pseudo-ops the assembler
1335 has to support. The fields are:
1336 pseudo-op name without dot
1337 function to call to execute this pseudo-op
1338 Integer arg to pass to the function. */
1339
1340static void s_req PARAMS ((int));
1341static void s_align PARAMS ((int));
1342static void s_bss PARAMS ((int));
1343static void s_even PARAMS ((int));
1344static void s_ltorg PARAMS ((int));
1345static void s_arm PARAMS ((int));
1346static void s_thumb PARAMS ((int));
1347static void s_code PARAMS ((int));
1348static void s_force_thumb PARAMS ((int));
1349static void s_thumb_func PARAMS ((int));
1350static void s_thumb_set PARAMS ((int));
1351static void arm_s_text PARAMS ((int));
1352static void arm_s_data PARAMS ((int));
1353#ifdef OBJ_ELF
1354static void arm_s_section PARAMS ((int));
1355static void s_arm_elf_cons PARAMS ((int));
1356#endif
1357
1358static int my_get_expression PARAMS ((expressionS *, char **));
1359
1360CONST pseudo_typeS md_pseudo_table[] =
1361{
1362 /* Never called becasue '.req' does not start line. */
1363 { "req", s_req, 0 },
1364 { "bss", s_bss, 0 },
1365 { "align", s_align, 0 },
1366 { "arm", s_arm, 0 },
1367 { "thumb", s_thumb, 0 },
1368 { "code", s_code, 0 },
1369 { "force_thumb", s_force_thumb, 0 },
1370 { "thumb_func", s_thumb_func, 0 },
1371 { "thumb_set", s_thumb_set, 0 },
1372 { "even", s_even, 0 },
1373 { "ltorg", s_ltorg, 0 },
1374 { "pool", s_ltorg, 0 },
1375 /* Allow for the effect of section changes. */
1376 { "text", arm_s_text, 0 },
1377 { "data", arm_s_data, 0 },
1378#ifdef OBJ_ELF
1379 { "section", arm_s_section, 0 },
1380 { "section.s", arm_s_section, 0 },
1381 { "sect", arm_s_section, 0 },
1382 { "sect.s", arm_s_section, 0 },
1383 { "word", s_arm_elf_cons, 4 },
1384 { "long", s_arm_elf_cons, 4 },
1385 { "file", dwarf2_directive_file, 0 },
1386 { "loc", dwarf2_directive_loc, 0 },
1387#else
1388 { "word", cons, 4},
1389#endif
1390 { "extend", float_cons, 'x' },
1391 { "ldouble", float_cons, 'x' },
1392 { "packed", float_cons, 'p' },
1393 { 0, 0, 0 }
1394};
1395
1396/* Stuff needed to resolve the label ambiguity
1397 As:
1398 ...
1399 label: <insn>
1400 may differ from:
1401 ...
1402 label:
1403 <insn>
1404*/
1405
1406symbolS * last_label_seen;
1407static int label_is_thumb_function_name = false;
1408
1409/* Literal stuff. */
1410
1411#define MAX_LITERAL_POOL_SIZE 1024
1412
1413typedef struct literalS
1414{
1415 struct expressionS exp;
1416 struct arm_it * inst;
1417} literalT;
1418
1419literalT literals[MAX_LITERAL_POOL_SIZE];
1420
1421/* Next free entry in the pool. */
1422int next_literal_pool_place = 0;
1423
1424/* Next literal pool number. */
1425int lit_pool_num = 1;
1426
1427symbolS * current_poolP = NULL;
1428
1429static int
1430add_to_lit_pool ()
1431{
1432 int lit_count = 0;
1433
1434 if (current_poolP == NULL)
1435 current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section,
1436 (valueT) 0, &zero_address_frag);
1437
1438 /* Check if this literal value is already in the pool: */
1439 while (lit_count < next_literal_pool_place)
1440 {
1441 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
1442 && inst.reloc.exp.X_op == O_constant
1443 && (literals[lit_count].exp.X_add_number
1444 == inst.reloc.exp.X_add_number)
1445 && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
1446 break;
1447
1448 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
1449 && inst.reloc.exp.X_op == O_symbol
1450 && (literals[lit_count].exp.X_add_number
1451 == inst.reloc.exp.X_add_number)
1452 && (literals[lit_count].exp.X_add_symbol
1453 == inst.reloc.exp.X_add_symbol)
1454 && (literals[lit_count].exp.X_op_symbol
1455 == inst.reloc.exp.X_op_symbol))
1456 break;
1457
1458 lit_count++;
1459 }
1460
1461 if (lit_count == next_literal_pool_place) /* New entry. */
1462 {
1463 if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE)
1464 {
1465 inst.error = _("Literal Pool Overflow");
1466 return FAIL;
1467 }
1468
1469 literals[next_literal_pool_place].exp = inst.reloc.exp;
1470 lit_count = next_literal_pool_place++;
1471 }
1472
1473 inst.reloc.exp.X_op = O_symbol;
1474 inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
1475 inst.reloc.exp.X_add_symbol = current_poolP;
1476
1477 return SUCCESS;
1478}
1479
1480/* Can't use symbol_new here, so have to create a symbol and then at
1481 a later date assign it a value. Thats what these functions do. */
1482
1483static void
1484symbol_locate (symbolP, name, segment, valu, frag)
1485 symbolS * symbolP;
1486 CONST char * name; /* It is copied, the caller can modify. */
1487 segT segment; /* Segment identifier (SEG_<something>). */
1488 valueT valu; /* Symbol value. */
1489 fragS * frag; /* Associated fragment. */
1490{
1491 unsigned int name_length;
1492 char * preserved_copy_of_name;
1493
1494 name_length = strlen (name) + 1; /* +1 for \0. */
1495 obstack_grow (&notes, name, name_length);
1496 preserved_copy_of_name = obstack_finish (&notes);
1497#ifdef STRIP_UNDERSCORE
1498 if (preserved_copy_of_name[0] == '_')
1499 preserved_copy_of_name++;
1500#endif
1501
1502#ifdef tc_canonicalize_symbol_name
1503 preserved_copy_of_name =
1504 tc_canonicalize_symbol_name (preserved_copy_of_name);
1505#endif
1506
1507 S_SET_NAME (symbolP, preserved_copy_of_name);
1508
1509 S_SET_SEGMENT (symbolP, segment);
1510 S_SET_VALUE (symbolP, valu);
1511 symbol_clear_list_pointers(symbolP);
1512
1513 symbol_set_frag (symbolP, frag);
1514
1515 /* Link to end of symbol chain. */
1516 {
1517 extern int symbol_table_frozen;
1518 if (symbol_table_frozen)
1519 abort ();
1520 }
1521
1522 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1523
1524 obj_symbol_new_hook (symbolP);
1525
1526#ifdef tc_symbol_new_hook
1527 tc_symbol_new_hook (symbolP);
1528#endif
1529
1530#ifdef DEBUG_SYMS
1531 verify_symbol_chain (symbol_rootP, symbol_lastP);
1532#endif /* DEBUG_SYMS */
1533}
1534
1535/* Check that an immediate is valid.
1536 If so, convert it to the right format. */
1537
1538static unsigned int
1539validate_immediate (val)
1540 unsigned int val;
1541{
1542 unsigned int a;
1543 unsigned int i;
1544
1545#define rotate_left(v, n) (v << n | v >> (32 - n))
1546
1547 for (i = 0; i < 32; i += 2)
1548 if ((a = rotate_left (val, i)) <= 0xff)
1549 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1550
1551 return FAIL;
1552}
1553
1554/* Check to see if an immediate can be computed as two seperate immediate
1555 values, added together. We already know that this value cannot be
1556 computed by just one ARM instruction. */
1557
1558static unsigned int
1559validate_immediate_twopart (val, highpart)
1560 unsigned int val;
1561 unsigned int * highpart;
1562{
1563 unsigned int a;
1564 unsigned int i;
1565
1566 for (i = 0; i < 32; i += 2)
1567 if (((a = rotate_left (val, i)) & 0xff) != 0)
1568 {
1569 if (a & 0xff00)
1570 {
1571 if (a & ~ 0xffff)
1572 continue;
1573 * highpart = (a >> 8) | ((i + 24) << 7);
1574 }
1575 else if (a & 0xff0000)
1576 {
1577 if (a & 0xff000000)
1578 continue;
1579 * highpart = (a >> 16) | ((i + 16) << 7);
1580 }
1581 else
1582 {
1583 assert (a & 0xff000000);
1584 * highpart = (a >> 24) | ((i + 8) << 7);
1585 }
1586
1587 return (a & 0xff) | (i << 7);
1588 }
1589
1590 return FAIL;
1591}
1592
1593static int
1594validate_offset_imm (val, hwse)
1595 unsigned int val;
1596 int hwse;
1597{
1598 if ((hwse && val > 255) || val > 4095)
1599 return FAIL;
1600 return val;
1601}
1602
1603static void
1604s_req (a)
1605 int a ATTRIBUTE_UNUSED;
1606{
1607 as_bad (_("Invalid syntax for .req directive."));
1608}
1609
1610static void
1611s_bss (ignore)
1612 int ignore ATTRIBUTE_UNUSED;
1613{
1614 /* We don't support putting frags in the BSS segment, we fake it by
1615 marking in_bss, then looking at s_skip for clues. */
1616 subseg_set (bss_section, 0);
1617 demand_empty_rest_of_line ();
1618}
1619
1620static void
1621s_even (ignore)
1622 int ignore ATTRIBUTE_UNUSED;
1623{
1624 /* Never make frag if expect extra pass. */
1625 if (!need_pass_2)
1626 frag_align (1, 0, 0);
1627
1628 record_alignment (now_seg, 1);
1629
1630 demand_empty_rest_of_line ();
1631}
1632
1633static void
1634s_ltorg (ignored)
1635 int ignored ATTRIBUTE_UNUSED;
1636{
1637 int lit_count = 0;
1638 char sym_name[20];
1639
1640 if (current_poolP == NULL)
1641 return;
1642
1643 /* Align pool as you have word accesses.
1644 Only make a frag if we have to. */
1645 if (!need_pass_2)
1646 frag_align (2, 0, 0);
1647
1648 record_alignment (now_seg, 2);
1649
1650 sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
1651
1652 symbol_locate (current_poolP, sym_name, now_seg,
1653 (valueT) frag_now_fix (), frag_now);
1654 symbol_table_insert (current_poolP);
1655
1656 ARM_SET_THUMB (current_poolP, thumb_mode);
1657
1658#if defined OBJ_COFF || defined OBJ_ELF
1659 ARM_SET_INTERWORK (current_poolP, support_interwork);
1660#endif
1661
1662 while (lit_count < next_literal_pool_place)
1663 /* First output the expression in the instruction to the pool. */
1664 emit_expr (&(literals[lit_count++].exp), 4); /* .word */
1665
1666 next_literal_pool_place = 0;
1667 current_poolP = NULL;
1668}
1669
1670/* Same as s_align_ptwo but align 0 => align 2. */
1671
1672static void
1673s_align (unused)
1674 int unused ATTRIBUTE_UNUSED;
1675{
1676 register int temp;
1677 register long temp_fill;
1678 long max_alignment = 15;
1679
1680 temp = get_absolute_expression ();
1681 if (temp > max_alignment)
1682 as_bad (_("Alignment too large: %d. assumed."), temp = max_alignment);
1683 else if (temp < 0)
1684 {
1685 as_bad (_("Alignment negative. 0 assumed."));
1686 temp = 0;
1687 }
1688
1689 if (*input_line_pointer == ',')
1690 {
1691 input_line_pointer++;
1692 temp_fill = get_absolute_expression ();
1693 }
1694 else
1695 temp_fill = 0;
1696
1697 if (!temp)
1698 temp = 2;
1699
1700 /* Only make a frag if we HAVE to. */
1701 if (temp && !need_pass_2)
1702 frag_align (temp, (int) temp_fill, 0);
1703 demand_empty_rest_of_line ();
1704
1705 record_alignment (now_seg, temp);
1706}
1707
1708static void
1709s_force_thumb (ignore)
1710 int ignore ATTRIBUTE_UNUSED;
1711{
1712 /* If we are not already in thumb mode go into it, EVEN if
1713 the target processor does not support thumb instructions.
1714 This is used by gcc/config/arm/lib1funcs.asm for example
1715 to compile interworking support functions even if the
1716 target processor should not support interworking. */
1717 if (! thumb_mode)
1718 {
1719 thumb_mode = 2;
1720
1721 record_alignment (now_seg, 1);
1722 }
1723
1724 demand_empty_rest_of_line ();
1725}
1726
1727static void
1728s_thumb_func (ignore)
1729 int ignore ATTRIBUTE_UNUSED;
1730{
1731 if (! thumb_mode)
1732 opcode_select (16);
1733
1734 /* The following label is the name/address of the start of a Thumb function.
1735 We need to know this for the interworking support. */
1736 label_is_thumb_function_name = true;
1737
1738 demand_empty_rest_of_line ();
1739}
1740
1741/* Perform a .set directive, but also mark the alias as
1742 being a thumb function. */
1743
1744static void
1745s_thumb_set (equiv)
1746 int equiv;
1747{
1748 /* XXX the following is a duplicate of the code for s_set() in read.c
1749 We cannot just call that code as we need to get at the symbol that
1750 is created. */
1751 register char * name;
1752 register char delim;
1753 register char * end_name;
1754 register symbolS * symbolP;
1755
1756 /* Especial apologies for the random logic:
1757 This just grew, and could be parsed much more simply!
1758 Dean - in haste. */
1759 name = input_line_pointer;
1760 delim = get_symbol_end ();
1761 end_name = input_line_pointer;
1762 *end_name = delim;
1763
1764 SKIP_WHITESPACE ();
1765
1766 if (*input_line_pointer != ',')
1767 {
1768 *end_name = 0;
1769 as_bad (_("Expected comma after name \"%s\""), name);
1770 *end_name = delim;
1771 ignore_rest_of_line ();
1772 return;
1773 }
1774
1775 input_line_pointer++;
1776 *end_name = 0;
1777
1778 if (name[0] == '.' && name[1] == '\0')
1779 {
1780 /* XXX - this should not happen to .thumb_set. */
1781 abort ();
1782 }
1783
1784 if ((symbolP = symbol_find (name)) == NULL
1785 && (symbolP = md_undefined_symbol (name)) == NULL)
1786 {
1787#ifndef NO_LISTING
1788 /* When doing symbol listings, play games with dummy fragments living
1789 outside the normal fragment chain to record the file and line info
1790 for this symbol. */
1791 if (listing & LISTING_SYMBOLS)
1792 {
1793 extern struct list_info_struct * listing_tail;
1794 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
1795
1796 memset (dummy_frag, 0, sizeof (fragS));
1797 dummy_frag->fr_type = rs_fill;
1798 dummy_frag->line = listing_tail;
1799 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1800 dummy_frag->fr_symbol = symbolP;
1801 }
1802 else
1803#endif
1804 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1805
1806#ifdef OBJ_COFF
1807 /* "set" symbols are local unless otherwise specified. */
1808 SF_SET_LOCAL (symbolP);
1809#endif /* OBJ_COFF */
1810 } /* Make a new symbol. */
1811
1812 symbol_table_insert (symbolP);
1813
1814 * end_name = delim;
1815
1816 if (equiv
1817 && S_IS_DEFINED (symbolP)
1818 && S_GET_SEGMENT (symbolP) != reg_section)
1819 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1820
1821 pseudo_set (symbolP);
1822
1823 demand_empty_rest_of_line ();
1824
1825 /* XXX Now we come to the Thumb specific bit of code. */
1826
1827 THUMB_SET_FUNC (symbolP, 1);
1828 ARM_SET_THUMB (symbolP, 1);
1829#if defined OBJ_ELF || defined OBJ_COFF
1830 ARM_SET_INTERWORK (symbolP, support_interwork);
1831#endif
1832}
1833
1834/* If we change section we must dump the literal pool first. */
1835
1836static void
1837arm_s_text (ignore)
1838 int ignore;
1839{
1840 if (now_seg != text_section)
1841 s_ltorg (0);
1842
1843#ifdef OBJ_ELF
1844 obj_elf_text (ignore);
1845#else
1846 s_text (ignore);
1847#endif
1848}
1849
1850static void
1851arm_s_data (ignore)
1852 int ignore;
1853{
1854 if (flag_readonly_data_in_text)
1855 {
1856 if (now_seg != text_section)
1857 s_ltorg (0);
1858 }
1859 else if (now_seg != data_section)
1860 s_ltorg (0);
1861
1862#ifdef OBJ_ELF
1863 obj_elf_data (ignore);
1864#else
1865 s_data (ignore);
1866#endif
1867}
1868
1869#ifdef OBJ_ELF
1870static void
1871arm_s_section (ignore)
1872 int ignore;
1873{
1874 s_ltorg (0);
1875
1876 obj_elf_section (ignore);
1877}
1878#endif
1879
1880static void
1881opcode_select (width)
1882 int width;
1883{
1884 switch (width)
1885 {
1886 case 16:
1887 if (! thumb_mode)
1888 {
1889 if (! (cpu_variant & ARM_EXT_THUMB))
1890 as_bad (_("selected processor does not support THUMB opcodes"));
1891
1892 thumb_mode = 1;
1893 /* No need to force the alignment, since we will have been
1894 coming from ARM mode, which is word-aligned. */
1895 record_alignment (now_seg, 1);
1896 }
1897 break;
1898
1899 case 32:
1900 if (thumb_mode)
1901 {
1902 if ((cpu_variant & ARM_ANY) == ARM_EXT_THUMB)
1903 as_bad (_("selected processor does not support ARM opcodes"));
1904
1905 thumb_mode = 0;
1906
1907 if (!need_pass_2)
1908 frag_align (2, 0, 0);
1909
1910 record_alignment (now_seg, 1);
1911 }
1912 break;
1913
1914 default:
1915 as_bad (_("invalid instruction size selected (%d)"), width);
1916 }
1917}
1918
1919static void
1920s_arm (ignore)
1921 int ignore ATTRIBUTE_UNUSED;
1922{
1923 opcode_select (32);
1924 demand_empty_rest_of_line ();
1925}
1926
1927static void
1928s_thumb (ignore)
1929 int ignore ATTRIBUTE_UNUSED;
1930{
1931 opcode_select (16);
1932 demand_empty_rest_of_line ();
1933}
1934
1935static void
1936s_code (unused)
1937 int unused ATTRIBUTE_UNUSED;
1938{
1939 register int temp;
1940
1941 temp = get_absolute_expression ();
1942 switch (temp)
1943 {
1944 case 16:
1945 case 32:
1946 opcode_select (temp);
1947 break;
1948
1949 default:
1950 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1951 }
1952}
1953
1954static void
1955end_of_line (str)
1956 char * str;
1957{
1958 skip_whitespace (str);
1959
1960 if (* str != '\0')
1961 inst.error = _("Garbage following instruction");
1962}
1963
1964static int
1965skip_past_comma (str)
1966 char ** str;
1967{
1968 char * p = * str, c;
1969 int comma = 0;
1970
1971 while ((c = *p) == ' ' || c == ',')
1972 {
1973 p++;
1974 if (c == ',' && comma++)
1975 return FAIL;
1976 }
1977
1978 if (c == '\0')
1979 return FAIL;
1980
1981 *str = p;
1982 return comma ? SUCCESS : FAIL;
1983}
1984
1985/* A standard register must be given at this point.
1986 SHIFT is the place to put it in inst.instruction.
1987 Restores input start point on error.
1988 Returns the reg#, or FAIL. */
1989
1990static int
1991reg_required_here (str, shift)
1992 char ** str;
1993 int shift;
1994{
1995 static char buff [128]; /* XXX */
1996 int reg;
1997 char * start = * str;
1998
1999 if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
2000 {
2001 if (shift >= 0)
2002 inst.instruction |= reg << shift;
2003 return reg;
2004 }
2005
2006 /* Restore the start point, we may have got a reg of the wrong class. */
2007 *str = start;
2008
2009 /* In the few cases where we might be able to accept something else
2010 this error can be overridden. */
2011 sprintf (buff, _("Register expected, not '%.100s'"), start);
2012 inst.error = buff;
2013
2014 return FAIL;
2015}
2016
2017static CONST struct asm_psr *
2018arm_psr_parse (ccp)
2019 register char ** ccp;
2020{
2021 char * start = * ccp;
2022 char c;
2023 char * p;
2024 CONST struct asm_psr * psr;
2025
2026 p = start;
2027
2028 /* Skip to the end of the next word in the input stream. */
2029 do
2030 {
2031 c = *p++;
2032 }
3882b010 2033 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2034
2035 /* Terminate the word. */
2036 *--p = 0;
2037
2038 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2039 feature for ease of use and backwards compatibility. */
2040 if (!strncmp (start, "cpsr", 4))
2041 strncpy (start, "CPSR", 4);
2042 else if (!strncmp (start, "spsr", 4))
2043 strncpy (start, "SPSR", 4);
2044
2045 /* Now locate the word in the psr hash table. */
2046 psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
2047
2048 /* Restore the input stream. */
2049 *p = c;
2050
2051 /* If we found a valid match, advance the
2052 stream pointer past the end of the word. */
2053 *ccp = p;
2054
2055 return psr;
2056}
2057
2058/* Parse the input looking for a PSR flag. */
2059
2060static int
2061psr_required_here (str)
2062 char ** str;
2063{
2064 char * start = * str;
2065 CONST struct asm_psr * psr;
2066
2067 psr = arm_psr_parse (str);
2068
2069 if (psr)
2070 {
2071 /* If this is the SPSR that is being modified, set the R bit. */
2072 if (! psr->cpsr)
2073 inst.instruction |= SPSR_BIT;
2074
2075 /* Set the psr flags in the MSR instruction. */
2076 inst.instruction |= psr->field << PSR_SHIFT;
2077
2078 return SUCCESS;
2079 }
2080
2081 /* In the few cases where we might be able to accept
2082 something else this error can be overridden. */
2083 inst.error = _("flag for {c}psr instruction expected");
2084
2085 /* Restore the start point. */
2086 *str = start;
2087 return FAIL;
2088}
2089
2090static int
2091co_proc_number (str)
2092 char ** str;
2093{
2094 int processor, pchar;
2095
2096 skip_whitespace (* str);
2097
2098 /* The data sheet seems to imply that just a number on its own is valid
2099 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2100 accept either. */
2101 if (**str == 'p' || **str == 'P')
2102 (*str)++;
2103
2104 pchar = *(*str)++;
2105 if (pchar >= '0' && pchar <= '9')
2106 {
2107 processor = pchar - '0';
2108 if (**str >= '0' && **str <= '9')
2109 {
2110 processor = processor * 10 + *(*str)++ - '0';
2111 if (processor > 15)
2112 {
2113 inst.error = _("Illegal co-processor number");
2114 return FAIL;
2115 }
2116 }
2117 }
2118 else
2119 {
2120 inst.error = _("Bad or missing co-processor number");
2121 return FAIL;
2122 }
2123
2124 inst.instruction |= processor << 8;
2125 return SUCCESS;
2126}
2127
2128static int
2129cp_opc_expr (str, where, length)
2130 char ** str;
2131 int where;
2132 int length;
2133{
2134 expressionS expr;
2135
2136 skip_whitespace (* str);
2137
2138 memset (&expr, '\0', sizeof (expr));
2139
2140 if (my_get_expression (&expr, str))
2141 return FAIL;
2142 if (expr.X_op != O_constant)
2143 {
2144 inst.error = _("bad or missing expression");
2145 return FAIL;
2146 }
2147
2148 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2149 {
2150 inst.error = _("immediate co-processor expression too large");
2151 return FAIL;
2152 }
2153
2154 inst.instruction |= expr.X_add_number << where;
2155 return SUCCESS;
2156}
2157
2158static int
2159cp_reg_required_here (str, where)
2160 char ** str;
2161 int where;
2162{
2163 int reg;
2164 char * start = *str;
2165
2166 if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
2167 {
2168 reg &= 15;
2169 inst.instruction |= reg << where;
2170 return reg;
2171 }
2172
2173 /* In the few cases where we might be able to accept something else
2174 this error can be overridden. */
2175 inst.error = _("Co-processor register expected");
2176
2177 /* Restore the start point. */
2178 *str = start;
2179 return FAIL;
2180}
2181
2182static int
2183fp_reg_required_here (str, where)
2184 char ** str;
2185 int where;
2186{
2187 int reg;
2188 char * start = * str;
2189
2190 if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
2191 {
2192 reg &= 7;
2193 inst.instruction |= reg << where;
2194 return reg;
2195 }
2196
2197 /* In the few cases where we might be able to accept something else
2198 this error can be overridden. */
2199 inst.error = _("Floating point register expected");
2200
2201 /* Restore the start point. */
2202 *str = start;
2203 return FAIL;
2204}
2205
2206static int
2207cp_address_offset (str)
2208 char ** str;
2209{
2210 int offset;
2211
2212 skip_whitespace (* str);
2213
2214 if (! is_immediate_prefix (**str))
2215 {
2216 inst.error = _("immediate expression expected");
2217 return FAIL;
2218 }
2219
2220 (*str)++;
2221
2222 if (my_get_expression (& inst.reloc.exp, str))
2223 return FAIL;
2224
2225 if (inst.reloc.exp.X_op == O_constant)
2226 {
2227 offset = inst.reloc.exp.X_add_number;
2228
2229 if (offset & 3)
2230 {
2231 inst.error = _("co-processor address must be word aligned");
2232 return FAIL;
2233 }
2234
2235 if (offset > 1023 || offset < -1023)
2236 {
2237 inst.error = _("offset too large");
2238 return FAIL;
2239 }
2240
2241 if (offset >= 0)
2242 inst.instruction |= INDEX_UP;
2243 else
2244 offset = -offset;
2245
2246 inst.instruction |= offset >> 2;
2247 }
2248 else
2249 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2250
2251 return SUCCESS;
2252}
2253
2254static int
2255cp_address_required_here (str)
2256 char ** str;
2257{
2258 char * p = * str;
2259 int pre_inc = 0;
2260 int write_back = 0;
2261
2262 if (*p == '[')
2263 {
2264 int reg;
2265
2266 p++;
2267 skip_whitespace (p);
2268
2269 if ((reg = reg_required_here (& p, 16)) == FAIL)
2270 return FAIL;
2271
2272 skip_whitespace (p);
2273
2274 if (*p == ']')
2275 {
2276 p++;
2277
2278 if (skip_past_comma (& p) == SUCCESS)
2279 {
2280 /* [Rn], #expr */
2281 write_back = WRITE_BACK;
2282
2283 if (reg == REG_PC)
2284 {
2285 inst.error = _("pc may not be used in post-increment");
2286 return FAIL;
2287 }
2288
2289 if (cp_address_offset (& p) == FAIL)
2290 return FAIL;
2291 }
2292 else
2293 pre_inc = PRE_INDEX | INDEX_UP;
2294 }
2295 else
2296 {
2297 /* '['Rn, #expr']'[!] */
2298
2299 if (skip_past_comma (& p) == FAIL)
2300 {
2301 inst.error = _("pre-indexed expression expected");
2302 return FAIL;
2303 }
2304
2305 pre_inc = PRE_INDEX;
2306
2307 if (cp_address_offset (& p) == FAIL)
2308 return FAIL;
2309
2310 skip_whitespace (p);
2311
2312 if (*p++ != ']')
2313 {
2314 inst.error = _("missing ]");
2315 return FAIL;
2316 }
2317
2318 skip_whitespace (p);
2319
2320 if (*p == '!')
2321 {
2322 if (reg == REG_PC)
2323 {
2324 inst.error = _("pc may not be used with write-back");
2325 return FAIL;
2326 }
2327
2328 p++;
2329 write_back = WRITE_BACK;
2330 }
2331 }
2332 }
2333 else
2334 {
2335 if (my_get_expression (&inst.reloc.exp, &p))
2336 return FAIL;
2337
2338 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2339 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2340 inst.reloc.pc_rel = 1;
2341 inst.instruction |= (REG_PC << 16);
2342 pre_inc = PRE_INDEX;
2343 }
2344
2345 inst.instruction |= write_back | pre_inc;
2346 *str = p;
2347 return SUCCESS;
2348}
2349
2350static void
2351do_nop (str, flags)
2352 char * str;
2353 unsigned long flags;
2354{
2355 /* Do nothing really. */
2356 inst.instruction |= flags; /* This is pointless. */
2357 end_of_line (str);
2358 return;
2359}
2360
2361static void
2362do_mrs (str, flags)
2363 char *str;
2364 unsigned long flags;
2365{
2366 int skip = 0;
2367
2368 /* Only one syntax. */
2369 skip_whitespace (str);
2370
2371 if (reg_required_here (&str, 12) == FAIL)
2372 {
2373 inst.error = BAD_ARGS;
2374 return;
2375 }
2376
2377 if (skip_past_comma (&str) == FAIL)
2378 {
2379 inst.error = _("comma expected after register name");
2380 return;
2381 }
2382
2383 skip_whitespace (str);
2384
2385 if ( strcmp (str, "CPSR") == 0
2386 || strcmp (str, "SPSR") == 0
2387 /* Lower case versions for backwards compatability. */
2388 || strcmp (str, "cpsr") == 0
2389 || strcmp (str, "spsr") == 0)
2390 skip = 4;
2391
2392 /* This is for backwards compatability with older toolchains. */
2393 else if ( strcmp (str, "cpsr_all") == 0
2394 || strcmp (str, "spsr_all") == 0)
2395 skip = 8;
2396 else
2397 {
2398 inst.error = _("{C|S}PSR expected");
2399 return;
2400 }
2401
2402 if (* str == 's' || * str == 'S')
2403 inst.instruction |= SPSR_BIT;
2404 str += skip;
2405
2406 inst.instruction |= flags;
2407 end_of_line (str);
2408}
2409
2410/* Two possible forms:
2411 "{C|S}PSR_<field>, Rm",
2412 "{C|S}PSR_f, #expression". */
2413
2414static void
2415do_msr (str, flags)
2416 char * str;
2417 unsigned long flags;
2418{
2419 skip_whitespace (str);
2420
2421 if (psr_required_here (& str) == FAIL)
2422 return;
2423
2424 if (skip_past_comma (& str) == FAIL)
2425 {
2426 inst.error = _("comma missing after psr flags");
2427 return;
2428 }
2429
2430 skip_whitespace (str);
2431
2432 if (reg_required_here (& str, 0) != FAIL)
2433 {
2434 inst.error = NULL;
2435 inst.instruction |= flags;
2436 end_of_line (str);
2437 return;
2438 }
2439
2440 if (! is_immediate_prefix (* str))
2441 {
2442 inst.error =
2443 _("only a register or immediate value can follow a psr flag");
2444 return;
2445 }
2446
2447 str ++;
2448 inst.error = NULL;
2449
2450 if (my_get_expression (& inst.reloc.exp, & str))
2451 {
2452 inst.error =
2453 _("only a register or immediate value can follow a psr flag");
2454 return;
2455 }
2456
2457#if 0 /* The first edition of the ARM architecture manual stated that
2458 writing anything other than the flags with an immediate operation
2459 had UNPREDICTABLE effects. This constraint was removed in the
2460 second edition of the specification. */
2461 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2462 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2463 {
2464 inst.error = _("immediate value cannot be used to set this field");
2465 return;
2466 }
2467#endif
2468
2469 flags |= INST_IMMEDIATE;
2470
2471 if (inst.reloc.exp.X_add_symbol)
2472 {
2473 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2474 inst.reloc.pc_rel = 0;
2475 }
2476 else
2477 {
2478 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2479
2480 if (value == (unsigned) FAIL)
2481 {
2482 inst.error = _("Invalid constant");
2483 return;
2484 }
2485
2486 inst.instruction |= value;
2487 }
2488
2489 inst.error = NULL;
2490 inst.instruction |= flags;
2491 end_of_line (str);
2492}
2493
2494/* Long Multiply Parser
2495 UMULL RdLo, RdHi, Rm, Rs
2496 SMULL RdLo, RdHi, Rm, Rs
2497 UMLAL RdLo, RdHi, Rm, Rs
2498 SMLAL RdLo, RdHi, Rm, Rs. */
2499
2500static void
2501do_mull (str, flags)
2502 char * str;
2503 unsigned long flags;
2504{
2505 int rdlo, rdhi, rm, rs;
2506
2507 /* Only one format "rdlo, rdhi, rm, rs". */
2508 skip_whitespace (str);
2509
2510 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2511 {
2512 inst.error = BAD_ARGS;
2513 return;
2514 }
2515
2516 if (skip_past_comma (&str) == FAIL
2517 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2518 {
2519 inst.error = BAD_ARGS;
2520 return;
2521 }
2522
2523 if (skip_past_comma (&str) == FAIL
2524 || (rm = reg_required_here (&str, 0)) == FAIL)
2525 {
2526 inst.error = BAD_ARGS;
2527 return;
2528 }
2529
2530 /* rdhi, rdlo and rm must all be different. */
2531 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2532 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2533
2534 if (skip_past_comma (&str) == FAIL
2535 || (rs = reg_required_here (&str, 8)) == FAIL)
2536 {
2537 inst.error = BAD_ARGS;
2538 return;
2539 }
2540
2541 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2542 {
2543 inst.error = BAD_PC;
2544 return;
2545 }
2546
2547 inst.instruction |= flags;
2548 end_of_line (str);
2549 return;
2550}
2551
2552static void
2553do_mul (str, flags)
2554 char * str;
2555 unsigned long flags;
2556{
2557 int rd, rm;
2558
2559 /* Only one format "rd, rm, rs". */
2560 skip_whitespace (str);
2561
2562 if ((rd = reg_required_here (&str, 16)) == FAIL)
2563 {
2564 inst.error = BAD_ARGS;
2565 return;
2566 }
2567
2568 if (rd == REG_PC)
2569 {
2570 inst.error = BAD_PC;
2571 return;
2572 }
2573
2574 if (skip_past_comma (&str) == FAIL
2575 || (rm = reg_required_here (&str, 0)) == FAIL)
2576 {
2577 inst.error = BAD_ARGS;
2578 return;
2579 }
2580
2581 if (rm == REG_PC)
2582 {
2583 inst.error = BAD_PC;
2584 return;
2585 }
2586
2587 if (rm == rd)
2588 as_tsktsk (_("rd and rm should be different in mul"));
2589
2590 if (skip_past_comma (&str) == FAIL
2591 || (rm = reg_required_here (&str, 8)) == FAIL)
2592 {
2593 inst.error = BAD_ARGS;
2594 return;
2595 }
2596
2597 if (rm == REG_PC)
2598 {
2599 inst.error = BAD_PC;
2600 return;
2601 }
2602
2603 inst.instruction |= flags;
2604 end_of_line (str);
2605 return;
2606}
2607
2608static void
2609do_mla (str, flags)
2610 char * str;
2611 unsigned long flags;
2612{
2613 int rd, rm;
2614
2615 /* Only one format "rd, rm, rs, rn". */
2616 skip_whitespace (str);
2617
2618 if ((rd = reg_required_here (&str, 16)) == FAIL)
2619 {
2620 inst.error = BAD_ARGS;
2621 return;
2622 }
2623
2624 if (rd == REG_PC)
2625 {
2626 inst.error = BAD_PC;
2627 return;
2628 }
2629
2630 if (skip_past_comma (&str) == FAIL
2631 || (rm = reg_required_here (&str, 0)) == FAIL)
2632 {
2633 inst.error = BAD_ARGS;
2634 return;
2635 }
2636
2637 if (rm == REG_PC)
2638 {
2639 inst.error = BAD_PC;
2640 return;
2641 }
2642
2643 if (rm == rd)
2644 as_tsktsk (_("rd and rm should be different in mla"));
2645
2646 if (skip_past_comma (&str) == FAIL
2647 || (rd = reg_required_here (&str, 8)) == FAIL
2648 || skip_past_comma (&str) == FAIL
2649 || (rm = reg_required_here (&str, 12)) == FAIL)
2650 {
2651 inst.error = BAD_ARGS;
2652 return;
2653 }
2654
2655 if (rd == REG_PC || rm == REG_PC)
2656 {
2657 inst.error = BAD_PC;
2658 return;
2659 }
2660
2661 inst.instruction |= flags;
2662 end_of_line (str);
2663 return;
2664}
2665
2666/* Expects *str -> the characters "acc0", possibly with leading blanks.
2667 Advances *str to the next non-alphanumeric.
2668 Returns 0, or else FAIL (in which case sets inst.error).
2669
2670 (In a future XScale, there may be accumulators other than zero.
2671 At that time this routine and its callers can be upgraded to suit.) */
2672
2673static int
2674accum0_required_here (str)
2675 char ** str;
2676{
2677 static char buff [128]; /* Note the address is taken. Hence, static. */
2678 char * p = * str;
2679 char c;
2680 int result = 0; /* The accum number. */
2681
2682 skip_whitespace (p);
2683
2684 *str = p; /* Advance caller's string pointer too. */
2685 c = *p++;
3882b010 2686 while (ISALNUM (c))
b99bd4ef
NC
2687 c = *p++;
2688
2689 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2690
2691 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2692 {
2693 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2694 inst.error = buff;
2695 result = FAIL;
2696 }
2697
2698 *p = c; /* Unzap. */
2699 *str = p; /* Caller's string pointer to after match. */
2700 return result;
2701}
2702
2703/* Expects **str -> after a comma. May be leading blanks.
2704 Advances *str, recognizing a load mode, and setting inst.instruction.
2705 Returns rn, or else FAIL (in which case may set inst.error
2706 and not advance str)
2707
2708 Note: doesn't know Rd, so no err checks that require such knowledge. */
2709
2710static int
2711ld_mode_required_here (string)
2712 char ** string;
2713{
2714 char * str = * string;
2715 int rn;
2716 int pre_inc = 0;
2717
2718 skip_whitespace (str);
2719
2720 if (* str == '[')
2721 {
2722 str++;
2723
2724 skip_whitespace (str);
2725
2726 if ((rn = reg_required_here (& str, 16)) == FAIL)
2727 return FAIL;
2728
2729 skip_whitespace (str);
2730
2731 if (* str == ']')
2732 {
2733 str ++;
2734
2735 if (skip_past_comma (& str) == SUCCESS)
2736 {
2737 /* [Rn],... (post inc) */
2738 if (ldst_extend (& str, 1) == FAIL)
2739 return FAIL;
2740 }
2741 else /* [Rn] */
2742 {
2743 skip_whitespace (str);
2744
2745 if (* str == '!')
2746 {
2747 str ++;
2748 inst.instruction |= WRITE_BACK;
2749 }
2750
2751 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
2752 pre_inc = 1;
2753 }
2754 }
2755 else /* [Rn,...] */
2756 {
2757 if (skip_past_comma (& str) == FAIL)
2758 {
2759 inst.error = _("pre-indexed expression expected");
2760 return FAIL;
2761 }
2762
2763 pre_inc = 1;
2764
2765 if (ldst_extend (& str, 1) == FAIL)
2766 return FAIL;
2767
2768 skip_whitespace (str);
2769
2770 if (* str ++ != ']')
2771 {
2772 inst.error = _("missing ]");
2773 return FAIL;
2774 }
2775
2776 skip_whitespace (str);
2777
2778 if (* str == '!')
2779 {
2780 str ++;
2781 inst.instruction |= WRITE_BACK;
2782 }
2783 }
2784 }
2785 else if (* str == '=') /* ldr's "r,=label" syntax */
2786 /* We should never reach here, because <text> = <expression> is
2787 caught gas/read.c read_a_source_file() as a .set operation. */
2788 return FAIL;
2789 else /* PC +- 8 bit immediate offset. */
2790 {
2791 if (my_get_expression (& inst.reloc.exp, & str))
2792 return FAIL;
2793
2794 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
2795 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2796 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2797 inst.reloc.pc_rel = 1;
2798 inst.instruction |= (REG_PC << 16);
2799
2800 rn = REG_PC;
2801 pre_inc = 1;
2802 }
2803
2804 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
2805 * string = str;
2806
2807 return rn;
2808}
2809
2810/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
2811 SMLAxy{cond} Rd,Rm,Rs,Rn
2812 SMLAWy{cond} Rd,Rm,Rs,Rn
2813 Error if any register is R15. */
2814
2815static void
2816do_smla (str, flags)
2817 char * str;
2818 unsigned long flags;
2819{
2820 int rd, rm, rs, rn;
2821
2822 skip_whitespace (str);
2823
2824 if ((rd = reg_required_here (& str, 16)) == FAIL
2825 || skip_past_comma (& str) == FAIL
2826 || (rm = reg_required_here (& str, 0)) == FAIL
2827 || skip_past_comma (& str) == FAIL
2828 || (rs = reg_required_here (& str, 8)) == FAIL
2829 || skip_past_comma (& str) == FAIL
2830 || (rn = reg_required_here (& str, 12)) == FAIL)
2831 inst.error = BAD_ARGS;
2832
2833 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
2834 inst.error = BAD_PC;
2835
2836 else if (flags)
2837 inst.error = BAD_FLAGS;
2838
2839 else
2840 end_of_line (str);
2841}
2842
2843/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
2844 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
2845 Error if any register is R15.
2846 Warning if Rdlo == Rdhi. */
2847
2848static void
2849do_smlal (str, flags)
2850 char * str;
2851 unsigned long flags;
2852{
2853 int rdlo, rdhi, rm, rs;
2854
2855 skip_whitespace (str);
2856
2857 if ((rdlo = reg_required_here (& str, 12)) == FAIL
2858 || skip_past_comma (& str) == FAIL
2859 || (rdhi = reg_required_here (& str, 16)) == FAIL
2860 || skip_past_comma (& str) == FAIL
2861 || (rm = reg_required_here (& str, 0)) == FAIL
2862 || skip_past_comma (& str) == FAIL
2863 || (rs = reg_required_here (& str, 8)) == FAIL)
2864 {
2865 inst.error = BAD_ARGS;
2866 return;
2867 }
2868
2869 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
2870 {
2871 inst.error = BAD_PC;
2872 return;
2873 }
2874
2875 if (rdlo == rdhi)
2876 as_tsktsk (_("rdhi and rdlo must be different"));
2877
2878 if (flags)
2879 inst.error = BAD_FLAGS;
2880 else
2881 end_of_line (str);
2882}
2883
2884/* ARM V5E (El Segundo) signed-multiply (argument parse)
2885 SMULxy{cond} Rd,Rm,Rs
2886 Error if any register is R15. */
2887
2888static void
2889do_smul (str, flags)
2890 char * str;
2891 unsigned long flags;
2892{
2893 int rd, rm, rs;
2894
2895 skip_whitespace (str);
2896
2897 if ((rd = reg_required_here (& str, 16)) == FAIL
2898 || skip_past_comma (& str) == FAIL
2899 || (rm = reg_required_here (& str, 0)) == FAIL
2900 || skip_past_comma (& str) == FAIL
2901 || (rs = reg_required_here (& str, 8)) == FAIL)
2902 inst.error = BAD_ARGS;
2903
2904 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
2905 inst.error = BAD_PC;
2906
2907 else if (flags)
2908 inst.error = BAD_FLAGS;
2909
2910 else
2911 end_of_line (str);
2912}
2913
2914/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
2915 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
2916 Error if any register is R15. */
2917
2918static void
2919do_qadd (str, flags)
2920 char * str;
2921 unsigned long flags;
2922{
2923 int rd, rm, rn;
2924
2925 skip_whitespace (str);
2926
2927 if ((rd = reg_required_here (& str, 12)) == FAIL
2928 || skip_past_comma (& str) == FAIL
2929 || (rm = reg_required_here (& str, 0)) == FAIL
2930 || skip_past_comma (& str) == FAIL
2931 || (rn = reg_required_here (& str, 16)) == FAIL)
2932 inst.error = BAD_ARGS;
2933
2934 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
2935 inst.error = BAD_PC;
2936
2937 else if (flags)
2938 inst.error = BAD_FLAGS;
2939
2940 else
2941 end_of_line (str);
2942}
2943
2944/* ARM V5E (el Segundo)
2945 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
2946 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
2947
2948 These are equivalent to the XScale instructions MAR and MRA,
2949 respectively, when coproc == 0, opcode == 0, and CRm == 0.
2950
2951 Result unpredicatable if Rd or Rn is R15. */
2952
2953static void
2954do_co_reg2c (str, flags)
2955 char * str;
2956 unsigned long flags;
2957{
2958 int rd, rn;
2959
2960 skip_whitespace (str);
2961
2962 if (co_proc_number (& str) == FAIL)
2963 {
2964 if (!inst.error)
2965 inst.error = BAD_ARGS;
2966 return;
2967 }
2968
2969 if (skip_past_comma (& str) == FAIL
2970 || cp_opc_expr (& str, 4, 4) == FAIL)
2971 {
2972 if (!inst.error)
2973 inst.error = BAD_ARGS;
2974 return;
2975 }
2976
2977 if (skip_past_comma (& str) == FAIL
2978 || (rd = reg_required_here (& str, 12)) == FAIL)
2979 {
2980 if (!inst.error)
2981 inst.error = BAD_ARGS;
2982 return;
2983 }
2984
2985 if (skip_past_comma (& str) == FAIL
2986 || (rn = reg_required_here (& str, 16)) == FAIL)
2987 {
2988 if (!inst.error)
2989 inst.error = BAD_ARGS;
2990 return;
2991 }
2992
2993 /* Unpredictable result if rd or rn is R15. */
2994 if (rd == REG_PC || rn == REG_PC)
2995 as_tsktsk
2996 (_("Warning: Instruction unpredictable when using r15"));
2997
2998 if (skip_past_comma (& str) == FAIL
2999 || cp_reg_required_here (& str, 0) == FAIL)
3000 {
3001 if (!inst.error)
3002 inst.error = BAD_ARGS;
3003 return;
3004 }
3005
3006 if (flags)
3007 inst.error = BAD_COND;
3008
3009 end_of_line (str);
3010}
3011
3012/* ARM V5 count-leading-zeroes instruction (argument parse)
3013 CLZ{<cond>} <Rd>, <Rm>
3014 Condition defaults to COND_ALWAYS.
3015 Error if Rd or Rm are R15. */
3016
3017static void
3018do_clz (str, flags)
3019 char * str;
3020 unsigned long flags;
3021{
3022 int rd, rm;
3023
3024 if (flags)
3025 {
3026 as_bad (BAD_FLAGS);
3027 return;
3028 }
3029
3030 skip_whitespace (str);
3031
3032 if (((rd = reg_required_here (& str, 12)) == FAIL)
3033 || (skip_past_comma (& str) == FAIL)
3034 || ((rm = reg_required_here (& str, 0)) == FAIL))
3035 inst.error = BAD_ARGS;
3036
3037 else if (rd == REG_PC || rm == REG_PC )
3038 inst.error = BAD_PC;
3039
3040 else
3041 end_of_line (str);
3042}
3043
3044/* ARM V5 (argument parse)
3045 LDC2{L} <coproc>, <CRd>, <addressing mode>
3046 STC2{L} <coproc>, <CRd>, <addressing mode>
3047 Instruction is not conditional, and has 0xf in the codition field.
3048 Otherwise, it's the same as LDC/STC. */
3049
3050static void
3051do_lstc2 (str, flags)
3052 char * str;
3053 unsigned long flags;
3054{
3055 if (flags)
3056 inst.error = BAD_COND;
3057
3058 skip_whitespace (str);
3059
3060 if (co_proc_number (& str) == FAIL)
3061 {
3062 if (!inst.error)
3063 inst.error = BAD_ARGS;
3064 }
3065 else if (skip_past_comma (& str) == FAIL
3066 || cp_reg_required_here (& str, 12) == FAIL)
3067 {
3068 if (!inst.error)
3069 inst.error = BAD_ARGS;
3070 }
3071 else if (skip_past_comma (& str) == FAIL
3072 || cp_address_required_here (& str) == FAIL)
3073 {
3074 if (! inst.error)
3075 inst.error = BAD_ARGS;
3076 }
3077 else
3078 end_of_line (str);
3079}
3080
3081/* ARM V5 (argument parse)
3082 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3083 Instruction is not conditional, and has 0xf in the condition field.
3084 Otherwise, it's the same as CDP. */
3085
3086static void
3087do_cdp2 (str, flags)
3088 char * str;
3089 unsigned long flags;
3090{
3091 skip_whitespace (str);
3092
3093 if (co_proc_number (& str) == FAIL)
3094 {
3095 if (!inst.error)
3096 inst.error = BAD_ARGS;
3097 return;
3098 }
3099
3100 if (skip_past_comma (& str) == FAIL
3101 || cp_opc_expr (& str, 20,4) == FAIL)
3102 {
3103 if (!inst.error)
3104 inst.error = BAD_ARGS;
3105 return;
3106 }
3107
3108 if (skip_past_comma (& str) == FAIL
3109 || cp_reg_required_here (& str, 12) == FAIL)
3110 {
3111 if (!inst.error)
3112 inst.error = BAD_ARGS;
3113 return;
3114 }
3115
3116 if (skip_past_comma (& str) == FAIL
3117 || cp_reg_required_here (& str, 16) == FAIL)
3118 {
3119 if (!inst.error)
3120 inst.error = BAD_ARGS;
3121 return;
3122 }
3123
3124 if (skip_past_comma (& str) == FAIL
3125 || cp_reg_required_here (& str, 0) == FAIL)
3126 {
3127 if (!inst.error)
3128 inst.error = BAD_ARGS;
3129 return;
3130 }
3131
3132 if (skip_past_comma (& str) == SUCCESS)
3133 {
3134 if (cp_opc_expr (& str, 5, 3) == FAIL)
3135 {
3136 if (!inst.error)
3137 inst.error = BAD_ARGS;
3138 return;
3139 }
3140 }
3141
3142 if (flags)
3143 inst.error = BAD_FLAGS;
3144
3145 end_of_line (str);
3146}
3147
3148/* ARM V5 (argument parse)
3149 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3150 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3151 Instruction is not conditional, and has 0xf in the condition field.
3152 Otherwise, it's the same as MCR/MRC. */
3153
3154static void
3155do_co_reg2 (str, flags)
3156 char * str;
3157 unsigned long flags;
3158{
3159 skip_whitespace (str);
3160
3161 if (co_proc_number (& str) == FAIL)
3162 {
3163 if (!inst.error)
3164 inst.error = BAD_ARGS;
3165 return;
3166 }
3167
3168 if (skip_past_comma (& str) == FAIL
3169 || cp_opc_expr (& str, 21, 3) == FAIL)
3170 {
3171 if (!inst.error)
3172 inst.error = BAD_ARGS;
3173 return;
3174 }
3175
3176 if (skip_past_comma (& str) == FAIL
3177 || reg_required_here (& str, 12) == FAIL)
3178 {
3179 if (!inst.error)
3180 inst.error = BAD_ARGS;
3181 return;
3182 }
3183
3184 if (skip_past_comma (& str) == FAIL
3185 || cp_reg_required_here (& str, 16) == FAIL)
3186 {
3187 if (!inst.error)
3188 inst.error = BAD_ARGS;
3189 return;
3190 }
3191
3192 if (skip_past_comma (& str) == FAIL
3193 || cp_reg_required_here (& str, 0) == FAIL)
3194 {
3195 if (!inst.error)
3196 inst.error = BAD_ARGS;
3197 return;
3198 }
3199
3200 if (skip_past_comma (& str) == SUCCESS)
3201 {
3202 if (cp_opc_expr (& str, 5, 3) == FAIL)
3203 {
3204 if (!inst.error)
3205 inst.error = BAD_ARGS;
3206 return;
3207 }
3208 }
3209
3210 if (flags)
3211 inst.error = BAD_COND;
3212
3213 end_of_line (str);
3214}
3215
3216/* THUMB V5 breakpoint instruction (argument parse)
3217 BKPT <immed_8>. */
3218
3219static void
3220do_t_bkpt (str)
3221 char * str;
3222{
3223 expressionS expr;
3224 unsigned long number;
3225
3226 skip_whitespace (str);
3227
3228 /* Allow optional leading '#'. */
3229 if (is_immediate_prefix (*str))
3230 str ++;
3231
3232 memset (& expr, '\0', sizeof (expr));
3233 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3234 {
3235 inst.error = _("bad or missing expression");
3236 return;
3237 }
3238
3239 number = expr.X_add_number;
3240
3241 /* Check it fits an 8 bit unsigned. */
3242 if (number != (number & 0xff))
3243 {
3244 inst.error = _("immediate value out of range");
3245 return;
3246 }
3247
3248 inst.instruction |= number;
3249
3250 end_of_line (str);
3251}
3252
3253/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3254 Expects inst.instruction is set for BLX(1).
3255 Note: this is cloned from do_branch, and the reloc changed to be a
3256 new one that can cope with setting one extra bit (the H bit). */
3257
3258static void
3259do_branch25 (str, flags)
3260 char * str;
3261 unsigned long flags ATTRIBUTE_UNUSED;
3262{
3263 if (my_get_expression (& inst.reloc.exp, & str))
3264 return;
3265
3266#ifdef OBJ_ELF
3267 {
3268 char * save_in;
3269
3270 /* ScottB: February 5, 1998 */
3271 /* Check to see of PLT32 reloc required for the instruction. */
3272
3273 /* arm_parse_reloc() works on input_line_pointer.
3274 We actually want to parse the operands to the branch instruction
3275 passed in 'str'. Save the input pointer and restore it later. */
3276 save_in = input_line_pointer;
3277 input_line_pointer = str;
3278
3279 if (inst.reloc.exp.X_op == O_symbol
3280 && *str == '('
3281 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
3282 {
3283 inst.reloc.type = BFD_RELOC_ARM_PLT32;
3284 inst.reloc.pc_rel = 0;
3285 /* Modify str to point to after parsed operands, otherwise
3286 end_of_line() will complain about the (PLT) left in str. */
3287 str = input_line_pointer;
3288 }
3289 else
3290 {
3291 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3292 inst.reloc.pc_rel = 1;
3293 }
3294
3295 input_line_pointer = save_in;
3296 }
3297#else
3298 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3299 inst.reloc.pc_rel = 1;
3300#endif /* OBJ_ELF */
3301
3302 end_of_line (str);
3303}
3304
3305/* ARM V5 branch-link-exchange instruction (argument parse)
3306 BLX <target_addr> ie BLX(1)
3307 BLX{<condition>} <Rm> ie BLX(2)
3308 Unfortunately, there are two different opcodes for this mnemonic.
3309 So, the insns[].value is not used, and the code here zaps values
3310 into inst.instruction.
3311 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
3312
3313static void
3314do_blx (str, flags)
3315 char * str;
3316 unsigned long flags;
3317{
3318 char * mystr = str;
3319 int rm;
3320
3321 if (flags)
3322 {
3323 as_bad (BAD_FLAGS);
3324 return;
3325 }
3326
3327 skip_whitespace (mystr);
3328 rm = reg_required_here (& mystr, 0);
3329
3330 /* The above may set inst.error. Ignore his opinion. */
3331 inst.error = 0;
3332
3333 if (rm != FAIL)
3334 {
3335 /* Arg is a register.
3336 Use the condition code our caller put in inst.instruction.
3337 Pass ourselves off as a BX with a funny opcode. */
3338 inst.instruction |= 0x012fff30;
3339 do_bx (str, flags);
3340 }
3341 else
3342 {
3343 /* This must be is BLX <target address>, no condition allowed. */
3344 if (inst.instruction != COND_ALWAYS)
3345 {
3346 inst.error = BAD_COND;
3347 return;
3348 }
3349
3350 inst.instruction = 0xfafffffe;
3351
3352 /* Process like a B/BL, but with a different reloc.
3353 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
3354 do_branch25 (str, flags);
3355 }
3356}
3357
3358/* ARM V5 Thumb BLX (argument parse)
3359 BLX <target_addr> which is BLX(1)
3360 BLX <Rm> which is BLX(2)
3361 Unfortunately, there are two different opcodes for this mnemonic.
3362 So, the tinsns[].value is not used, and the code here zaps values
3363 into inst.instruction. */
3364
3365static void
3366do_t_blx (str)
3367 char * str;
3368{
3369 char * mystr = str;
3370 int rm;
3371
3372 skip_whitespace (mystr);
3373 inst.instruction = 0x4780;
3374
3375 /* Note that this call is to the ARM register recognizer. BLX(2)
3376 uses the ARM register space, not the Thumb one, so a call to
3377 thumb_reg() would be wrong. */
3378 rm = reg_required_here (& mystr, 3);
3379 inst.error = 0;
3380
3381 if (rm != FAIL)
3382 {
3383 /* It's BLX(2). The .instruction was zapped with rm & is final. */
3384 inst.size = 2;
3385 }
3386 else
3387 {
3388 /* No ARM register. This must be BLX(1). Change the .instruction. */
3389 inst.instruction = 0xf7ffeffe;
3390 inst.size = 4;
3391
3392 if (my_get_expression (& inst.reloc.exp, & mystr))
3393 return;
3394
3395 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
3396 inst.reloc.pc_rel = 1;
3397 }
3398
3399 end_of_line (mystr);
3400}
3401
3402/* ARM V5 breakpoint instruction (argument parse)
3403 BKPT <16 bit unsigned immediate>
3404 Instruction is not conditional.
3405 The bit pattern given in insns[] has the COND_ALWAYS condition,
3406 and it is an error if the caller tried to override that.
3407 Note "flags" is nonzero if a flag was supplied (which is an error). */
3408
3409static void
3410do_bkpt (str, flags)
3411 char * str;
3412 unsigned long flags;
3413{
3414 expressionS expr;
3415 unsigned long number;
3416
3417 skip_whitespace (str);
3418
3419 /* Allow optional leading '#'. */
3420 if (is_immediate_prefix (* str))
3421 str++;
3422
3423 memset (& expr, '\0', sizeof (expr));
3424
3425 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3426 {
3427 inst.error = _("bad or missing expression");
3428 return;
3429 }
3430
3431 number = expr.X_add_number;
3432
3433 /* Check it fits a 16 bit unsigned. */
3434 if (number != (number & 0xffff))
3435 {
3436 inst.error = _("immediate value out of range");
3437 return;
3438 }
3439
3440 /* Top 12 of 16 bits to bits 19:8. */
3441 inst.instruction |= (number & 0xfff0) << 4;
3442
3443 /* Bottom 4 of 16 bits to bits 3:0. */
3444 inst.instruction |= number & 0xf;
3445
3446 end_of_line (str);
3447
3448 if (flags)
3449 inst.error = BAD_FLAGS;
3450}
3451
3452/* Xscale multiply-accumulate (argument parse)
3453 MIAcc acc0,Rm,Rs
3454 MIAPHcc acc0,Rm,Rs
3455 MIAxycc acc0,Rm,Rs. */
3456
3457static void
3458do_mia (str, flags)
3459 char * str;
3460 unsigned long flags;
3461{
3462 int rs;
3463 int rm;
3464
3465 if (flags)
3466 as_bad (BAD_FLAGS);
3467
3468 else if (accum0_required_here (& str) == FAIL)
3469 inst.error = ERR_NO_ACCUM;
3470
3471 else if (skip_past_comma (& str) == FAIL
3472 || (rm = reg_required_here (& str, 0)) == FAIL)
3473 inst.error = BAD_ARGS;
3474
3475 else if (skip_past_comma (& str) == FAIL
3476 || (rs = reg_required_here (& str, 12)) == FAIL)
3477 inst.error = BAD_ARGS;
3478
3479 /* inst.instruction has now been zapped with both rm and rs. */
3480 else if (rm == REG_PC || rs == REG_PC)
3481 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
3482
3483 else
3484 end_of_line (str);
3485}
3486
3487/* Xscale move-accumulator-register (argument parse)
3488
3489 MARcc acc0,RdLo,RdHi. */
3490
3491static void
3492do_mar (str, flags)
3493 char * str;
3494 unsigned long flags;
3495{
3496 int rdlo, rdhi;
3497
3498 if (flags)
3499 as_bad (BAD_FLAGS);
3500
3501 else if (accum0_required_here (& str) == FAIL)
3502 inst.error = ERR_NO_ACCUM;
3503
3504 else if (skip_past_comma (& str) == FAIL
3505 || (rdlo = reg_required_here (& str, 12)) == FAIL)
3506 inst.error = BAD_ARGS;
3507
3508 else if (skip_past_comma (& str) == FAIL
3509 || (rdhi = reg_required_here (& str, 16)) == FAIL)
3510 inst.error = BAD_ARGS;
3511
3512 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3513 else if (rdlo == REG_PC || rdhi == REG_PC)
3514 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
3515
3516 else
3517 end_of_line (str);
3518}
3519
3520/* Xscale move-register-accumulator (argument parse)
3521
3522 MRAcc RdLo,RdHi,acc0. */
3523
3524static void
3525do_mra (str, flags)
3526 char * str;
3527 unsigned long flags;
3528{
3529 int rdlo;
3530 int rdhi;
3531
3532 if (flags)
3533 {
3534 as_bad (BAD_FLAGS);
3535 return;
3536 }
3537
3538 skip_whitespace (str);
3539
3540 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
3541 inst.error = BAD_ARGS;
3542
3543 else if (skip_past_comma (& str) == FAIL
3544 || (rdhi = reg_required_here (& str, 16)) == FAIL)
3545 inst.error = BAD_ARGS;
3546
3547 else if (skip_past_comma (& str) == FAIL
3548 || accum0_required_here (& str) == FAIL)
3549 inst.error = ERR_NO_ACCUM;
3550
3551 /* inst.instruction has now been zapped with both rdlo and rdhi. */
3552 else if (rdlo == rdhi)
3553 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
3554
3555 else if (rdlo == REG_PC || rdhi == REG_PC)
3556 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
3557 else
3558 end_of_line (str);
3559}
3560
3561/* Xscale: Preload-Cache
3562
3563 PLD <addr_mode>
3564
3565 Syntactically, like LDR with B=1, W=0, L=1. */
3566
3567static void
3568do_pld (str, flags)
3569 char * str;
3570 unsigned long flags;
3571{
3572 int rd;
3573
3574 if (flags)
3575 {
3576 as_bad (BAD_FLAGS);
3577 return;
3578 }
3579
3580 skip_whitespace (str);
3581
3582 if (* str != '[')
3583 {
3584 inst.error = _("'[' expected after PLD mnemonic");
3585 return;
3586 }
3587
3588 ++ str;
3589 skip_whitespace (str);
3590
3591 if ((rd = reg_required_here (& str, 16)) == FAIL)
3592 return;
3593
3594 skip_whitespace (str);
3595
3596 if (* str == ']')
3597 {
3598 /* [Rn], ... ? */
3599 ++ str;
3600 skip_whitespace (str);
3601
3602 if (skip_past_comma (& str) == SUCCESS)
3603 {
3604 if (ldst_extend (& str, 0) == FAIL)
3605 return;
3606 }
3607 else if (* str == '!') /* [Rn]! */
3608 {
3609 inst.error = _("writeback used in preload instruction");
3610 ++ str;
3611 }
3612 else /* [Rn] */
3613 inst.instruction |= INDEX_UP | PRE_INDEX;
3614 }
3615 else /* [Rn, ...] */
3616 {
3617 if (skip_past_comma (& str) == FAIL)
3618 {
3619 inst.error = _("pre-indexed expression expected");
3620 return;
3621 }
3622
3623 if (ldst_extend (& str, 0) == FAIL)
3624 return;
3625
3626 skip_whitespace (str);
3627
3628 if (* str != ']')
3629 {
3630 inst.error = _("missing ]");
3631 return;
3632 }
3633
3634 ++ str;
3635 skip_whitespace (str);
3636
3637 if (* str == '!') /* [Rn]! */
3638 {
3639 inst.error = _("writeback used in preload instruction");
3640 ++ str;
3641 }
3642
3643 inst.instruction |= PRE_INDEX;
3644 }
3645
3646 end_of_line (str);
3647}
3648
3649/* Xscale load-consecutive (argument parse)
3650 Mode is like LDRH.
3651
3652 LDRccD R, mode
3653 STRccD R, mode. */
3654
3655static void
3656do_ldrd (str, flags)
3657 char * str;
3658 unsigned long flags;
3659{
3660 int rd;
3661 int rn;
3662
3663 if (flags != DOUBLE_LOAD_FLAG)
3664 {
3665 /* Change instruction pattern to normal ldr/str. */
3666 if (inst.instruction & 0x20)
3667 inst.instruction = (inst.instruction & COND_MASK) | 0x04000000; /* str */
3668 else
3669 inst.instruction = (inst.instruction & COND_MASK) | 0x04100000; /* ldr */
3670
3671 /* Perform a normal load/store instruction parse. */
3672 do_ldst (str, flags);
3673
3674 return;
3675 }
3676
3677 if ((cpu_variant & ARM_EXT_XSCALE) != ARM_EXT_XSCALE)
3678 {
3679 static char buff[128];
3680
3681 --str;
3882b010 3682 while (ISSPACE (*str))
b99bd4ef
NC
3683 --str;
3684 str -= 4;
3685
3686 /* Deny all knowledge. */
3687 sprintf (buff, _("bad instruction '%.100s'"), str);
3688 inst.error = buff;
3689 return;
3690 }
3691
3692 skip_whitespace (str);
3693
3694 if ((rd = reg_required_here (& str, 12)) == FAIL)
3695 {
3696 inst.error = BAD_ARGS;
3697 return;
3698 }
3699
3700 if (skip_past_comma (& str) == FAIL
3701 || (rn = ld_mode_required_here (& str)) == FAIL)
3702 {
3703 if (!inst.error)
3704 inst.error = BAD_ARGS;
3705 return;
3706 }
3707
3708 /* inst.instruction has now been zapped with Rd and the addressing mode. */
3709 if (rd & 1) /* Unpredictable result if Rd is odd. */
3710 {
3711 inst.error = _("Destination register must be even");
3712 return;
3713 }
3714
3715 if (rd == REG_LR || rd == 12)
3716 {
3717 inst.error = _("r12 or r14 not allowed here");
3718 return;
3719 }
3720
3721 if (((rd == rn) || (rd + 1 == rn))
3722 &&
3723 ((inst.instruction & WRITE_BACK)
3724 || (!(inst.instruction & PRE_INDEX))))
3725 as_warn (_("pre/post-indexing used when modified address register is destination"));
3726
3727 end_of_line (str);
3728}
3729
3730/* Returns the index into fp_values of a floating point number,
3731 or -1 if not in the table. */
3732
3733static int
3734my_get_float_expression (str)
3735 char ** str;
3736{
3737 LITTLENUM_TYPE words[MAX_LITTLENUMS];
3738 char * save_in;
3739 expressionS exp;
3740 int i;
3741 int j;
3742
3743 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
3744
3745 /* Look for a raw floating point number. */
3746 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
3747 && is_end_of_line[(unsigned char) *save_in])
3748 {
3749 for (i = 0; i < NUM_FLOAT_VALS; i++)
3750 {
3751 for (j = 0; j < MAX_LITTLENUMS; j++)
3752 {
3753 if (words[j] != fp_values[i][j])
3754 break;
3755 }
3756
3757 if (j == MAX_LITTLENUMS)
3758 {
3759 *str = save_in;
3760 return i;
3761 }
3762 }
3763 }
3764
3765 /* Try and parse a more complex expression, this will probably fail
3766 unless the code uses a floating point prefix (eg "0f"). */
3767 save_in = input_line_pointer;
3768 input_line_pointer = *str;
3769 if (expression (&exp) == absolute_section
3770 && exp.X_op == O_big
3771 && exp.X_add_number < 0)
3772 {
3773 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
3774 Ditto for 15. */
3775 if (gen_to_words (words, 5, (long) 15) == 0)
3776 {
3777 for (i = 0; i < NUM_FLOAT_VALS; i++)
3778 {
3779 for (j = 0; j < MAX_LITTLENUMS; j++)
3780 {
3781 if (words[j] != fp_values[i][j])
3782 break;
3783 }
3784
3785 if (j == MAX_LITTLENUMS)
3786 {
3787 *str = input_line_pointer;
3788 input_line_pointer = save_in;
3789 return i;
3790 }
3791 }
3792 }
3793 }
3794
3795 *str = input_line_pointer;
3796 input_line_pointer = save_in;
3797 return -1;
3798}
3799
3800/* Return true if anything in the expression is a bignum. */
3801
3802static int
3803walk_no_bignums (sp)
3804 symbolS * sp;
3805{
3806 if (symbol_get_value_expression (sp)->X_op == O_big)
3807 return 1;
3808
3809 if (symbol_get_value_expression (sp)->X_add_symbol)
3810 {
3811 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
3812 || (symbol_get_value_expression (sp)->X_op_symbol
3813 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
3814 }
3815
3816 return 0;
3817}
3818
3819static int
3820my_get_expression (ep, str)
3821 expressionS * ep;
3822 char ** str;
3823{
3824 char * save_in;
3825 segT seg;
3826
3827 save_in = input_line_pointer;
3828 input_line_pointer = *str;
3829 seg = expression (ep);
3830
3831#ifdef OBJ_AOUT
3832 if (seg != absolute_section
3833 && seg != text_section
3834 && seg != data_section
3835 && seg != bss_section
3836 && seg != undefined_section)
3837 {
3838 inst.error = _("bad_segment");
3839 *str = input_line_pointer;
3840 input_line_pointer = save_in;
3841 return 1;
3842 }
3843#endif
3844
3845 /* Get rid of any bignums now, so that we don't generate an error for which
3846 we can't establish a line number later on. Big numbers are never valid
3847 in instructions, which is where this routine is always called. */
3848 if (ep->X_op == O_big
3849 || (ep->X_add_symbol
3850 && (walk_no_bignums (ep->X_add_symbol)
3851 || (ep->X_op_symbol
3852 && walk_no_bignums (ep->X_op_symbol)))))
3853 {
3854 inst.error = _("Invalid constant");
3855 *str = input_line_pointer;
3856 input_line_pointer = save_in;
3857 return 1;
3858 }
3859
3860 *str = input_line_pointer;
3861 input_line_pointer = save_in;
3862 return 0;
3863}
3864
3865/* UNRESTRICT should be one if <shift> <register> is permitted for this
3866 instruction. */
3867
3868static int
3869decode_shift (str, unrestrict)
3870 char ** str;
3871 int unrestrict;
3872{
3873 const struct asm_shift_name * shift;
3874 char * p;
3875 char c;
3876
3877 skip_whitespace (* str);
3878
3882b010 3879 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
3880 ;
3881
3882 if (p == * str)
3883 {
3884 inst.error = _("Shift expression expected");
3885 return FAIL;
3886 }
3887
3888 c = * p;
3889 * p = '\0';
3890 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3891 * p = c;
3892
3893 if (shift == NULL)
3894 {
3895 inst.error = _("Shift expression expected");
3896 return FAIL;
3897 }
3898
3899 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3900
3901 if (shift->properties->index == SHIFT_RRX)
3902 {
3903 * str = p;
3904 inst.instruction |= shift->properties->bit_field;
3905 return SUCCESS;
3906 }
3907
3908 skip_whitespace (p);
3909
3910 if (unrestrict && reg_required_here (& p, 8) != FAIL)
3911 {
3912 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3913 * str = p;
3914 return SUCCESS;
3915 }
3916 else if (! is_immediate_prefix (* p))
3917 {
3918 inst.error = (unrestrict
3919 ? _("shift requires register or #expression")
3920 : _("shift requires #expression"));
3921 * str = p;
3922 return FAIL;
3923 }
3924
3925 inst.error = NULL;
3926 p ++;
3927
3928 if (my_get_expression (& inst.reloc.exp, & p))
3929 return FAIL;
3930
3931 /* Validate some simple #expressions. */
3932 if (inst.reloc.exp.X_op == O_constant)
3933 {
3934 unsigned num = inst.reloc.exp.X_add_number;
3935
3936 /* Reject operations greater than 32. */
3937 if (num > 32
3938 /* Reject a shift of 0 unless the mode allows it. */
3939 || (num == 0 && shift->properties->allows_0 == 0)
3940 /* Reject a shift of 32 unless the mode allows it. */
3941 || (num == 32 && shift->properties->allows_32 == 0)
3942 )
3943 {
3944 /* As a special case we allow a shift of zero for
3945 modes that do not support it to be recoded as an
3946 logical shift left of zero (ie nothing). We warn
3947 about this though. */
3948 if (num == 0)
3949 {
3950 as_warn (_("Shift of 0 ignored."));
3951 shift = & shift_names[0];
3952 assert (shift->properties->index == SHIFT_LSL);
3953 }
3954 else
3955 {
3956 inst.error = _("Invalid immediate shift");
3957 return FAIL;
3958 }
3959 }
3960
3961 /* Shifts of 32 are encoded as 0, for those shifts that
3962 support it. */
3963 if (num == 32)
3964 num = 0;
3965
3966 inst.instruction |= (num << 7) | shift->properties->bit_field;
3967 }
3968 else
3969 {
3970 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3971 inst.reloc.pc_rel = 0;
3972 inst.instruction |= shift->properties->bit_field;
3973 }
3974
3975 * str = p;
3976 return SUCCESS;
3977}
3978
3979/* Do those data_ops which can take a negative immediate constant
3980 by altering the instuction. A bit of a hack really.
3981 MOV <-> MVN
3982 AND <-> BIC
3983 ADC <-> SBC
3984 by inverting the second operand, and
3985 ADD <-> SUB
3986 CMP <-> CMN
3987 by negating the second operand. */
3988
3989static int
3990negate_data_op (instruction, value)
3991 unsigned long * instruction;
3992 unsigned long value;
3993{
3994 int op, new_inst;
3995 unsigned long negated, inverted;
3996
3997 negated = validate_immediate (-value);
3998 inverted = validate_immediate (~value);
3999
4000 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
4001 switch (op)
4002 {
4003 /* First negates. */
4004 case OPCODE_SUB: /* ADD <-> SUB */
4005 new_inst = OPCODE_ADD;
4006 value = negated;
4007 break;
4008
4009 case OPCODE_ADD:
4010 new_inst = OPCODE_SUB;
4011 value = negated;
4012 break;
4013
4014 case OPCODE_CMP: /* CMP <-> CMN */
4015 new_inst = OPCODE_CMN;
4016 value = negated;
4017 break;
4018
4019 case OPCODE_CMN:
4020 new_inst = OPCODE_CMP;
4021 value = negated;
4022 break;
4023
4024 /* Now Inverted ops. */
4025 case OPCODE_MOV: /* MOV <-> MVN */
4026 new_inst = OPCODE_MVN;
4027 value = inverted;
4028 break;
4029
4030 case OPCODE_MVN:
4031 new_inst = OPCODE_MOV;
4032 value = inverted;
4033 break;
4034
4035 case OPCODE_AND: /* AND <-> BIC */
4036 new_inst = OPCODE_BIC;
4037 value = inverted;
4038 break;
4039
4040 case OPCODE_BIC:
4041 new_inst = OPCODE_AND;
4042 value = inverted;
4043 break;
4044
4045 case OPCODE_ADC: /* ADC <-> SBC */
4046 new_inst = OPCODE_SBC;
4047 value = inverted;
4048 break;
4049
4050 case OPCODE_SBC:
4051 new_inst = OPCODE_ADC;
4052 value = inverted;
4053 break;
4054
4055 /* We cannot do anything. */
4056 default:
4057 return FAIL;
4058 }
4059
4060 if (value == (unsigned) FAIL)
4061 return FAIL;
4062
4063 *instruction &= OPCODE_MASK;
4064 *instruction |= new_inst << DATA_OP_SHIFT;
4065 return value;
4066}
4067
4068static int
4069data_op2 (str)
4070 char ** str;
4071{
4072 int value;
4073 expressionS expr;
4074
4075 skip_whitespace (* str);
4076
4077 if (reg_required_here (str, 0) != FAIL)
4078 {
4079 if (skip_past_comma (str) == SUCCESS)
4080 /* Shift operation on register. */
4081 return decode_shift (str, NO_SHIFT_RESTRICT);
4082
4083 return SUCCESS;
4084 }
4085 else
4086 {
4087 /* Immediate expression. */
4088 if (is_immediate_prefix (**str))
4089 {
4090 (*str)++;
4091 inst.error = NULL;
4092
4093 if (my_get_expression (&inst.reloc.exp, str))
4094 return FAIL;
4095
4096 if (inst.reloc.exp.X_add_symbol)
4097 {
4098 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4099 inst.reloc.pc_rel = 0;
4100 }
4101 else
4102 {
4103 if (skip_past_comma (str) == SUCCESS)
4104 {
4105 /* #x, y -- ie explicit rotation by Y. */
4106 if (my_get_expression (&expr, str))
4107 return FAIL;
4108
4109 if (expr.X_op != O_constant)
4110 {
4111 inst.error = _("Constant expression expected");
4112 return FAIL;
4113 }
4114
4115 /* Rotate must be a multiple of 2. */
4116 if (((unsigned) expr.X_add_number) > 30
4117 || (expr.X_add_number & 1) != 0
4118 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
4119 {
4120 inst.error = _("Invalid constant");
4121 return FAIL;
4122 }
4123 inst.instruction |= INST_IMMEDIATE;
4124 inst.instruction |= inst.reloc.exp.X_add_number;
4125 inst.instruction |= expr.X_add_number << 7;
4126 return SUCCESS;
4127 }
4128
4129 /* Implicit rotation, select a suitable one. */
4130 value = validate_immediate (inst.reloc.exp.X_add_number);
4131
4132 if (value == FAIL)
4133 {
4134 /* Can't be done. Perhaps the code reads something like
4135 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4136 if ((value = negate_data_op (&inst.instruction,
4137 inst.reloc.exp.X_add_number))
4138 == FAIL)
4139 {
4140 inst.error = _("Invalid constant");
4141 return FAIL;
4142 }
4143 }
4144
4145 inst.instruction |= value;
4146 }
4147
4148 inst.instruction |= INST_IMMEDIATE;
4149 return SUCCESS;
4150 }
4151
4152 (*str)++;
4153 inst.error = _("Register or shift expression expected");
4154 return FAIL;
4155 }
4156}
4157
4158static int
4159fp_op2 (str)
4160 char ** str;
4161{
4162 skip_whitespace (* str);
4163
4164 if (fp_reg_required_here (str, 0) != FAIL)
4165 return SUCCESS;
4166 else
4167 {
4168 /* Immediate expression. */
4169 if (*((*str)++) == '#')
4170 {
4171 int i;
4172
4173 inst.error = NULL;
4174
4175 skip_whitespace (* str);
4176
4177 /* First try and match exact strings, this is to guarantee
4178 that some formats will work even for cross assembly. */
4179
4180 for (i = 0; fp_const[i]; i++)
4181 {
4182 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
4183 {
4184 char *start = *str;
4185
4186 *str += strlen (fp_const[i]);
4187 if (is_end_of_line[(unsigned char) **str])
4188 {
4189 inst.instruction |= i + 8;
4190 return SUCCESS;
4191 }
4192 *str = start;
4193 }
4194 }
4195
4196 /* Just because we didn't get a match doesn't mean that the
4197 constant isn't valid, just that it is in a format that we
4198 don't automatically recognize. Try parsing it with
4199 the standard expression routines. */
4200 if ((i = my_get_float_expression (str)) >= 0)
4201 {
4202 inst.instruction |= i + 8;
4203 return SUCCESS;
4204 }
4205
4206 inst.error = _("Invalid floating point immediate expression");
4207 return FAIL;
4208 }
4209 inst.error =
4210 _("Floating point register or immediate expression expected");
4211 return FAIL;
4212 }
4213}
4214
4215static void
4216do_arit (str, flags)
4217 char * str;
4218 unsigned long flags;
4219{
4220 skip_whitespace (str);
4221
4222 if (reg_required_here (&str, 12) == FAIL
4223 || skip_past_comma (&str) == FAIL
4224 || reg_required_here (&str, 16) == FAIL
4225 || skip_past_comma (&str) == FAIL
4226 || data_op2 (&str) == FAIL)
4227 {
4228 if (!inst.error)
4229 inst.error = BAD_ARGS;
4230 return;
4231 }
4232
4233 inst.instruction |= flags;
4234 end_of_line (str);
4235 return;
4236}
4237
4238static void
4239do_adr (str, flags)
4240 char * str;
4241 unsigned long flags;
4242{
b99bd4ef
NC
4243 skip_whitespace (str);
4244
4245 if (reg_required_here (&str, 12) == FAIL
4246 || skip_past_comma (&str) == FAIL
4247 || my_get_expression (&inst.reloc.exp, &str))
4248 {
4249 if (!inst.error)
4250 inst.error = BAD_ARGS;
4251 return;
4252 }
4253
1cac9012 4254 if (flags & 0x00400000)
b99bd4ef 4255 {
1cac9012
NC
4256 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4257 into a relative address of the form:
4258 add rd, pc, #low(label-.-8)"
4259 add rd, rd, #high(label-.-8)" */
4260 /* Frag hacking will turn this into a sub instruction if the offset turns
4261 out to be negative. */
4262 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
4263 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
4264 inst.reloc.pc_rel = 1;
4265 inst.instruction |= flags & ~0x00400000;
4266 inst.size = INSN_SIZE * 2;
4267 }
4268 else
4269 {
4270 /* This is a pseudo-op of the form "adr rd, label" to be converted
4271 into a relative address of the form "add rd, pc, #label-.-8". */
4272 /* Frag hacking will turn this into a sub instruction if the offset turns
4273 out to be negative. */
4274 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4275 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
4276 inst.reloc.pc_rel = 1;
4277 inst.instruction |= flags;
b99bd4ef
NC
4278 }
4279
4280 end_of_line (str);
b99bd4ef
NC
4281}
4282
4283static void
4284do_cmp (str, flags)
4285 char * str;
4286 unsigned long flags;
4287{
4288 skip_whitespace (str);
4289
4290 if (reg_required_here (&str, 16) == FAIL)
4291 {
4292 if (!inst.error)
4293 inst.error = BAD_ARGS;
4294 return;
4295 }
4296
4297 if (skip_past_comma (&str) == FAIL
4298 || data_op2 (&str) == FAIL)
4299 {
4300 if (!inst.error)
4301 inst.error = BAD_ARGS;
4302 return;
4303 }
4304
4305 inst.instruction |= flags;
4306 if ((flags & 0x0000f000) == 0)
4307 inst.instruction |= CONDS_BIT;
4308
4309 end_of_line (str);
4310 return;
4311}
4312
4313static void
4314do_mov (str, flags)
4315 char * str;
4316 unsigned long flags;
4317{
4318 skip_whitespace (str);
4319
4320 if (reg_required_here (&str, 12) == FAIL)
4321 {
4322 if (!inst.error)
4323 inst.error = BAD_ARGS;
4324 return;
4325 }
4326
4327 if (skip_past_comma (&str) == FAIL
4328 || data_op2 (&str) == FAIL)
4329 {
4330 if (!inst.error)
4331 inst.error = BAD_ARGS;
4332 return;
4333 }
4334
4335 inst.instruction |= flags;
4336 end_of_line (str);
4337 return;
4338}
4339
4340static int
4341ldst_extend (str, hwse)
4342 char ** str;
4343 int hwse;
4344{
4345 int add = INDEX_UP;
4346
4347 switch (**str)
4348 {
4349 case '#':
4350 case '$':
4351 (*str)++;
4352 if (my_get_expression (& inst.reloc.exp, str))
4353 return FAIL;
4354
4355 if (inst.reloc.exp.X_op == O_constant)
4356 {
4357 int value = inst.reloc.exp.X_add_number;
4358
4359 if ((hwse && (value < -255 || value > 255))
4360 || (value < -4095 || value > 4095))
4361 {
4362 inst.error = _("address offset too large");
4363 return FAIL;
4364 }
4365
4366 if (value < 0)
4367 {
4368 value = -value;
4369 add = 0;
4370 }
4371
4372 /* Halfword and signextension instructions have the
4373 immediate value split across bits 11..8 and bits 3..0. */
4374 if (hwse)
4375 inst.instruction |= (add | HWOFFSET_IMM
4376 | ((value >> 4) << 8) | (value & 0xF));
4377 else
4378 inst.instruction |= add | value;
4379 }
4380 else
4381 {
4382 if (hwse)
4383 {
4384 inst.instruction |= HWOFFSET_IMM;
4385 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4386 }
4387 else
4388 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4389 inst.reloc.pc_rel = 0;
4390 }
4391 return SUCCESS;
4392
4393 case '-':
4394 add = 0;
4395 /* Fall through. */
4396
4397 case '+':
4398 (*str)++;
4399 /* Fall through. */
4400
4401 default:
4402 if (reg_required_here (str, 0) == FAIL)
4403 return FAIL;
4404
4405 if (hwse)
4406 inst.instruction |= add;
4407 else
4408 {
4409 inst.instruction |= add | OFFSET_REG;
4410 if (skip_past_comma (str) == SUCCESS)
4411 return decode_shift (str, SHIFT_RESTRICT);
4412 }
4413
4414 return SUCCESS;
4415 }
4416}
4417
4418static void
4419do_ldst (str, flags)
4420 char * str;
4421 unsigned long flags;
4422{
4423 int halfword = 0;
4424 int pre_inc = 0;
4425 int conflict_reg;
4426 int value;
4427
4428 /* This is not ideal, but it is the simplest way of dealing with the
4429 ARM7T halfword instructions (since they use a different
4430 encoding, but the same mnemonic): */
4431 halfword = (flags & 0x80000000) != 0;
4432 if (halfword)
4433 {
4434 /* This is actually a load/store of a halfword, or a
4435 signed-extension load. */
4436 if ((cpu_variant & ARM_EXT_HALFWORD) == 0)
4437 {
4438 inst.error
4439 = _("Processor does not support halfwords or signed bytes");
4440 return;
4441 }
4442
4443 inst.instruction = ((inst.instruction & COND_MASK)
4444 | (flags & ~COND_MASK));
4445
4446 flags = 0;
4447 }
4448
4449 skip_whitespace (str);
4450
4451 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
4452 {
4453 if (!inst.error)
4454 inst.error = BAD_ARGS;
4455 return;
4456 }
4457
4458 if (skip_past_comma (& str) == FAIL)
4459 {
4460 inst.error = _("Address expected");
4461 return;
4462 }
4463
4464 if (*str == '[')
4465 {
4466 int reg;
4467
4468 str++;
4469
4470 skip_whitespace (str);
4471
4472 if ((reg = reg_required_here (&str, 16)) == FAIL)
4473 return;
4474
4475 /* Conflicts can occur on stores as well as loads. */
4476 conflict_reg = (conflict_reg == reg);
4477
4478 skip_whitespace (str);
4479
4480 if (*str == ']')
4481 {
4482 str ++;
4483
4484 if (skip_past_comma (&str) == SUCCESS)
4485 {
4486 /* [Rn],... (post inc) */
4487 if (ldst_extend (&str, halfword) == FAIL)
4488 return;
4489 if (conflict_reg)
4490 {
4491 if (flags & TRANS_BIT)
4492 as_warn (_("Rn and Rd must be different in %s"),
4493 ((inst.instruction & LOAD_BIT)
4494 ? "LDRT" : "STRT"));
4495 else
4496 as_warn (_("%s register same as write-back base"),
4497 ((inst.instruction & LOAD_BIT)
4498 ? _("destination") : _("source")));
4499 }
4500 }
4501 else
4502 {
4503 /* [Rn] */
4504 if (halfword)
4505 inst.instruction |= HWOFFSET_IMM;
4506
4507 skip_whitespace (str);
4508
4509 if (*str == '!')
4510 {
4511 if (conflict_reg)
4512 as_warn (_("%s register same as write-back base"),
4513 ((inst.instruction & LOAD_BIT)
4514 ? _("destination") : _("source")));
4515 str++;
4516 inst.instruction |= WRITE_BACK;
4517 }
4518
4519 flags |= INDEX_UP;
4520 if (flags & TRANS_BIT)
4521 {
4522 if (conflict_reg)
4523 as_warn (_("Rn and Rd must be different in %s"),
4524 ((inst.instruction & LOAD_BIT)
4525 ? "LDRT" : "STRT"));
4526 }
4527 else
4528 pre_inc = 1;
4529 }
4530 }
4531 else
4532 {
4533 /* [Rn,...] */
4534 if (skip_past_comma (&str) == FAIL)
4535 {
4536 inst.error = _("pre-indexed expression expected");
4537 return;
4538 }
4539
4540 pre_inc = 1;
4541 if (ldst_extend (&str, halfword) == FAIL)
4542 return;
4543
4544 skip_whitespace (str);
4545
4546 if (*str++ != ']')
4547 {
4548 inst.error = _("missing ]");
4549 return;
4550 }
4551
4552 skip_whitespace (str);
4553
4554 if (*str == '!')
4555 {
4556 if (conflict_reg)
4557 as_warn (_("%s register same as write-back base"),
4558 ((inst.instruction & LOAD_BIT)
4559 ? _("destination") : _("source")));
4560 str++;
4561 inst.instruction |= WRITE_BACK;
4562 }
4563 }
4564 }
4565 else if (*str == '=')
4566 {
4567 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
4568 str++;
4569
4570 skip_whitespace (str);
4571
4572 if (my_get_expression (&inst.reloc.exp, &str))
4573 return;
4574
4575 if (inst.reloc.exp.X_op != O_constant
4576 && inst.reloc.exp.X_op != O_symbol)
4577 {
4578 inst.error = _("Constant expression expected");
4579 return;
4580 }
4581
d8273442 4582 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 4583 {
d8273442
NC
4584 value = validate_immediate (inst.reloc.exp.X_add_number);
4585
4586 if (value != FAIL)
b99bd4ef 4587 {
d8273442
NC
4588 /* This can be done with a mov instruction. */
4589 inst.instruction &= LITERAL_MASK;
4590 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
4591 inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
4592 end_of_line (str);
b99bd4ef
NC
4593 return;
4594 }
d8273442
NC
4595
4596 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 4597
d8273442 4598 if (value != FAIL)
b99bd4ef 4599 {
d8273442
NC
4600 /* This can be done with a mvn instruction. */
4601 inst.instruction &= LITERAL_MASK;
4602 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
4603 inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
4604 end_of_line (str);
4605 return;
b99bd4ef 4606 }
b99bd4ef 4607 }
d8273442
NC
4608
4609 /* Insert into literal pool. */
4610 if (add_to_lit_pool () == FAIL)
4611 {
4612 if (!inst.error)
4613 inst.error = _("literal pool insertion failed");
4614 return;
4615 }
4616
4617 /* Change the instruction exp to point to the pool. */
4618 if (halfword)
4619 {
4620 inst.instruction |= HWOFFSET_IMM;
4621 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
4622 }
4623 else
4624 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
4625
4626 inst.reloc.pc_rel = 1;
4627 inst.instruction |= (REG_PC << 16);
4628 pre_inc = 1;
b99bd4ef
NC
4629 }
4630 else
4631 {
4632 if (my_get_expression (&inst.reloc.exp, &str))
4633 return;
4634
4635 if (halfword)
4636 {
4637 inst.instruction |= HWOFFSET_IMM;
4638 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4639 }
4640 else
4641 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
4642#ifndef TE_WINCE
4643 /* PC rel adjust. */
4644 inst.reloc.exp.X_add_number -= 8;
4645#endif
4646 inst.reloc.pc_rel = 1;
4647 inst.instruction |= (REG_PC << 16);
4648 pre_inc = 1;
4649 }
4650
4651 if (pre_inc && (flags & TRANS_BIT))
4652 inst.error = _("Pre-increment instruction with translate");
4653
4654 inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0);
4655 end_of_line (str);
4656 return;
4657}
4658
4659static long
4660reg_list (strp)
4661 char ** strp;
4662{
4663 char * str = * strp;
4664 long range = 0;
4665 int another_range;
4666
4667 /* We come back here if we get ranges concatenated by '+' or '|'. */
4668 do
4669 {
4670 another_range = 0;
4671
4672 if (*str == '{')
4673 {
4674 int in_range = 0;
4675 int cur_reg = -1;
4676
4677 str++;
4678 do
4679 {
4680 int reg;
4681
4682 skip_whitespace (str);
4683
4684 if ((reg = reg_required_here (& str, -1)) == FAIL)
4685 return FAIL;
4686
4687 if (in_range)
4688 {
4689 int i;
4690
4691 if (reg <= cur_reg)
4692 {
4693 inst.error = _("Bad range in register list");
4694 return FAIL;
4695 }
4696
4697 for (i = cur_reg + 1; i < reg; i++)
4698 {
4699 if (range & (1 << i))
4700 as_tsktsk
4701 (_("Warning: Duplicated register (r%d) in register list"),
4702 i);
4703 else
4704 range |= 1 << i;
4705 }
4706 in_range = 0;
4707 }
4708
4709 if (range & (1 << reg))
4710 as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
4711 reg);
4712 else if (reg <= cur_reg)
4713 as_tsktsk (_("Warning: Register range not in ascending order"));
4714
4715 range |= 1 << reg;
4716 cur_reg = reg;
4717 }
4718 while (skip_past_comma (&str) != FAIL
4719 || (in_range = 1, *str++ == '-'));
4720 str--;
4721 skip_whitespace (str);
4722
4723 if (*str++ != '}')
4724 {
4725 inst.error = _("Missing `}'");
4726 return FAIL;
4727 }
4728 }
4729 else
4730 {
4731 expressionS expr;
4732
4733 if (my_get_expression (&expr, &str))
4734 return FAIL;
4735
4736 if (expr.X_op == O_constant)
4737 {
4738 if (expr.X_add_number
4739 != (expr.X_add_number & 0x0000ffff))
4740 {
4741 inst.error = _("invalid register mask");
4742 return FAIL;
4743 }
4744
4745 if ((range & expr.X_add_number) != 0)
4746 {
4747 int regno = range & expr.X_add_number;
4748
4749 regno &= -regno;
4750 regno = (1 << regno) - 1;
4751 as_tsktsk
4752 (_("Warning: Duplicated register (r%d) in register list"),
4753 regno);
4754 }
4755
4756 range |= expr.X_add_number;
4757 }
4758 else
4759 {
4760 if (inst.reloc.type != 0)
4761 {
4762 inst.error = _("expression too complex");
4763 return FAIL;
4764 }
4765
4766 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
4767 inst.reloc.type = BFD_RELOC_ARM_MULTI;
4768 inst.reloc.pc_rel = 0;
4769 }
4770 }
4771
4772 skip_whitespace (str);
4773
4774 if (*str == '|' || *str == '+')
4775 {
4776 str++;
4777 another_range = 1;
4778 }
4779 }
4780 while (another_range);
4781
4782 *strp = str;
4783 return range;
4784}
4785
4786static void
4787do_ldmstm (str, flags)
4788 char * str;
4789 unsigned long flags;
4790{
4791 int base_reg;
4792 long range;
4793
4794 skip_whitespace (str);
4795
4796 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
4797 return;
4798
4799 if (base_reg == REG_PC)
4800 {
4801 inst.error = _("r15 not allowed as base register");
4802 return;
4803 }
4804
4805 skip_whitespace (str);
4806
4807 if (*str == '!')
4808 {
4809 flags |= WRITE_BACK;
4810 str++;
4811 }
4812
4813 if (skip_past_comma (&str) == FAIL
4814 || (range = reg_list (&str)) == FAIL)
4815 {
4816 if (! inst.error)
4817 inst.error = BAD_ARGS;
4818 return;
4819 }
4820
4821 if (*str == '^')
4822 {
4823 str++;
4824 flags |= LDM_TYPE_2_OR_3;
4825 }
4826
4827 inst.instruction |= flags | range;
4828 end_of_line (str);
4829 return;
4830}
4831
4832static void
4833do_swi (str, flags)
4834 char * str;
4835 unsigned long flags;
4836{
4837 skip_whitespace (str);
4838
4839 /* Allow optional leading '#'. */
4840 if (is_immediate_prefix (*str))
4841 str++;
4842
4843 if (my_get_expression (& inst.reloc.exp, & str))
4844 return;
4845
4846 inst.reloc.type = BFD_RELOC_ARM_SWI;
4847 inst.reloc.pc_rel = 0;
4848 inst.instruction |= flags;
4849
4850 end_of_line (str);
4851
4852 return;
4853}
4854
4855static void
4856do_swap (str, flags)
4857 char * str;
4858 unsigned long flags;
4859{
4860 int reg;
4861
4862 skip_whitespace (str);
4863
4864 if ((reg = reg_required_here (&str, 12)) == FAIL)
4865 return;
4866
4867 if (reg == REG_PC)
4868 {
4869 inst.error = _("r15 not allowed in swap");
4870 return;
4871 }
4872
4873 if (skip_past_comma (&str) == FAIL
4874 || (reg = reg_required_here (&str, 0)) == FAIL)
4875 {
4876 if (!inst.error)
4877 inst.error = BAD_ARGS;
4878 return;
4879 }
4880
4881 if (reg == REG_PC)
4882 {
4883 inst.error = _("r15 not allowed in swap");
4884 return;
4885 }
4886
4887 if (skip_past_comma (&str) == FAIL
4888 || *str++ != '[')
4889 {
4890 inst.error = BAD_ARGS;
4891 return;
4892 }
4893
4894 skip_whitespace (str);
4895
4896 if ((reg = reg_required_here (&str, 16)) == FAIL)
4897 return;
4898
4899 if (reg == REG_PC)
4900 {
4901 inst.error = BAD_PC;
4902 return;
4903 }
4904
4905 skip_whitespace (str);
4906
4907 if (*str++ != ']')
4908 {
4909 inst.error = _("missing ]");
4910 return;
4911 }
4912
4913 inst.instruction |= flags;
4914 end_of_line (str);
4915 return;
4916}
4917
4918static void
4919do_branch (str, flags)
4920 char * str;
4921 unsigned long flags ATTRIBUTE_UNUSED;
4922{
4923 if (my_get_expression (&inst.reloc.exp, &str))
4924 return;
4925
4926#ifdef OBJ_ELF
4927 {
4928 char * save_in;
4929
4930 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
4931 required for the instruction. */
4932
4933 /* arm_parse_reloc () works on input_line_pointer.
4934 We actually want to parse the operands to the branch instruction
4935 passed in 'str'. Save the input pointer and restore it later. */
4936 save_in = input_line_pointer;
4937 input_line_pointer = str;
4938 if (inst.reloc.exp.X_op == O_symbol
4939 && *str == '('
4940 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4941 {
4942 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4943 inst.reloc.pc_rel = 0;
4944 /* Modify str to point to after parsed operands, otherwise
4945 end_of_line() will complain about the (PLT) left in str. */
4946 str = input_line_pointer;
4947 }
4948 else
4949 {
4950 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
4951 inst.reloc.pc_rel = 1;
4952 }
4953 input_line_pointer = save_in;
4954 }
4955#else
4956 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
4957 inst.reloc.pc_rel = 1;
4958#endif /* OBJ_ELF */
4959
4960 end_of_line (str);
4961 return;
4962}
4963
4964static void
4965do_bx (str, flags)
4966 char * str;
4967 unsigned long flags ATTRIBUTE_UNUSED;
4968{
4969 int reg;
4970
4971 skip_whitespace (str);
4972
4973 if ((reg = reg_required_here (&str, 0)) == FAIL)
4974 {
4975 inst.error = BAD_ARGS;
4976 return;
4977 }
4978
4979 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
4980 if (reg == REG_PC)
4981 as_tsktsk (_("Use of r15 in bx in ARM mode is not really useful"));
4982
4983 end_of_line (str);
4984}
4985
4986static void
4987do_cdp (str, flags)
4988 char * str;
4989 unsigned long flags ATTRIBUTE_UNUSED;
4990{
4991 /* Co-processor data operation.
4992 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
4993 skip_whitespace (str);
4994
4995 if (co_proc_number (&str) == FAIL)
4996 {
4997 if (!inst.error)
4998 inst.error = BAD_ARGS;
4999 return;
5000 }
5001
5002 if (skip_past_comma (&str) == FAIL
5003 || cp_opc_expr (&str, 20,4) == FAIL)
5004 {
5005 if (!inst.error)
5006 inst.error = BAD_ARGS;
5007 return;
5008 }
5009
5010 if (skip_past_comma (&str) == FAIL
5011 || cp_reg_required_here (&str, 12) == FAIL)
5012 {
5013 if (!inst.error)
5014 inst.error = BAD_ARGS;
5015 return;
5016 }
5017
5018 if (skip_past_comma (&str) == FAIL
5019 || cp_reg_required_here (&str, 16) == FAIL)
5020 {
5021 if (!inst.error)
5022 inst.error = BAD_ARGS;
5023 return;
5024 }
5025
5026 if (skip_past_comma (&str) == FAIL
5027 || cp_reg_required_here (&str, 0) == FAIL)
5028 {
5029 if (!inst.error)
5030 inst.error = BAD_ARGS;
5031 return;
5032 }
5033
5034 if (skip_past_comma (&str) == SUCCESS)
5035 {
5036 if (cp_opc_expr (&str, 5, 3) == FAIL)
5037 {
5038 if (!inst.error)
5039 inst.error = BAD_ARGS;
5040 return;
5041 }
5042 }
5043
5044 end_of_line (str);
5045 return;
5046}
5047
5048static void
5049do_lstc (str, flags)
5050 char * str;
5051 unsigned long flags;
5052{
5053 /* Co-processor register load/store.
5054 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5055
5056 skip_whitespace (str);
5057
5058 if (co_proc_number (&str) == FAIL)
5059 {
5060 if (!inst.error)
5061 inst.error = BAD_ARGS;
5062 return;
5063 }
5064
5065 if (skip_past_comma (&str) == FAIL
5066 || cp_reg_required_here (&str, 12) == FAIL)
5067 {
5068 if (!inst.error)
5069 inst.error = BAD_ARGS;
5070 return;
5071 }
5072
5073 if (skip_past_comma (&str) == FAIL
5074 || cp_address_required_here (&str) == FAIL)
5075 {
5076 if (! inst.error)
5077 inst.error = BAD_ARGS;
5078 return;
5079 }
5080
5081 inst.instruction |= flags;
5082 end_of_line (str);
5083 return;
5084}
5085
5086static void
5087do_co_reg (str, flags)
5088 char * str;
5089 unsigned long flags;
5090{
5091 /* Co-processor register transfer.
5092 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
5093
5094 skip_whitespace (str);
5095
5096 if (co_proc_number (&str) == FAIL)
5097 {
5098 if (!inst.error)
5099 inst.error = BAD_ARGS;
5100 return;
5101 }
5102
5103 if (skip_past_comma (&str) == FAIL
5104 || cp_opc_expr (&str, 21, 3) == FAIL)
5105 {
5106 if (!inst.error)
5107 inst.error = BAD_ARGS;
5108 return;
5109 }
5110
5111 if (skip_past_comma (&str) == FAIL
5112 || reg_required_here (&str, 12) == FAIL)
5113 {
5114 if (!inst.error)
5115 inst.error = BAD_ARGS;
5116 return;
5117 }
5118
5119 if (skip_past_comma (&str) == FAIL
5120 || cp_reg_required_here (&str, 16) == FAIL)
5121 {
5122 if (!inst.error)
5123 inst.error = BAD_ARGS;
5124 return;
5125 }
5126
5127 if (skip_past_comma (&str) == FAIL
5128 || cp_reg_required_here (&str, 0) == FAIL)
5129 {
5130 if (!inst.error)
5131 inst.error = BAD_ARGS;
5132 return;
5133 }
5134
5135 if (skip_past_comma (&str) == SUCCESS)
5136 {
5137 if (cp_opc_expr (&str, 5, 3) == FAIL)
5138 {
5139 if (!inst.error)
5140 inst.error = BAD_ARGS;
5141 return;
5142 }
5143 }
5144 if (flags)
5145 {
5146 inst.error = BAD_COND;
5147 }
5148
5149 end_of_line (str);
5150 return;
5151}
5152
5153static void
5154do_fp_ctrl (str, flags)
5155 char * str;
5156 unsigned long flags ATTRIBUTE_UNUSED;
5157{
5158 /* FP control registers.
5159 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
5160
5161 skip_whitespace (str);
5162
5163 if (reg_required_here (&str, 12) == FAIL)
5164 {
5165 if (!inst.error)
5166 inst.error = BAD_ARGS;
5167 return;
5168 }
5169
5170 end_of_line (str);
5171 return;
5172}
5173
5174static void
5175do_fp_ldst (str, flags)
5176 char * str;
5177 unsigned long flags ATTRIBUTE_UNUSED;
5178{
5179 skip_whitespace (str);
5180
5181 switch (inst.suffix)
5182 {
5183 case SUFF_S:
5184 break;
5185 case SUFF_D:
5186 inst.instruction |= CP_T_X;
5187 break;
5188 case SUFF_E:
5189 inst.instruction |= CP_T_Y;
5190 break;
5191 case SUFF_P:
5192 inst.instruction |= CP_T_X | CP_T_Y;
5193 break;
5194 default:
5195 abort ();
5196 }
5197
5198 if (fp_reg_required_here (&str, 12) == FAIL)
5199 {
5200 if (!inst.error)
5201 inst.error = BAD_ARGS;
5202 return;
5203 }
5204
5205 if (skip_past_comma (&str) == FAIL
5206 || cp_address_required_here (&str) == FAIL)
5207 {
5208 if (!inst.error)
5209 inst.error = BAD_ARGS;
5210 return;
5211 }
5212
5213 end_of_line (str);
5214}
5215
5216static void
5217do_fp_ldmstm (str, flags)
5218 char * str;
5219 unsigned long flags;
5220{
5221 int num_regs;
5222
5223 skip_whitespace (str);
5224
5225 if (fp_reg_required_here (&str, 12) == FAIL)
5226 {
5227 if (! inst.error)
5228 inst.error = BAD_ARGS;
5229 return;
5230 }
5231
5232 /* Get Number of registers to transfer. */
5233 if (skip_past_comma (&str) == FAIL
5234 || my_get_expression (&inst.reloc.exp, &str))
5235 {
5236 if (! inst.error)
5237 inst.error = _("constant expression expected");
5238 return;
5239 }
5240
5241 if (inst.reloc.exp.X_op != O_constant)
5242 {
5243 inst.error = _("Constant value required for number of registers");
5244 return;
5245 }
5246
5247 num_regs = inst.reloc.exp.X_add_number;
5248
5249 if (num_regs < 1 || num_regs > 4)
5250 {
5251 inst.error = _("number of registers must be in the range [1:4]");
5252 return;
5253 }
5254
5255 switch (num_regs)
5256 {
5257 case 1:
5258 inst.instruction |= CP_T_X;
5259 break;
5260 case 2:
5261 inst.instruction |= CP_T_Y;
5262 break;
5263 case 3:
5264 inst.instruction |= CP_T_Y | CP_T_X;
5265 break;
5266 case 4:
5267 break;
5268 default:
5269 abort ();
5270 }
5271
5272 if (flags)
5273 {
5274 int reg;
5275 int write_back;
5276 int offset;
5277
5278 /* The instruction specified "ea" or "fd", so we can only accept
5279 [Rn]{!}. The instruction does not really support stacking or
5280 unstacking, so we have to emulate these by setting appropriate
5281 bits and offsets. */
5282 if (skip_past_comma (&str) == FAIL
5283 || *str != '[')
5284 {
5285 if (! inst.error)
5286 inst.error = BAD_ARGS;
5287 return;
5288 }
5289
5290 str++;
5291 skip_whitespace (str);
5292
5293 if ((reg = reg_required_here (&str, 16)) == FAIL)
5294 return;
5295
5296 skip_whitespace (str);
5297
5298 if (*str != ']')
5299 {
5300 inst.error = BAD_ARGS;
5301 return;
5302 }
5303
5304 str++;
5305 if (*str == '!')
5306 {
5307 write_back = 1;
5308 str++;
5309 if (reg == REG_PC)
5310 {
5311 inst.error =
5312 _("R15 not allowed as base register with write-back");
5313 return;
5314 }
5315 }
5316 else
5317 write_back = 0;
5318
5319 if (flags & CP_T_Pre)
5320 {
5321 /* Pre-decrement. */
5322 offset = 3 * num_regs;
5323 if (write_back)
5324 flags |= CP_T_WB;
5325 }
5326 else
5327 {
5328 /* Post-increment. */
5329 if (write_back)
5330 {
5331 flags |= CP_T_WB;
5332 offset = 3 * num_regs;
5333 }
5334 else
5335 {
5336 /* No write-back, so convert this into a standard pre-increment
5337 instruction -- aesthetically more pleasing. */
5338 flags = CP_T_Pre | CP_T_UD;
5339 offset = 0;
5340 }
5341 }
5342
5343 inst.instruction |= flags | offset;
5344 }
5345 else if (skip_past_comma (&str) == FAIL
5346 || cp_address_required_here (&str) == FAIL)
5347 {
5348 if (! inst.error)
5349 inst.error = BAD_ARGS;
5350 return;
5351 }
5352
5353 end_of_line (str);
5354}
5355
5356static void
5357do_fp_dyadic (str, flags)
5358 char * str;
5359 unsigned long flags;
5360{
5361 skip_whitespace (str);
5362
5363 switch (inst.suffix)
5364 {
5365 case SUFF_S:
5366 break;
5367 case SUFF_D:
5368 inst.instruction |= 0x00000080;
5369 break;
5370 case SUFF_E:
5371 inst.instruction |= 0x00080000;
5372 break;
5373 default:
5374 abort ();
5375 }
5376
5377 if (fp_reg_required_here (&str, 12) == FAIL)
5378 {
5379 if (! inst.error)
5380 inst.error = BAD_ARGS;
5381 return;
5382 }
5383
5384 if (skip_past_comma (&str) == FAIL
5385 || fp_reg_required_here (&str, 16) == FAIL)
5386 {
5387 if (! inst.error)
5388 inst.error = BAD_ARGS;
5389 return;
5390 }
5391
5392 if (skip_past_comma (&str) == FAIL
5393 || fp_op2 (&str) == FAIL)
5394 {
5395 if (! inst.error)
5396 inst.error = BAD_ARGS;
5397 return;
5398 }
5399
5400 inst.instruction |= flags;
5401 end_of_line (str);
5402 return;
5403}
5404
5405static void
5406do_fp_monadic (str, flags)
5407 char * str;
5408 unsigned long flags;
5409{
5410 skip_whitespace (str);
5411
5412 switch (inst.suffix)
5413 {
5414 case SUFF_S:
5415 break;
5416 case SUFF_D:
5417 inst.instruction |= 0x00000080;
5418 break;
5419 case SUFF_E:
5420 inst.instruction |= 0x00080000;
5421 break;
5422 default:
5423 abort ();
5424 }
5425
5426 if (fp_reg_required_here (&str, 12) == FAIL)
5427 {
5428 if (! inst.error)
5429 inst.error = BAD_ARGS;
5430 return;
5431 }
5432
5433 if (skip_past_comma (&str) == FAIL
5434 || fp_op2 (&str) == FAIL)
5435 {
5436 if (! inst.error)
5437 inst.error = BAD_ARGS;
5438 return;
5439 }
5440
5441 inst.instruction |= flags;
5442 end_of_line (str);
5443 return;
5444}
5445
5446static void
5447do_fp_cmp (str, flags)
5448 char * str;
5449 unsigned long flags;
5450{
5451 skip_whitespace (str);
5452
5453 if (fp_reg_required_here (&str, 16) == FAIL)
5454 {
5455 if (! inst.error)
5456 inst.error = BAD_ARGS;
5457 return;
5458 }
5459
5460 if (skip_past_comma (&str) == FAIL
5461 || fp_op2 (&str) == FAIL)
5462 {
5463 if (! inst.error)
5464 inst.error = BAD_ARGS;
5465 return;
5466 }
5467
5468 inst.instruction |= flags;
5469 end_of_line (str);
5470 return;
5471}
5472
5473static void
5474do_fp_from_reg (str, flags)
5475 char * str;
5476 unsigned long flags;
5477{
5478 skip_whitespace (str);
5479
5480 switch (inst.suffix)
5481 {
5482 case SUFF_S:
5483 break;
5484 case SUFF_D:
5485 inst.instruction |= 0x00000080;
5486 break;
5487 case SUFF_E:
5488 inst.instruction |= 0x00080000;
5489 break;
5490 default:
5491 abort ();
5492 }
5493
5494 if (fp_reg_required_here (&str, 16) == FAIL)
5495 {
5496 if (! inst.error)
5497 inst.error = BAD_ARGS;
5498 return;
5499 }
5500
5501 if (skip_past_comma (&str) == FAIL
5502 || reg_required_here (&str, 12) == FAIL)
5503 {
5504 if (! inst.error)
5505 inst.error = BAD_ARGS;
5506 return;
5507 }
5508
5509 inst.instruction |= flags;
5510 end_of_line (str);
5511 return;
5512}
5513
5514static void
5515do_fp_to_reg (str, flags)
5516 char * str;
5517 unsigned long flags;
5518{
5519 skip_whitespace (str);
5520
5521 if (reg_required_here (&str, 12) == FAIL)
5522 return;
5523
5524 if (skip_past_comma (&str) == FAIL
5525 || fp_reg_required_here (&str, 0) == FAIL)
5526 {
5527 if (! inst.error)
5528 inst.error = BAD_ARGS;
5529 return;
5530 }
5531
5532 inst.instruction |= flags;
5533 end_of_line (str);
5534 return;
5535}
5536
5537/* Thumb specific routines. */
5538
5539/* Parse and validate that a register is of the right form, this saves
5540 repeated checking of this information in many similar cases.
5541 Unlike the 32-bit case we do not insert the register into the opcode
5542 here, since the position is often unknown until the full instruction
5543 has been parsed. */
5544
5545static int
5546thumb_reg (strp, hi_lo)
5547 char ** strp;
5548 int hi_lo;
5549{
5550 int reg;
5551
5552 if ((reg = reg_required_here (strp, -1)) == FAIL)
5553 return FAIL;
5554
5555 switch (hi_lo)
5556 {
5557 case THUMB_REG_LO:
5558 if (reg > 7)
5559 {
5560 inst.error = _("lo register required");
5561 return FAIL;
5562 }
5563 break;
5564
5565 case THUMB_REG_HI:
5566 if (reg < 8)
5567 {
5568 inst.error = _("hi register required");
5569 return FAIL;
5570 }
5571 break;
5572
5573 default:
5574 break;
5575 }
5576
5577 return reg;
5578}
5579
5580/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
5581 was SUB. */
5582
5583static void
5584thumb_add_sub (str, subtract)
5585 char * str;
5586 int subtract;
5587{
5588 int Rd, Rs, Rn = FAIL;
5589
5590 skip_whitespace (str);
5591
5592 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5593 || skip_past_comma (&str) == FAIL)
5594 {
5595 if (! inst.error)
5596 inst.error = BAD_ARGS;
5597 return;
5598 }
5599
5600 if (is_immediate_prefix (*str))
5601 {
5602 Rs = Rd;
5603 str++;
5604 if (my_get_expression (&inst.reloc.exp, &str))
5605 return;
5606 }
5607 else
5608 {
5609 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5610 return;
5611
5612 if (skip_past_comma (&str) == FAIL)
5613 {
5614 /* Two operand format, shuffle the registers
5615 and pretend there are 3. */
5616 Rn = Rs;
5617 Rs = Rd;
5618 }
5619 else if (is_immediate_prefix (*str))
5620 {
5621 str++;
5622 if (my_get_expression (&inst.reloc.exp, &str))
5623 return;
5624 }
5625 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5626 return;
5627 }
5628
5629 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
5630 for the latter case, EXPR contains the immediate that was found. */
5631 if (Rn != FAIL)
5632 {
5633 /* All register format. */
5634 if (Rd > 7 || Rs > 7 || Rn > 7)
5635 {
5636 if (Rs != Rd)
5637 {
5638 inst.error = _("dest and source1 must be the same register");
5639 return;
5640 }
5641
5642 /* Can't do this for SUB. */
5643 if (subtract)
5644 {
5645 inst.error = _("subtract valid only on lo regs");
5646 return;
5647 }
5648
5649 inst.instruction = (T_OPCODE_ADD_HI
5650 | (Rd > 7 ? THUMB_H1 : 0)
5651 | (Rn > 7 ? THUMB_H2 : 0));
5652 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
5653 }
5654 else
5655 {
5656 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
5657 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
5658 }
5659 }
5660 else
5661 {
5662 /* Immediate expression, now things start to get nasty. */
5663
5664 /* First deal with HI regs, only very restricted cases allowed:
5665 Adjusting SP, and using PC or SP to get an address. */
5666 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
5667 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
5668 {
5669 inst.error = _("invalid Hi register with immediate");
5670 return;
5671 }
5672
5673 if (inst.reloc.exp.X_op != O_constant)
5674 {
5675 /* Value isn't known yet, all we can do is store all the fragments
5676 we know about in the instruction and let the reloc hacking
5677 work it all out. */
5678 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
5679 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
5680 }
5681 else
5682 {
5683 int offset = inst.reloc.exp.X_add_number;
5684
5685 if (subtract)
5686 offset = -offset;
5687
5688 if (offset < 0)
5689 {
5690 offset = -offset;
5691 subtract = 1;
5692
5693 /* Quick check, in case offset is MIN_INT. */
5694 if (offset < 0)
5695 {
5696 inst.error = _("immediate value out of range");
5697 return;
5698 }
5699 }
5700 else
5701 subtract = 0;
5702
5703 if (Rd == REG_SP)
5704 {
5705 if (offset & ~0x1fc)
5706 {
5707 inst.error = _("invalid immediate value for stack adjust");
5708 return;
5709 }
5710 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
5711 inst.instruction |= offset >> 2;
5712 }
5713 else if (Rs == REG_PC || Rs == REG_SP)
5714 {
5715 if (subtract
5716 || (offset & ~0x3fc))
5717 {
5718 inst.error = _("invalid immediate for address calculation");
5719 return;
5720 }
5721 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
5722 : T_OPCODE_ADD_SP);
5723 inst.instruction |= (Rd << 8) | (offset >> 2);
5724 }
5725 else if (Rs == Rd)
5726 {
5727 if (offset & ~0xff)
5728 {
5729 inst.error = _("immediate value out of range");
5730 return;
5731 }
5732 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
5733 inst.instruction |= (Rd << 8) | offset;
5734 }
5735 else
5736 {
5737 if (offset & ~0x7)
5738 {
5739 inst.error = _("immediate value out of range");
5740 return;
5741 }
5742 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
5743 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
5744 }
5745 }
5746 }
5747
5748 end_of_line (str);
5749}
5750
5751static void
5752thumb_shift (str, shift)
5753 char * str;
5754 int shift;
5755{
5756 int Rd, Rs, Rn = FAIL;
5757
5758 skip_whitespace (str);
5759
5760 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
5761 || skip_past_comma (&str) == FAIL)
5762 {
5763 if (! inst.error)
5764 inst.error = BAD_ARGS;
5765 return;
5766 }
5767
5768 if (is_immediate_prefix (*str))
5769 {
5770 /* Two operand immediate format, set Rs to Rd. */
5771 Rs = Rd;
5772 str ++;
5773 if (my_get_expression (&inst.reloc.exp, &str))
5774 return;
5775 }
5776 else
5777 {
5778 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
5779 return;
5780
5781 if (skip_past_comma (&str) == FAIL)
5782 {
5783 /* Two operand format, shuffle the registers
5784 and pretend there are 3. */
5785 Rn = Rs;
5786 Rs = Rd;
5787 }
5788 else if (is_immediate_prefix (*str))
5789 {
5790 str++;
5791 if (my_get_expression (&inst.reloc.exp, &str))
5792 return;
5793 }
5794 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
5795 return;
5796 }
5797
5798 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
5799 for the latter case, EXPR contains the immediate that was found. */
5800
5801 if (Rn != FAIL)
5802 {
5803 if (Rs != Rd)
5804 {
5805 inst.error = _("source1 and dest must be same register");
5806 return;
5807 }
5808
5809 switch (shift)
5810 {
5811 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
5812 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
5813 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
5814 }
5815
5816 inst.instruction |= Rd | (Rn << 3);
5817 }
5818 else
5819 {
5820 switch (shift)
5821 {
5822 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
5823 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
5824 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
5825 }
5826
5827 if (inst.reloc.exp.X_op != O_constant)
5828 {
5829 /* Value isn't known yet, create a dummy reloc and let reloc
5830 hacking fix it up. */
5831 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
5832 }
5833 else
5834 {
5835 unsigned shift_value = inst.reloc.exp.X_add_number;
5836
5837 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
5838 {
5839 inst.error = _("Invalid immediate for shift");
5840 return;
5841 }
5842
5843 /* Shifts of zero are handled by converting to LSL. */
5844 if (shift_value == 0)
5845 inst.instruction = T_OPCODE_LSL_I;
5846
5847 /* Shifts of 32 are encoded as a shift of zero. */
5848 if (shift_value == 32)
5849 shift_value = 0;
5850
5851 inst.instruction |= shift_value << 6;
5852 }
5853
5854 inst.instruction |= Rd | (Rs << 3);
5855 }
5856
5857 end_of_line (str);
5858}
5859
5860static void
5861thumb_mov_compare (str, move)
5862 char * str;
5863 int move;
5864{
5865 int Rd, Rs = FAIL;
5866
5867 skip_whitespace (str);
5868
5869 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5870 || skip_past_comma (&str) == FAIL)
5871 {
5872 if (! inst.error)
5873 inst.error = BAD_ARGS;
5874 return;
5875 }
5876
5877 if (is_immediate_prefix (*str))
5878 {
5879 str++;
5880 if (my_get_expression (&inst.reloc.exp, &str))
5881 return;
5882 }
5883 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5884 return;
5885
5886 if (Rs != FAIL)
5887 {
5888 if (Rs < 8 && Rd < 8)
5889 {
5890 if (move == THUMB_MOVE)
5891 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5892 since a MOV instruction produces unpredictable results. */
5893 inst.instruction = T_OPCODE_ADD_I3;
5894 else
5895 inst.instruction = T_OPCODE_CMP_LR;
5896 inst.instruction |= Rd | (Rs << 3);
5897 }
5898 else
5899 {
5900 if (move == THUMB_MOVE)
5901 inst.instruction = T_OPCODE_MOV_HR;
5902 else
5903 inst.instruction = T_OPCODE_CMP_HR;
5904
5905 if (Rd > 7)
5906 inst.instruction |= THUMB_H1;
5907
5908 if (Rs > 7)
5909 inst.instruction |= THUMB_H2;
5910
5911 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5912 }
5913 }
5914 else
5915 {
5916 if (Rd > 7)
5917 {
5918 inst.error = _("only lo regs allowed with immediate");
5919 return;
5920 }
5921
5922 if (move == THUMB_MOVE)
5923 inst.instruction = T_OPCODE_MOV_I8;
5924 else
5925 inst.instruction = T_OPCODE_CMP_I8;
5926
5927 inst.instruction |= Rd << 8;
5928
5929 if (inst.reloc.exp.X_op != O_constant)
5930 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5931 else
5932 {
5933 unsigned value = inst.reloc.exp.X_add_number;
5934
5935 if (value > 255)
5936 {
5937 inst.error = _("invalid immediate");
5938 return;
5939 }
5940
5941 inst.instruction |= value;
5942 }
5943 }
5944
5945 end_of_line (str);
5946}
5947
5948static void
5949thumb_load_store (str, load_store, size)
5950 char * str;
5951 int load_store;
5952 int size;
5953{
5954 int Rd, Rb, Ro = FAIL;
5955
5956 skip_whitespace (str);
5957
5958 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
5959 || skip_past_comma (&str) == FAIL)
5960 {
5961 if (! inst.error)
5962 inst.error = BAD_ARGS;
5963 return;
5964 }
5965
5966 if (*str == '[')
5967 {
5968 str++;
5969 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5970 return;
5971
5972 if (skip_past_comma (&str) != FAIL)
5973 {
5974 if (is_immediate_prefix (*str))
5975 {
5976 str++;
5977 if (my_get_expression (&inst.reloc.exp, &str))
5978 return;
5979 }
5980 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
5981 return;
5982 }
5983 else
5984 {
5985 inst.reloc.exp.X_op = O_constant;
5986 inst.reloc.exp.X_add_number = 0;
5987 }
5988
5989 if (*str != ']')
5990 {
5991 inst.error = _("expected ']'");
5992 return;
5993 }
5994 str++;
5995 }
5996 else if (*str == '=')
5997 {
5998 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5999 str++;
6000
6001 skip_whitespace (str);
6002
6003 if (my_get_expression (& inst.reloc.exp, & str))
6004 return;
6005
6006 end_of_line (str);
6007
6008 if ( inst.reloc.exp.X_op != O_constant
6009 && inst.reloc.exp.X_op != O_symbol)
6010 {
6011 inst.error = "Constant expression expected";
6012 return;
6013 }
6014
6015 if (inst.reloc.exp.X_op == O_constant
6016 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
6017 {
6018 /* This can be done with a mov instruction. */
6019
6020 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
6021 inst.instruction |= inst.reloc.exp.X_add_number;
6022 return;
6023 }
6024
6025 /* Insert into literal pool. */
6026 if (add_to_lit_pool () == FAIL)
6027 {
6028 if (!inst.error)
6029 inst.error = "literal pool insertion failed";
6030 return;
6031 }
6032
6033 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6034 inst.reloc.pc_rel = 1;
6035 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6036 /* Adjust ARM pipeline offset to Thumb. */
6037 inst.reloc.exp.X_add_number += 4;
6038
6039 return;
6040 }
6041 else
6042 {
6043 if (my_get_expression (&inst.reloc.exp, &str))
6044 return;
6045
6046 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
6047 inst.reloc.pc_rel = 1;
6048 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
6049 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6050 end_of_line (str);
6051 return;
6052 }
6053
6054 if (Rb == REG_PC || Rb == REG_SP)
6055 {
6056 if (size != THUMB_WORD)
6057 {
6058 inst.error = _("byte or halfword not valid for base register");
6059 return;
6060 }
6061 else if (Rb == REG_PC && load_store != THUMB_LOAD)
6062 {
6063 inst.error = _("R15 based store not allowed");
6064 return;
6065 }
6066 else if (Ro != FAIL)
6067 {
6068 inst.error = _("Invalid base register for register offset");
6069 return;
6070 }
6071
6072 if (Rb == REG_PC)
6073 inst.instruction = T_OPCODE_LDR_PC;
6074 else if (load_store == THUMB_LOAD)
6075 inst.instruction = T_OPCODE_LDR_SP;
6076 else
6077 inst.instruction = T_OPCODE_STR_SP;
6078
6079 inst.instruction |= Rd << 8;
6080 if (inst.reloc.exp.X_op == O_constant)
6081 {
6082 unsigned offset = inst.reloc.exp.X_add_number;
6083
6084 if (offset & ~0x3fc)
6085 {
6086 inst.error = _("invalid offset");
6087 return;
6088 }
6089
6090 inst.instruction |= offset >> 2;
6091 }
6092 else
6093 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6094 }
6095 else if (Rb > 7)
6096 {
6097 inst.error = _("invalid base register in load/store");
6098 return;
6099 }
6100 else if (Ro == FAIL)
6101 {
6102 /* Immediate offset. */
6103 if (size == THUMB_WORD)
6104 inst.instruction = (load_store == THUMB_LOAD
6105 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
6106 else if (size == THUMB_HALFWORD)
6107 inst.instruction = (load_store == THUMB_LOAD
6108 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
6109 else
6110 inst.instruction = (load_store == THUMB_LOAD
6111 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
6112
6113 inst.instruction |= Rd | (Rb << 3);
6114
6115 if (inst.reloc.exp.X_op == O_constant)
6116 {
6117 unsigned offset = inst.reloc.exp.X_add_number;
6118
6119 if (offset & ~(0x1f << size))
6120 {
6121 inst.error = _("Invalid offset");
6122 return;
6123 }
6124 inst.instruction |= (offset >> size) << 6;
6125 }
6126 else
6127 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
6128 }
6129 else
6130 {
6131 /* Register offset. */
6132 if (size == THUMB_WORD)
6133 inst.instruction = (load_store == THUMB_LOAD
6134 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
6135 else if (size == THUMB_HALFWORD)
6136 inst.instruction = (load_store == THUMB_LOAD
6137 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
6138 else
6139 inst.instruction = (load_store == THUMB_LOAD
6140 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
6141
6142 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
6143 }
6144
6145 end_of_line (str);
6146}
6147
404ff6b5
AH
6148/* Given a register and a register type, return 1 if
6149 the register is of the given type, else return 0. */
6150
6151static int
6152cirrus_valid_reg (reg, regtype)
6153 int reg;
6154 enum cirrus_regtype regtype;
6155{
6156 switch (regtype)
6157 {
6158 case CIRRUS_REGTYPE_ANY:
6159 return 1;
6160
6161 case CIRRUS_REGTYPE_MVF:
6162 return cirrus_mvf_register (reg);
6163
6164 case CIRRUS_REGTYPE_MVFX:
6165 return cirrus_mvfx_register (reg);
6166
6167 case CIRRUS_REGTYPE_MVD:
6168 return cirrus_mvd_register (reg);
6169
6170 case CIRRUS_REGTYPE_MVDX:
6171 return cirrus_mvdx_register (reg);
6172
6173 case CIRRUS_REGTYPE_MVAX:
6174 return cirrus_mvax_register (reg);
6175
6176 case CIRRUS_REGTYPE_DSPSC:
90f9b791 6177 return ARM_EXT_MAVERICKsc_register (reg);
404ff6b5
AH
6178 }
6179
6180 return 0;
6181}
6182
6183/* A register must be given at this point.
6184
6185 If the register is a Cirrus register, convert it's reg# appropriately.
6186
6187 Shift is the place to put it in inst.instruction.
6188
6189 regtype is type register type expected, and is:
6190 CIRRUS_REGTYPE_MVF
6191 CIRRUS_REGTYPE_MVFX
6192 CIRRUS_REGTYPE_MVD
6193 CIRRUS_REGTYPE_MVDX
6194 CIRRUS_REGTYPE_MVAX
6195 CIRRUS_REGTYPE_DSPSC
6196
6197 Restores input start point on err.
6198 Returns the reg#, or FAIL. */
6199
6200static int
6201cirrus_reg_required_here (str, shift, regtype)
6202 char ** str;
6203 int shift;
6204 enum cirrus_regtype regtype;
6205{
6206 static char buff [135]; /* XXX */
6207 int reg;
6208 char * start = * str;
6209
6210 if ((reg = arm_reg_parse (str)) != FAIL
6211 && (int_register (reg)
6212 || cirrus_register (reg)))
6213 {
6214 int orig_reg = reg;
6215
6216 /* Calculate actual register # for opcode. */
6217 if (cirrus_register (reg)
90f9b791 6218 && !ARM_EXT_MAVERICKsc_register (reg)) /* Leave this one as is. */
404ff6b5
AH
6219 {
6220 if (reg >= 130)
6221 reg -= 130;
6222 else if (reg >= 110)
6223 reg -= 110;
6224 else if (reg >= 90)
6225 reg -= 90;
6226 else if (reg >= 70)
6227 reg -= 70;
6228 else if (reg >= 50)
6229 reg -= 50;
6230 }
6231
6232 if (!cirrus_valid_reg (orig_reg, regtype))
6233 {
6234 sprintf (buff, _("invalid register type at '%.100s'"), start);
6235 inst.error = buff;
6236 return FAIL;
6237 }
6238
6239 if (shift >= 0)
6240 inst.instruction |= reg << shift;
6241
6242 return orig_reg;
6243 }
6244
6245 /* Restore the start point, we may have got a reg of the wrong class. */
6246 *str = start;
6247
6248 /* In the few cases where we might be able to accept something else
6249 this error can be overridden. */
6250 sprintf (buff, _("Cirrus register expected, not '%.100s'"), start);
6251 inst.error = buff;
6252
6253 return FAIL;
6254}
6255
6256/* Cirrus Instructions. */
6257
6258/* Wrapper functions. */
6259
6260static void
6261do_c_binops_1 (str, flags)
6262 char * str;
6263 unsigned long flags;
6264{
6265 do_c_binops (str, flags, CIRRUS_MODE1);
6266}
6267
6268static void
6269do_c_binops_2 (str, flags)
6270 char * str;
6271 unsigned long flags;
6272{
6273 do_c_binops (str, flags, CIRRUS_MODE2);
6274}
6275
6276static void
6277do_c_binops_3 (str, flags)
6278 char * str;
6279 unsigned long flags;
6280{
6281 do_c_binops (str, flags, CIRRUS_MODE3);
6282}
6283
6284static void
6285do_c_triple_4 (str, flags)
6286 char * str;
6287 unsigned long flags;
6288{
6289 do_c_triple (str, flags, CIRRUS_MODE4);
6290}
6291
6292static void
6293do_c_triple_5 (str, flags)
6294 char * str;
6295 unsigned long flags;
6296{
6297 do_c_triple (str, flags, CIRRUS_MODE5);
6298}
6299
6300static void
6301do_c_quad_6 (str, flags)
6302 char * str;
6303 unsigned long flags;
6304{
6305 do_c_quad (str, flags, CIRRUS_MODE6);
6306}
6307
6308static void
6309do_c_dspsc_1 (str, flags)
6310 char * str;
6311 unsigned long flags;
6312{
6313 do_c_dspsc (str, flags, CIRRUS_MODE1);
6314}
6315
6316static void
6317do_c_dspsc_2 (str, flags)
6318 char * str;
6319 unsigned long flags;
6320{
6321 do_c_dspsc (str, flags, CIRRUS_MODE2);
6322}
6323
6324static void
6325do_c_shift_1 (str, flags)
6326 char * str;
6327 unsigned long flags;
6328{
6329 do_c_shift (str, flags, CIRRUS_MODE1);
6330}
6331
6332static void
6333do_c_shift_2 (str, flags)
6334 char * str;
6335 unsigned long flags;
6336{
6337 do_c_shift (str, flags, CIRRUS_MODE2);
6338}
6339
6340static void
6341do_c_ldst_1 (str, flags)
6342 char * str;
6343 unsigned long flags;
6344{
6345 do_c_ldst (str, flags, CIRRUS_MODE1);
6346}
6347
6348static void
6349do_c_ldst_2 (str, flags)
6350 char * str;
6351 unsigned long flags;
6352{
6353 do_c_ldst (str, flags, CIRRUS_MODE2);
6354}
6355
6356static void
6357do_c_ldst_3 (str, flags)
6358 char * str;
6359 unsigned long flags;
6360{
6361 do_c_ldst (str, flags, CIRRUS_MODE3);
6362}
6363
6364static void
6365do_c_ldst_4 (str, flags)
6366 char * str;
6367 unsigned long flags;
6368{
6369 do_c_ldst (str, flags, CIRRUS_MODE4);
6370}
6371
6372/* Isnsn like "foo X,Y". */
6373
6374static void
6375do_c_binops (str, flags, mode)
6376 char * str;
6377 unsigned long flags;
6378 int mode;
6379{
6380 int shift1, shift2;
6381
6382 shift1 = mode & 0xff;
6383 shift2 = (mode >> 8) & 0xff;
6384
6385 skip_whitespace (str);
6386
6387 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
6388 || skip_past_comma (&str) == FAIL
6389 || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL)
6390 {
6391 if (!inst.error)
6392 inst.error = BAD_ARGS;
6393 }
6394 else
6395 end_of_line (str);
6396
6397 inst.instruction |= flags;
6398 return;
6399}
6400
6401/* Isnsn like "foo X,Y,Z". */
6402
6403static void
6404do_c_triple (str, flags, mode)
6405 char * str;
6406 unsigned long flags;
6407 int mode;
6408{
6409 int shift1, shift2, shift3;
6410
6411 shift1 = mode & 0xff;
6412 shift2 = (mode >> 8) & 0xff;
6413 shift3 = (mode >> 16) & 0xff;
6414
6415 skip_whitespace (str);
6416
6417 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
6418 || skip_past_comma (&str) == FAIL
6419 || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL
6420 || skip_past_comma (&str) == FAIL
6421 || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_ANY) == FAIL)
6422 {
6423 if (!inst.error)
6424 inst.error = BAD_ARGS;
6425 }
6426 else
6427 end_of_line (str);
6428
6429 inst.instruction |= flags;
6430 return;
6431}
6432
6433/* Isnsn like "foo W,X,Y,Z".
6434 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
6435
6436static void
6437do_c_quad (str, flags, mode)
6438 char * str;
6439 unsigned long flags;
6440 int mode;
6441{
6442 int shift1, shift2, shift3, shift4;
6443 enum cirrus_regtype rt;
6444
6445 rt = (inst.instruction << 4 == 0xe2006000
6446 || inst.instruction << 4 == 0xe3006000) ? CIRRUS_REGTYPE_MVAX
6447 : CIRRUS_REGTYPE_MVFX;
6448
6449 shift1 = mode & 0xff;
6450 shift2 = (mode >> 8) & 0xff;
6451 shift3 = (mode >> 16) & 0xff;
6452 shift4 = (mode >> 24) & 0xff;
6453
6454 skip_whitespace (str);
6455
6456 if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_MVAX) == FAIL
6457 || skip_past_comma (&str) == FAIL
6458 || cirrus_reg_required_here (&str, shift2, rt) == FAIL
6459 || skip_past_comma (&str) == FAIL
6460 || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_MVFX) == FAIL
6461 || skip_past_comma (&str) == FAIL
6462 || cirrus_reg_required_here (&str, shift4, CIRRUS_REGTYPE_MVFX) == FAIL)
6463 {
6464 if (!inst.error)
6465 inst.error = BAD_ARGS;
6466 }
6467 else
6468 end_of_line (str);
6469
6470 inst.instruction |= flags;
6471 return;
6472}
6473
6474/* cfmvsc32<cond> DSPSC,MVFX[15:0].
6475 cfmv32sc<cond> MVFX[15:0],DSPSC. */
6476
6477static void
6478do_c_dspsc (str, flags, mode)
6479 char * str;
6480 unsigned long flags;
6481 int mode;
6482{
6483 int error;
6484
6485 skip_whitespace (str);
6486
6487 error = 0;
6488
6489 if (mode == CIRRUS_MODE1)
6490 {
6491 /* cfmvsc32. */
6492 if (cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL
6493 || skip_past_comma (&str) == FAIL
6494 || cirrus_reg_required_here (&str, 16, CIRRUS_REGTYPE_MVFX) == FAIL)
6495 error = 1;
6496 }
6497 else
6498 {
6499 /* cfmv32sc. */
6500 if (cirrus_reg_required_here (&str, 0, CIRRUS_REGTYPE_MVFX) == FAIL
6501 || skip_past_comma (&str) == FAIL
6502 || cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL)
6503 error = 1;
6504 }
6505
6506 if (error)
6507 {
6508 if (!inst.error)
6509 inst.error = BAD_ARGS;
6510 }
6511 else
6512 {
6513 inst.instruction |= flags;
6514 end_of_line (str);
6515 }
6516
6517 return;
6518}
6519
6520/* Cirrus shift immediate instructions.
6521 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
6522 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
6523
6524static void
6525do_c_shift (str, flags, mode)
6526 char * str;
6527 unsigned long flags;
6528 int mode;
6529{
6530 int error;
6531 int imm, neg = 0;
6532
6533 skip_whitespace (str);
6534
6535 error = 0;
6536
6537 if (cirrus_reg_required_here (&str, 12,
6538 (mode == CIRRUS_MODE1)
6539 ? CIRRUS_REGTYPE_MVFX
6540 : CIRRUS_REGTYPE_MVDX) == FAIL
6541 || skip_past_comma (&str) == FAIL
6542 || cirrus_reg_required_here (&str, 16,
6543 (mode == CIRRUS_MODE1)
6544 ? CIRRUS_REGTYPE_MVFX
6545 : CIRRUS_REGTYPE_MVDX) == FAIL
6546 || skip_past_comma (&str) == FAIL)
6547 {
6548 if (!inst.error)
6549 inst.error = BAD_ARGS;
6550 return;
6551 }
6552
6553 /* Calculate the immediate operand.
6554 The operand is a 7bit signed number. */
6555 skip_whitespace (str);
6556
6557 if (*str == '#')
6558 ++str;
6559
6560 if (!isdigit (*str) && *str != '-')
6561 {
6562 inst.error = _("expecting immediate, 7bit operand");
6563 return;
6564 }
6565
6566 if (*str == '-')
6567 {
6568 neg = 1;
6569 ++str;
6570 }
6571
6572 for (imm = 0; *str && isdigit (*str); ++str)
6573 imm = imm * 10 + *str - '0';
6574
6575 if (imm > 64)
6576 {
6577 inst.error = _("immediate out of range");
6578 return;
6579 }
6580
6581 /* Make negative imm's into 7bit signed numbers. */
6582 if (neg)
6583 {
6584 imm = -imm;
6585 imm &= 0x0000007f;
6586 }
6587
6588 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
6589 Bits 5-7 of the insn should have bits 4-6 of the immediate.
6590 Bit 4 should be 0. */
6591 imm = (imm & 0xf) | ((imm & 0x70) << 1);
6592
6593 inst.instruction |= imm;
6594 inst.instruction |= flags;
6595
6596 end_of_line (str);
6597
6598 return;
6599}
6600
6601static int
6602cirrus_parse_offset (str, negative)
6603 char ** str;
6604 int *negative;
6605{
6606 char * p = *str;
6607 int offset;
6608
6609 *negative = 0;
6610
6611 skip_whitespace (p);
6612
6613 if (*p == '#')
6614 ++p;
6615
6616 if (*p == '-')
6617 {
6618 *negative = 1;
6619 ++p;
6620 }
6621
6622 if (!isdigit (*p))
6623 {
6624 inst.error = _("offset expected");
6625 return 0;
6626 }
6627
6628 for (offset = 0; *p && isdigit (*p); ++p)
6629 offset = offset * 10 + *p - '0';
6630
6631 if (offset > 0xff)
6632 {
6633 inst.error = _("offset out of range");
6634 return 0;
6635 }
6636
6637 *str = p;
6638
6639 return *negative ? -offset : offset;
6640}
6641
6642/* Cirrus load/store instructions.
6643 <insn><cond> CRd,[Rn,<offset>]{!}.
6644 <insn><cond> CRd,[Rn],<offset>. */
6645
6646static void
6647do_c_ldst (str, flags, mode)
6648 char * str;
6649 unsigned long flags;
6650 int mode;
6651{
6652 int offset, negative;
6653 enum cirrus_regtype rt;
6654
6655 rt = mode == CIRRUS_MODE1 ? CIRRUS_REGTYPE_MVF
6656 : mode == CIRRUS_MODE2 ? CIRRUS_REGTYPE_MVD
6657 : mode == CIRRUS_MODE3 ? CIRRUS_REGTYPE_MVFX
6658 : mode == CIRRUS_MODE4 ? CIRRUS_REGTYPE_MVDX : CIRRUS_REGTYPE_MVF;
6659
6660 skip_whitespace (str);
6661
6662 if (cirrus_reg_required_here (& str, 12, rt) == FAIL
6663 || skip_past_comma (& str) == FAIL
6664 || *str++ != '['
6665 || reg_required_here (& str, 16) == FAIL)
6666 goto fail_ldst;
6667
6668 if (skip_past_comma (& str) == SUCCESS)
6669 {
6670 /* You are here: "<offset>]{!}". */
6671 inst.instruction |= PRE_INDEX;
6672
6673 offset = cirrus_parse_offset (&str, &negative);
6674
6675 if (inst.error)
6676 return;
6677
6678 if (*str++ != ']')
6679 {
6680 inst.error = _("missing ]");
6681 return;
6682 }
6683
6684 if (*str == '!')
6685 {
6686 inst.instruction |= WRITE_BACK;
6687 ++str;
6688 }
6689 }
6690 else
6691 {
6692 /* You are here: "], <offset>". */
6693 if (*str++ != ']')
6694 {
6695 inst.error = _("missing ]");
6696 return;
6697 }
6698
6699 if (skip_past_comma (&str) == FAIL
6700 || (offset = cirrus_parse_offset (&str, &negative), inst.error))
6701 goto fail_ldst;
6702
6703 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
6704 }
6705
6706 if (negative)
6707 offset = -offset;
6708 else
6709 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
6710
6711 inst.instruction |= offset >> 2;
6712 inst.instruction |= flags;
6713
6714 end_of_line (str);
6715 return;
6716
6717fail_ldst:
6718 if (!inst.error)
6719 inst.error = BAD_ARGS;
6720 return;
6721}
6722
b99bd4ef
NC
6723static void
6724do_t_nop (str)
6725 char * str;
6726{
6727 /* Do nothing. */
6728 end_of_line (str);
6729 return;
6730}
6731
6732/* Handle the Format 4 instructions that do not have equivalents in other
6733 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
6734 BIC and MVN. */
6735
6736static void
6737do_t_arit (str)
6738 char * str;
6739{
6740 int Rd, Rs, Rn;
6741
6742 skip_whitespace (str);
6743
6744 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6745 || skip_past_comma (&str) == FAIL
6746 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6747 {
6748 inst.error = BAD_ARGS;
6749 return;
6750 }
6751
6752 if (skip_past_comma (&str) != FAIL)
6753 {
6754 /* Three operand format not allowed for TST, CMN, NEG and MVN.
6755 (It isn't allowed for CMP either, but that isn't handled by this
6756 function.) */
6757 if (inst.instruction == T_OPCODE_TST
6758 || inst.instruction == T_OPCODE_CMN
6759 || inst.instruction == T_OPCODE_NEG
6760 || inst.instruction == T_OPCODE_MVN)
6761 {
6762 inst.error = BAD_ARGS;
6763 return;
6764 }
6765
6766 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6767 return;
6768
6769 if (Rs != Rd)
6770 {
6771 inst.error = _("dest and source1 must be the same register");
6772 return;
6773 }
6774 Rs = Rn;
6775 }
6776
6777 if (inst.instruction == T_OPCODE_MUL
6778 && Rs == Rd)
6779 as_tsktsk (_("Rs and Rd must be different in MUL"));
6780
6781 inst.instruction |= Rd | (Rs << 3);
6782 end_of_line (str);
6783}
6784
6785static void
6786do_t_add (str)
6787 char * str;
6788{
6789 thumb_add_sub (str, 0);
6790}
6791
6792static void
6793do_t_asr (str)
6794 char * str;
6795{
6796 thumb_shift (str, THUMB_ASR);
6797}
6798
6799static void
6800do_t_branch9 (str)
6801 char * str;
6802{
6803 if (my_get_expression (&inst.reloc.exp, &str))
6804 return;
6805 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
6806 inst.reloc.pc_rel = 1;
6807 end_of_line (str);
6808}
6809
6810static void
6811do_t_branch12 (str)
6812 char * str;
6813{
6814 if (my_get_expression (&inst.reloc.exp, &str))
6815 return;
6816 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
6817 inst.reloc.pc_rel = 1;
6818 end_of_line (str);
6819}
6820
6821/* Find the real, Thumb encoded start of a Thumb function. */
6822
6823static symbolS *
6824find_real_start (symbolP)
6825 symbolS * symbolP;
6826{
6827 char * real_start;
6828 const char * name = S_GET_NAME (symbolP);
6829 symbolS * new_target;
6830
6831 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
6832#define STUB_NAME ".real_start_of"
6833
6834 if (name == NULL)
6835 abort ();
6836
6837 /* Names that start with '.' are local labels, not function entry points.
6838 The compiler may generate BL instructions to these labels because it
6839 needs to perform a branch to a far away location. */
6840 if (name[0] == '.')
6841 return symbolP;
6842
6843 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
6844 sprintf (real_start, "%s%s", STUB_NAME, name);
6845
6846 new_target = symbol_find (real_start);
6847
6848 if (new_target == NULL)
6849 {
6850 as_warn ("Failed to find real start of function: %s\n", name);
6851 new_target = symbolP;
6852 }
6853
6854 free (real_start);
6855
6856 return new_target;
6857}
6858
6859static void
6860do_t_branch23 (str)
6861 char * str;
6862{
6863 if (my_get_expression (& inst.reloc.exp, & str))
6864 return;
6865
6866 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
6867 inst.reloc.pc_rel = 1;
6868 end_of_line (str);
6869
6870 /* If the destination of the branch is a defined symbol which does not have
6871 the THUMB_FUNC attribute, then we must be calling a function which has
6872 the (interfacearm) attribute. We look for the Thumb entry point to that
6873 function and change the branch to refer to that function instead. */
6874 if ( inst.reloc.exp.X_op == O_symbol
6875 && inst.reloc.exp.X_add_symbol != NULL
6876 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
6877 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
6878 inst.reloc.exp.X_add_symbol =
6879 find_real_start (inst.reloc.exp.X_add_symbol);
6880}
6881
6882static void
6883do_t_bx (str)
6884 char * str;
6885{
6886 int reg;
6887
6888 skip_whitespace (str);
6889
6890 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
6891 return;
6892
6893 /* This sets THUMB_H2 from the top bit of reg. */
6894 inst.instruction |= reg << 3;
6895
6896 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
6897 should cause the alignment to be checked once it is known. This is
6898 because BX PC only works if the instruction is word aligned. */
6899
6900 end_of_line (str);
6901}
6902
6903static void
6904do_t_compare (str)
6905 char * str;
6906{
6907 thumb_mov_compare (str, THUMB_COMPARE);
6908}
6909
6910static void
6911do_t_ldmstm (str)
6912 char * str;
6913{
6914 int Rb;
6915 long range;
6916
6917 skip_whitespace (str);
6918
6919 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6920 return;
6921
6922 if (*str != '!')
6923 as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
6924 else
6925 str++;
6926
6927 if (skip_past_comma (&str) == FAIL
6928 || (range = reg_list (&str)) == FAIL)
6929 {
6930 if (! inst.error)
6931 inst.error = BAD_ARGS;
6932 return;
6933 }
6934
6935 if (inst.reloc.type != BFD_RELOC_NONE)
6936 {
6937 /* This really doesn't seem worth it. */
6938 inst.reloc.type = BFD_RELOC_NONE;
6939 inst.error = _("Expression too complex");
6940 return;
6941 }
6942
6943 if (range & ~0xff)
6944 {
6945 inst.error = _("only lo-regs valid in load/store multiple");
6946 return;
6947 }
6948
6949 inst.instruction |= (Rb << 8) | range;
6950 end_of_line (str);
6951}
6952
6953static void
6954do_t_ldr (str)
6955 char * str;
6956{
6957 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
6958}
6959
6960static void
6961do_t_ldrb (str)
6962 char * str;
6963{
6964 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
6965}
6966
6967static void
6968do_t_ldrh (str)
6969 char * str;
6970{
6971 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
6972}
6973
6974static void
6975do_t_lds (str)
6976 char * str;
6977{
6978 int Rd, Rb, Ro;
6979
6980 skip_whitespace (str);
6981
6982 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6983 || skip_past_comma (&str) == FAIL
6984 || *str++ != '['
6985 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6986 || skip_past_comma (&str) == FAIL
6987 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6988 || *str++ != ']')
6989 {
6990 if (! inst.error)
6991 inst.error = _("Syntax: ldrs[b] Rd, [Rb, Ro]");
6992 return;
6993 }
6994
6995 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
6996 end_of_line (str);
6997}
6998
6999static void
7000do_t_lsl (str)
7001 char * str;
7002{
7003 thumb_shift (str, THUMB_LSL);
7004}
7005
7006static void
7007do_t_lsr (str)
7008 char * str;
7009{
7010 thumb_shift (str, THUMB_LSR);
7011}
7012
7013static void
7014do_t_mov (str)
7015 char * str;
7016{
7017 thumb_mov_compare (str, THUMB_MOVE);
7018}
7019
7020static void
7021do_t_push_pop (str)
7022 char * str;
7023{
7024 long range;
7025
7026 skip_whitespace (str);
7027
7028 if ((range = reg_list (&str)) == FAIL)
7029 {
7030 if (! inst.error)
7031 inst.error = BAD_ARGS;
7032 return;
7033 }
7034
7035 if (inst.reloc.type != BFD_RELOC_NONE)
7036 {
7037 /* This really doesn't seem worth it. */
7038 inst.reloc.type = BFD_RELOC_NONE;
7039 inst.error = _("Expression too complex");
7040 return;
7041 }
7042
7043 if (range & ~0xff)
7044 {
7045 if ((inst.instruction == T_OPCODE_PUSH
7046 && (range & ~0xff) == 1 << REG_LR)
7047 || (inst.instruction == T_OPCODE_POP
7048 && (range & ~0xff) == 1 << REG_PC))
7049 {
7050 inst.instruction |= THUMB_PP_PC_LR;
7051 range &= 0xff;
7052 }
7053 else
7054 {
7055 inst.error = _("invalid register list to push/pop instruction");
7056 return;
7057 }
7058 }
7059
7060 inst.instruction |= range;
7061 end_of_line (str);
7062}
7063
7064static void
7065do_t_str (str)
7066 char * str;
7067{
7068 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
7069}
7070
7071static void
7072do_t_strb (str)
7073 char * str;
7074{
7075 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
7076}
7077
7078static void
7079do_t_strh (str)
7080 char * str;
7081{
7082 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
7083}
7084
7085static void
7086do_t_sub (str)
7087 char * str;
7088{
7089 thumb_add_sub (str, 1);
7090}
7091
7092static void
7093do_t_swi (str)
7094 char * str;
7095{
7096 skip_whitespace (str);
7097
7098 if (my_get_expression (&inst.reloc.exp, &str))
7099 return;
7100
7101 inst.reloc.type = BFD_RELOC_ARM_SWI;
7102 end_of_line (str);
7103 return;
7104}
7105
7106static void
7107do_t_adr (str)
7108 char * str;
7109{
7110 int reg;
7111
7112 /* This is a pseudo-op of the form "adr rd, label" to be converted
7113 into a relative address of the form "add rd, pc, #label-.-4". */
7114 skip_whitespace (str);
7115
7116 /* Store Rd in temporary location inside instruction. */
7117 if ((reg = reg_required_here (&str, 4)) == FAIL
7118 || (reg > 7) /* For Thumb reg must be r0..r7. */
7119 || skip_past_comma (&str) == FAIL
7120 || my_get_expression (&inst.reloc.exp, &str))
7121 {
7122 if (!inst.error)
7123 inst.error = BAD_ARGS;
7124 return;
7125 }
7126
7127 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
7128 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
7129 inst.reloc.pc_rel = 1;
7130 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
7131
7132 end_of_line (str);
7133}
7134
7135static void
7136insert_reg (entry)
7137 int entry;
7138{
7139 int len = strlen (reg_table[entry].name) + 2;
7140 char * buf = (char *) xmalloc (len);
7141 char * buf2 = (char *) xmalloc (len);
7142 int i = 0;
7143
7144#ifdef REGISTER_PREFIX
7145 buf[i++] = REGISTER_PREFIX;
7146#endif
7147
7148 strcpy (buf + i, reg_table[entry].name);
7149
7150 for (i = 0; buf[i]; i++)
3882b010 7151 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
7152
7153 buf2[i] = '\0';
7154
7155 hash_insert (arm_reg_hsh, buf, (PTR) & reg_table[entry]);
7156 hash_insert (arm_reg_hsh, buf2, (PTR) & reg_table[entry]);
7157}
7158
7159static void
7160insert_reg_alias (str, regnum)
7161 char *str;
7162 int regnum;
7163{
7164 struct reg_entry *new =
7165 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
7166 char *name = xmalloc (strlen (str) + 1);
7167 strcpy (name, str);
7168
7169 new->name = name;
7170 new->number = regnum;
7171
7172 hash_insert (arm_reg_hsh, name, (PTR) new);
7173}
7174
7175static void
7176set_constant_flonums ()
7177{
7178 int i;
7179
7180 for (i = 0; i < NUM_FLOAT_VALS; i++)
7181 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
7182 abort ();
7183}
7184
7185void
7186md_begin ()
7187{
7188 unsigned mach;
7189 unsigned int i;
7190
7191 if ( (arm_ops_hsh = hash_new ()) == NULL
7192 || (arm_tops_hsh = hash_new ()) == NULL
7193 || (arm_cond_hsh = hash_new ()) == NULL
7194 || (arm_shift_hsh = hash_new ()) == NULL
7195 || (arm_reg_hsh = hash_new ()) == NULL
7196 || (arm_psr_hsh = hash_new ()) == NULL)
7197 as_fatal (_("Virtual memory exhausted"));
7198
7199 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
7200 hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
7201 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
7202 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
7203 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
7204 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
7205 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
7206 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
7207 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
7208 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
7209
7210 for (i = 0; reg_table[i].name; i++)
7211 insert_reg (i);
7212
7213 set_constant_flonums ();
7214
7215#if defined OBJ_COFF || defined OBJ_ELF
7216 {
7217 unsigned int flags = 0;
7218
7219 /* Set the flags in the private structure. */
7220 if (uses_apcs_26) flags |= F_APCS26;
7221 if (support_interwork) flags |= F_INTERWORK;
7222 if (uses_apcs_float) flags |= F_APCS_FLOAT;
7223 if (pic_code) flags |= F_PIC;
7224 if ((cpu_variant & FPU_ALL) == FPU_NONE) flags |= F_SOFT_FLOAT;
7225
7226 bfd_set_private_flags (stdoutput, flags);
7227
7228 /* We have run out flags in the COFF header to encode the
7229 status of ATPCS support, so instead we create a dummy,
7230 empty, debug section called .arm.atpcs. */
7231 if (atpcs)
7232 {
7233 asection * sec;
7234
7235 sec = bfd_make_section (stdoutput, ".arm.atpcs");
7236
7237 if (sec != NULL)
7238 {
7239 bfd_set_section_flags
7240 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
7241 bfd_set_section_size (stdoutput, sec, 0);
7242 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
7243 }
7244 }
7245 }
7246#endif
7247
7248 /* Record the CPU type as well. */
7249 switch (cpu_variant & ARM_CPU_MASK)
7250 {
7251 case ARM_2:
7252 mach = bfd_mach_arm_2;
7253 break;
7254
7255 case ARM_3: /* Also ARM_250. */
7256 mach = bfd_mach_arm_2a;
7257 break;
7258
7259 default:
7260 case ARM_6 | ARM_3 | ARM_2: /* Actually no CPU type defined. */
7261 mach = bfd_mach_arm_4;
7262 break;
7263
7264 case ARM_7: /* Also ARM_6. */
7265 mach = bfd_mach_arm_3;
7266 break;
7267 }
7268
7269 /* Catch special cases. */
7270 if (cpu_variant & ARM_EXT_XSCALE)
7271 mach = bfd_mach_arm_XScale;
7272 else if (cpu_variant & ARM_EXT_V5E)
7273 mach = bfd_mach_arm_5TE;
7274 else if (cpu_variant & ARM_EXT_V5)
7275 {
7276 if (cpu_variant & ARM_EXT_THUMB)
7277 mach = bfd_mach_arm_5T;
7278 else
7279 mach = bfd_mach_arm_5;
7280 }
7281 else if (cpu_variant & ARM_EXT_HALFWORD)
7282 {
7283 if (cpu_variant & ARM_EXT_THUMB)
7284 mach = bfd_mach_arm_4T;
7285 else
7286 mach = bfd_mach_arm_4;
7287 }
7288 else if (cpu_variant & ARM_EXT_LONGMUL)
7289 mach = bfd_mach_arm_3M;
7290
7291 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
7292}
7293
7294/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7295 for use in the a.out file, and stores them in the array pointed to by buf.
7296 This knows about the endian-ness of the target machine and does
7297 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
7298 2 (short) and 4 (long) Floating numbers are put out as a series of
7299 LITTLENUMS (shorts, here at least). */
7300
7301void
7302md_number_to_chars (buf, val, n)
7303 char * buf;
7304 valueT val;
7305 int n;
7306{
7307 if (target_big_endian)
7308 number_to_chars_bigendian (buf, val, n);
7309 else
7310 number_to_chars_littleendian (buf, val, n);
7311}
7312
7313static valueT
7314md_chars_to_number (buf, n)
7315 char * buf;
7316 int n;
7317{
7318 valueT result = 0;
7319 unsigned char * where = (unsigned char *) buf;
7320
7321 if (target_big_endian)
7322 {
7323 while (n--)
7324 {
7325 result <<= 8;
7326 result |= (*where++ & 255);
7327 }
7328 }
7329 else
7330 {
7331 while (n--)
7332 {
7333 result <<= 8;
7334 result |= (where[n] & 255);
7335 }
7336 }
7337
7338 return result;
7339}
7340
7341/* Turn a string in input_line_pointer into a floating point constant
7342 of type TYPE, and store the appropriate bytes in *LITP. The number
7343 of LITTLENUMS emitted is stored in *SIZEP. An error message is
7344 returned, or NULL on OK.
7345
7346 Note that fp constants aren't represent in the normal way on the ARM.
7347 In big endian mode, things are as expected. However, in little endian
7348 mode fp constants are big-endian word-wise, and little-endian byte-wise
7349 within the words. For example, (double) 1.1 in big endian mode is
7350 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7351 the byte sequence 99 99 f1 3f 9a 99 99 99.
7352
7353 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
7354
7355char *
7356md_atof (type, litP, sizeP)
7357 char type;
7358 char * litP;
7359 int * sizeP;
7360{
7361 int prec;
7362 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7363 char *t;
7364 int i;
7365
7366 switch (type)
7367 {
7368 case 'f':
7369 case 'F':
7370 case 's':
7371 case 'S':
7372 prec = 2;
7373 break;
7374
7375 case 'd':
7376 case 'D':
7377 case 'r':
7378 case 'R':
7379 prec = 4;
7380 break;
7381
7382 case 'x':
7383 case 'X':
7384 prec = 6;
7385 break;
7386
7387 case 'p':
7388 case 'P':
7389 prec = 6;
7390 break;
7391
7392 default:
7393 *sizeP = 0;
7394 return _("Bad call to MD_ATOF()");
7395 }
7396
7397 t = atof_ieee (input_line_pointer, type, words);
7398 if (t)
7399 input_line_pointer = t;
7400 *sizeP = prec * 2;
7401
7402 if (target_big_endian)
7403 {
7404 for (i = 0; i < prec; i++)
7405 {
7406 md_number_to_chars (litP, (valueT) words[i], 2);
7407 litP += 2;
7408 }
7409 }
7410 else
7411 {
7412 /* For a 4 byte float the order of elements in `words' is 1 0. For an
7413 8 byte float the order is 1 0 3 2. */
7414 for (i = 0; i < prec; i += 2)
7415 {
7416 md_number_to_chars (litP, (valueT) words[i + 1], 2);
7417 md_number_to_chars (litP + 2, (valueT) words[i], 2);
7418 litP += 4;
7419 }
7420 }
7421
7422 return 0;
7423}
7424
7425/* The knowledge of the PC's pipeline offset is built into the insns
7426 themselves. */
7427
7428long
7429md_pcrel_from (fixP)
7430 fixS * fixP;
7431{
7432 if (fixP->fx_addsy
7433 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
7434 && fixP->fx_subsy == NULL)
7435 return 0;
7436
7437 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
7438 {
7439 /* PC relative addressing on the Thumb is slightly odd
7440 as the bottom two bits of the PC are forced to zero
7441 for the calculation. */
7442 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
7443 }
7444
7445#ifdef TE_WINCE
7446 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
7447 so we un-adjust here to compensate for the accomodation. */
7448 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
7449#else
7450 return fixP->fx_where + fixP->fx_frag->fr_address;
7451#endif
7452}
7453
7454/* Round up a section size to the appropriate boundary. */
7455
7456valueT
7457md_section_align (segment, size)
7458 segT segment ATTRIBUTE_UNUSED;
7459 valueT size;
7460{
7461#ifdef OBJ_ELF
7462 return size;
7463#else
7464 /* Round all sects to multiple of 4. */
7465 return (size + 3) & ~3;
7466#endif
7467}
7468
7469/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
7470 Otherwise we have no need to default values of symbols. */
7471
7472symbolS *
7473md_undefined_symbol (name)
7474 char * name ATTRIBUTE_UNUSED;
7475{
7476#ifdef OBJ_ELF
7477 if (name[0] == '_' && name[1] == 'G'
7478 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
7479 {
7480 if (!GOT_symbol)
7481 {
7482 if (symbol_find (name))
7483 as_bad ("GOT already in the symbol table");
7484
7485 GOT_symbol = symbol_new (name, undefined_section,
7486 (valueT) 0, & zero_address_frag);
7487 }
7488
7489 return GOT_symbol;
7490 }
7491#endif
7492
7493 return 0;
7494}
7495
7496/* arm_reg_parse () := if it looks like a register, return its token and
7497 advance the pointer. */
7498
7499static int
7500arm_reg_parse (ccp)
7501 register char ** ccp;
7502{
7503 char * start = * ccp;
7504 char c;
7505 char * p;
7506 struct reg_entry * reg;
7507
7508#ifdef REGISTER_PREFIX
7509 if (*start != REGISTER_PREFIX)
7510 return FAIL;
7511 p = start + 1;
7512#else
7513 p = start;
7514#ifdef OPTIONAL_REGISTER_PREFIX
7515 if (*p == OPTIONAL_REGISTER_PREFIX)
7516 p++, start++;
7517#endif
7518#endif
3882b010 7519 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
7520 return FAIL;
7521
7522 c = *p++;
3882b010 7523 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
7524 c = *p++;
7525
7526 *--p = 0;
7527 reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
7528 *p = c;
7529
7530 if (reg)
7531 {
7532 *ccp = p;
7533 return reg->number;
7534 }
7535
7536 return FAIL;
7537}
7538
7539int
7540md_apply_fix3 (fixP, val, seg)
7541 fixS * fixP;
7542 valueT * val;
7543 segT seg;
7544{
7545 offsetT value = * val;
7546 offsetT newval;
7547 unsigned int newimm;
7548 unsigned long temp;
7549 int sign;
7550 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
7551 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
7552
7553 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
7554
7555 /* Note whether this will delete the relocation. */
7556#if 0
7557 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
7558 doesn't work fully.) */
7559 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
7560 && !fixP->fx_pcrel)
7561#else
7562 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
7563#endif
7564 fixP->fx_done = 1;
7565
7566 /* If this symbol is in a different section then we need to leave it for
7567 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
7568 so we have to undo it's effects here. */
7569 if (fixP->fx_pcrel)
7570 {
7571 if (fixP->fx_addsy != NULL
7572 && S_IS_DEFINED (fixP->fx_addsy)
7573 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7574 {
7575 if (target_oabi
7576 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
7577 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
7578 ))
7579 value = 0;
7580 else
7581 value += md_pcrel_from (fixP);
7582 }
7583 }
7584
7585 /* Remember value for emit_reloc. */
7586 fixP->fx_addnumber = value;
7587
7588 switch (fixP->fx_r_type)
7589 {
7590 case BFD_RELOC_ARM_IMMEDIATE:
7591 newimm = validate_immediate (value);
7592 temp = md_chars_to_number (buf, INSN_SIZE);
7593
7594 /* If the instruction will fail, see if we can fix things up by
7595 changing the opcode. */
7596 if (newimm == (unsigned int) FAIL
7597 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
7598 {
7599 as_bad_where (fixP->fx_file, fixP->fx_line,
7600 _("invalid constant (%lx) after fixup"),
7601 (unsigned long) value);
7602 break;
7603 }
7604
7605 newimm |= (temp & 0xfffff000);
7606 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
7607 break;
7608
7609 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
7610 {
7611 unsigned int highpart = 0;
7612 unsigned int newinsn = 0xe1a00000; /* nop. */
7613 newimm = validate_immediate (value);
7614 temp = md_chars_to_number (buf, INSN_SIZE);
7615
7616 /* If the instruction will fail, see if we can fix things up by
7617 changing the opcode. */
7618 if (newimm == (unsigned int) FAIL
7619 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
7620 {
7621 /* No ? OK - try using two ADD instructions to generate
7622 the value. */
7623 newimm = validate_immediate_twopart (value, & highpart);
7624
7625 /* Yes - then make sure that the second instruction is
7626 also an add. */
7627 if (newimm != (unsigned int) FAIL)
7628 newinsn = temp;
7629 /* Still No ? Try using a negated value. */
7630 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
7631 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
7632 /* Otherwise - give up. */
7633 else
7634 {
7635 as_bad_where (fixP->fx_file, fixP->fx_line,
7636 _("Unable to compute ADRL instructions for PC offset of 0x%lx"),
7637 value);
7638 break;
7639 }
7640
7641 /* Replace the first operand in the 2nd instruction (which
7642 is the PC) with the destination register. We have
7643 already added in the PC in the first instruction and we
7644 do not want to do it again. */
7645 newinsn &= ~ 0xf0000;
7646 newinsn |= ((newinsn & 0x0f000) << 4);
7647 }
7648
7649 newimm |= (temp & 0xfffff000);
7650 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
7651
7652 highpart |= (newinsn & 0xfffff000);
7653 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
7654 }
7655 break;
7656
7657 case BFD_RELOC_ARM_OFFSET_IMM:
7658 sign = value >= 0;
7659
7660 if (value < 0)
7661 value = - value;
7662
7663 if (validate_offset_imm (value, 0) == FAIL)
7664 {
7665 as_bad_where (fixP->fx_file, fixP->fx_line,
7666 _("bad immediate value for offset (%ld)"),
7667 (long) value);
7668 break;
7669 }
7670
7671 newval = md_chars_to_number (buf, INSN_SIZE);
7672 newval &= 0xff7ff000;
7673 newval |= value | (sign ? INDEX_UP : 0);
7674 md_number_to_chars (buf, newval, INSN_SIZE);
7675 break;
7676
7677 case BFD_RELOC_ARM_OFFSET_IMM8:
7678 case BFD_RELOC_ARM_HWLITERAL:
7679 sign = value >= 0;
7680
7681 if (value < 0)
7682 value = - value;
7683
7684 if (validate_offset_imm (value, 1) == FAIL)
7685 {
7686 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
7687 as_bad_where (fixP->fx_file, fixP->fx_line,
7688 _("invalid literal constant: pool needs to be closer"));
7689 else
7690 as_bad (_("bad immediate value for half-word offset (%ld)"),
7691 (long) value);
7692 break;
7693 }
7694
7695 newval = md_chars_to_number (buf, INSN_SIZE);
7696 newval &= 0xff7ff0f0;
7697 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
7698 md_number_to_chars (buf, newval, INSN_SIZE);
7699 break;
7700
7701 case BFD_RELOC_ARM_LITERAL:
7702 sign = value >= 0;
7703
7704 if (value < 0)
7705 value = - value;
7706
7707 if (validate_offset_imm (value, 0) == FAIL)
7708 {
7709 as_bad_where (fixP->fx_file, fixP->fx_line,
7710 _("invalid literal constant: pool needs to be closer"));
7711 break;
7712 }
7713
7714 newval = md_chars_to_number (buf, INSN_SIZE);
7715 newval &= 0xff7ff000;
7716 newval |= value | (sign ? INDEX_UP : 0);
7717 md_number_to_chars (buf, newval, INSN_SIZE);
7718 break;
7719
7720 case BFD_RELOC_ARM_SHIFT_IMM:
7721 newval = md_chars_to_number (buf, INSN_SIZE);
7722 if (((unsigned long) value) > 32
7723 || (value == 32
7724 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
7725 {
7726 as_bad_where (fixP->fx_file, fixP->fx_line,
7727 _("shift expression is too large"));
7728 break;
7729 }
7730
7731 if (value == 0)
7732 /* Shifts of zero must be done as lsl. */
7733 newval &= ~0x60;
7734 else if (value == 32)
7735 value = 0;
7736 newval &= 0xfffff07f;
7737 newval |= (value & 0x1f) << 7;
7738 md_number_to_chars (buf, newval, INSN_SIZE);
7739 break;
7740
7741 case BFD_RELOC_ARM_SWI:
7742 if (arm_data->thumb_mode)
7743 {
7744 if (((unsigned long) value) > 0xff)
7745 as_bad_where (fixP->fx_file, fixP->fx_line,
7746 _("Invalid swi expression"));
7747 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
7748 newval |= value;
7749 md_number_to_chars (buf, newval, THUMB_SIZE);
7750 }
7751 else
7752 {
7753 if (((unsigned long) value) > 0x00ffffff)
7754 as_bad_where (fixP->fx_file, fixP->fx_line,
7755 _("Invalid swi expression"));
7756 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
7757 newval |= value;
7758 md_number_to_chars (buf, newval, INSN_SIZE);
7759 }
7760 break;
7761
7762 case BFD_RELOC_ARM_MULTI:
7763 if (((unsigned long) value) > 0xffff)
7764 as_bad_where (fixP->fx_file, fixP->fx_line,
7765 _("Invalid expression in load/store multiple"));
7766 newval = value | md_chars_to_number (buf, INSN_SIZE);
7767 md_number_to_chars (buf, newval, INSN_SIZE);
7768 break;
7769
7770 case BFD_RELOC_ARM_PCREL_BRANCH:
7771 newval = md_chars_to_number (buf, INSN_SIZE);
7772
7773 /* Sign-extend a 24-bit number. */
7774#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
7775
7776#ifdef OBJ_ELF
7777 if (! target_oabi)
7778 value = fixP->fx_offset;
7779#endif
7780
7781 /* We are going to store value (shifted right by two) in the
7782 instruction, in a 24 bit, signed field. Thus we need to check
7783 that none of the top 8 bits of the shifted value (top 7 bits of
7784 the unshifted, unsigned value) are set, or that they are all set. */
7785 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
7786 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
7787 {
7788#ifdef OBJ_ELF
7789 /* Normally we would be stuck at this point, since we cannot store
7790 the absolute address that is the destination of the branch in the
7791 24 bits of the branch instruction. If however, we happen to know
7792 that the destination of the branch is in the same section as the
7793 branch instruciton itself, then we can compute the relocation for
7794 ourselves and not have to bother the linker with it.
7795
7796 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
7797 because I have not worked out how to do this for OBJ_COFF or
7798 target_oabi. */
7799 if (! target_oabi
7800 && fixP->fx_addsy != NULL
7801 && S_IS_DEFINED (fixP->fx_addsy)
7802 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
7803 {
7804 /* Get pc relative value to go into the branch. */
7805 value = * val;
7806
7807 /* Permit a backward branch provided that enough bits
7808 are set. Allow a forwards branch, provided that
7809 enough bits are clear. */
7810 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
7811 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
7812 fixP->fx_done = 1;
7813 }
7814
7815 if (! fixP->fx_done)
7816#endif
7817 as_bad_where (fixP->fx_file, fixP->fx_line,
7818 _("gas can't handle same-section branch dest >= 0x04000000"));
7819 }
7820
7821 value >>= 2;
7822 value += SEXT24 (newval);
7823
7824 if ( (value & ~ ((offsetT) 0xffffff)) != 0
7825 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
7826 as_bad_where (fixP->fx_file, fixP->fx_line,
7827 _("out of range branch"));
7828
7829 newval = (value & 0x00ffffff) | (newval & 0xff000000);
7830 md_number_to_chars (buf, newval, INSN_SIZE);
7831 break;
7832
7833 case BFD_RELOC_ARM_PCREL_BLX:
7834 {
7835 offsetT hbit;
7836 newval = md_chars_to_number (buf, INSN_SIZE);
7837
7838#ifdef OBJ_ELF
7839 if (! target_oabi)
7840 value = fixP->fx_offset;
7841#endif
7842 hbit = (value >> 1) & 1;
7843 value = (value >> 2) & 0x00ffffff;
7844 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
7845 newval = value | (newval & 0xfe000000) | (hbit << 24);
7846 md_number_to_chars (buf, newval, INSN_SIZE);
7847 }
7848 break;
7849
7850 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
7851 newval = md_chars_to_number (buf, THUMB_SIZE);
7852 {
7853 addressT diff = (newval & 0xff) << 1;
7854 if (diff & 0x100)
7855 diff |= ~0xff;
7856
7857 value += diff;
7858 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
7859 as_bad_where (fixP->fx_file, fixP->fx_line,
7860 _("Branch out of range"));
7861 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
7862 }
7863 md_number_to_chars (buf, newval, THUMB_SIZE);
7864 break;
7865
7866 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
7867 newval = md_chars_to_number (buf, THUMB_SIZE);
7868 {
7869 addressT diff = (newval & 0x7ff) << 1;
7870 if (diff & 0x800)
7871 diff |= ~0x7ff;
7872
7873 value += diff;
7874 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
7875 as_bad_where (fixP->fx_file, fixP->fx_line,
7876 _("Branch out of range"));
7877 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
7878 }
7879 md_number_to_chars (buf, newval, THUMB_SIZE);
7880 break;
7881
7882 case BFD_RELOC_THUMB_PCREL_BLX:
7883 case BFD_RELOC_THUMB_PCREL_BRANCH23:
7884 {
7885 offsetT newval2;
7886 addressT diff;
7887
7888 newval = md_chars_to_number (buf, THUMB_SIZE);
7889 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
7890 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
7891 if (diff & 0x400000)
7892 diff |= ~0x3fffff;
7893#ifdef OBJ_ELF
7894 value = fixP->fx_offset;
7895#endif
7896 value += diff;
7897 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
7898 as_bad_where (fixP->fx_file, fixP->fx_line,
7899 _("Branch with link out of range"));
7900
7901 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
7902 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
7903 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
7904 /* Remove bit zero of the adjusted offset. Bit zero can only be
7905 set if the upper insn is at a half-word boundary, since the
7906 destination address, an ARM instruction, must always be on a
7907 word boundary. The semantics of the BLX (1) instruction, however,
7908 are that bit zero in the offset must always be zero, and the
7909 corresponding bit one in the target address will be set from bit
7910 one of the source address. */
7911 newval2 &= ~1;
7912 md_number_to_chars (buf, newval, THUMB_SIZE);
7913 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
7914 }
7915 break;
7916
7917 case BFD_RELOC_8:
7918 if (fixP->fx_done || fixP->fx_pcrel)
7919 md_number_to_chars (buf, value, 1);
7920#ifdef OBJ_ELF
7921 else if (!target_oabi)
7922 {
7923 value = fixP->fx_offset;
7924 md_number_to_chars (buf, value, 1);
7925 }
7926#endif
7927 break;
7928
7929 case BFD_RELOC_16:
7930 if (fixP->fx_done || fixP->fx_pcrel)
7931 md_number_to_chars (buf, value, 2);
7932#ifdef OBJ_ELF
7933 else if (!target_oabi)
7934 {
7935 value = fixP->fx_offset;
7936 md_number_to_chars (buf, value, 2);
7937 }
7938#endif
7939 break;
7940
7941#ifdef OBJ_ELF
7942 case BFD_RELOC_ARM_GOT32:
7943 case BFD_RELOC_ARM_GOTOFF:
7944 md_number_to_chars (buf, 0, 4);
7945 break;
7946#endif
7947
7948 case BFD_RELOC_RVA:
7949 case BFD_RELOC_32:
7950 if (fixP->fx_done || fixP->fx_pcrel)
7951 md_number_to_chars (buf, value, 4);
7952#ifdef OBJ_ELF
7953 else if (!target_oabi)
7954 {
7955 value = fixP->fx_offset;
7956 md_number_to_chars (buf, value, 4);
7957 }
7958#endif
7959 break;
7960
7961#ifdef OBJ_ELF
7962 case BFD_RELOC_ARM_PLT32:
7963 /* It appears the instruction is fully prepared at this point. */
7964 break;
7965#endif
7966
7967 case BFD_RELOC_ARM_GOTPC:
7968 md_number_to_chars (buf, value, 4);
7969 break;
7970
7971 case BFD_RELOC_ARM_CP_OFF_IMM:
7972 sign = value >= 0;
7973 if (value < -1023 || value > 1023 || (value & 3))
7974 as_bad_where (fixP->fx_file, fixP->fx_line,
7975 _("Illegal value for co-processor offset"));
7976 if (value < 0)
7977 value = -value;
7978 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
7979 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
7980 md_number_to_chars (buf, newval, INSN_SIZE);
7981 break;
7982
7983 case BFD_RELOC_ARM_THUMB_OFFSET:
7984 newval = md_chars_to_number (buf, THUMB_SIZE);
7985 /* Exactly what ranges, and where the offset is inserted depends
7986 on the type of instruction, we can establish this from the
7987 top 4 bits. */
7988 switch (newval >> 12)
7989 {
7990 case 4: /* PC load. */
7991 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
7992 forced to zero for these loads, so we will need to round
7993 up the offset if the instruction address is not word
7994 aligned (since the final address produced must be, and
7995 we can only describe word-aligned immediate offsets). */
7996
7997 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
7998 as_bad_where (fixP->fx_file, fixP->fx_line,
7999 _("Invalid offset, target not word aligned (0x%08X)"),
8000 (unsigned int) (fixP->fx_frag->fr_address
8001 + fixP->fx_where + value));
8002
8003 if ((value + 2) & ~0x3fe)
8004 as_bad_where (fixP->fx_file, fixP->fx_line,
8005 _("Invalid offset, value too big (0x%08lX)"), value);
8006
8007 /* Round up, since pc will be rounded down. */
8008 newval |= (value + 2) >> 2;
8009 break;
8010
8011 case 9: /* SP load/store. */
8012 if (value & ~0x3fc)
8013 as_bad_where (fixP->fx_file, fixP->fx_line,
8014 _("Invalid offset, value too big (0x%08lX)"), value);
8015 newval |= value >> 2;
8016 break;
8017
8018 case 6: /* Word load/store. */
8019 if (value & ~0x7c)
8020 as_bad_where (fixP->fx_file, fixP->fx_line,
8021 _("Invalid offset, value too big (0x%08lX)"), value);
8022 newval |= value << 4; /* 6 - 2. */
8023 break;
8024
8025 case 7: /* Byte load/store. */
8026 if (value & ~0x1f)
8027 as_bad_where (fixP->fx_file, fixP->fx_line,
8028 _("Invalid offset, value too big (0x%08lX)"), value);
8029 newval |= value << 6;
8030 break;
8031
8032 case 8: /* Halfword load/store. */
8033 if (value & ~0x3e)
8034 as_bad_where (fixP->fx_file, fixP->fx_line,
8035 _("Invalid offset, value too big (0x%08lX)"), value);
8036 newval |= value << 5; /* 6 - 1. */
8037 break;
8038
8039 default:
8040 as_bad_where (fixP->fx_file, fixP->fx_line,
8041 "Unable to process relocation for thumb opcode: %lx",
8042 (unsigned long) newval);
8043 break;
8044 }
8045 md_number_to_chars (buf, newval, THUMB_SIZE);
8046 break;
8047
8048 case BFD_RELOC_ARM_THUMB_ADD:
8049 /* This is a complicated relocation, since we use it for all of
8050 the following immediate relocations:
8051
8052 3bit ADD/SUB
8053 8bit ADD/SUB
8054 9bit ADD/SUB SP word-aligned
8055 10bit ADD PC/SP word-aligned
8056
8057 The type of instruction being processed is encoded in the
8058 instruction field:
8059
8060 0x8000 SUB
8061 0x00F0 Rd
8062 0x000F Rs
8063 */
8064 newval = md_chars_to_number (buf, THUMB_SIZE);
8065 {
8066 int rd = (newval >> 4) & 0xf;
8067 int rs = newval & 0xf;
8068 int subtract = newval & 0x8000;
8069
8070 if (rd == REG_SP)
8071 {
8072 if (value & ~0x1fc)
8073 as_bad_where (fixP->fx_file, fixP->fx_line,
8074 _("Invalid immediate for stack address calculation"));
8075 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8076 newval |= value >> 2;
8077 }
8078 else if (rs == REG_PC || rs == REG_SP)
8079 {
8080 if (subtract ||
8081 value & ~0x3fc)
8082 as_bad_where (fixP->fx_file, fixP->fx_line,
8083 _("Invalid immediate for address calculation (value = 0x%08lX)"),
8084 (unsigned long) value);
8085 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
8086 newval |= rd << 8;
8087 newval |= value >> 2;
8088 }
8089 else if (rs == rd)
8090 {
8091 if (value & ~0xff)
8092 as_bad_where (fixP->fx_file, fixP->fx_line,
8093 _("Invalid 8bit immediate"));
8094 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8095 newval |= (rd << 8) | value;
8096 }
8097 else
8098 {
8099 if (value & ~0x7)
8100 as_bad_where (fixP->fx_file, fixP->fx_line,
8101 _("Invalid 3bit immediate"));
8102 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8103 newval |= rd | (rs << 3) | (value << 6);
8104 }
8105 }
8106 md_number_to_chars (buf, newval, THUMB_SIZE);
8107 break;
8108
8109 case BFD_RELOC_ARM_THUMB_IMM:
8110 newval = md_chars_to_number (buf, THUMB_SIZE);
8111 switch (newval >> 11)
8112 {
8113 case 0x04: /* 8bit immediate MOV. */
8114 case 0x05: /* 8bit immediate CMP. */
8115 if (value < 0 || value > 255)
8116 as_bad_where (fixP->fx_file, fixP->fx_line,
8117 _("Invalid immediate: %ld is too large"),
8118 (long) value);
8119 newval |= value;
8120 break;
8121
8122 default:
8123 abort ();
8124 }
8125 md_number_to_chars (buf, newval, THUMB_SIZE);
8126 break;
8127
8128 case BFD_RELOC_ARM_THUMB_SHIFT:
8129 /* 5bit shift value (0..31). */
8130 if (value < 0 || value > 31)
8131 as_bad_where (fixP->fx_file, fixP->fx_line,
8132 _("Illegal Thumb shift value: %ld"), (long) value);
8133 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
8134 newval |= value << 6;
8135 md_number_to_chars (buf, newval, THUMB_SIZE);
8136 break;
8137
8138 case BFD_RELOC_VTABLE_INHERIT:
8139 case BFD_RELOC_VTABLE_ENTRY:
8140 fixP->fx_done = 0;
8141 return 1;
8142
8143 case BFD_RELOC_NONE:
8144 default:
8145 as_bad_where (fixP->fx_file, fixP->fx_line,
8146 _("Bad relocation fixup type (%d)"), fixP->fx_r_type);
8147 }
8148
8149 return 1;
8150}
8151
8152/* Translate internal representation of relocation info to BFD target
8153 format. */
8154
8155arelent *
8156tc_gen_reloc (section, fixp)
8157 asection * section ATTRIBUTE_UNUSED;
8158 fixS * fixp;
8159{
8160 arelent * reloc;
8161 bfd_reloc_code_real_type code;
8162
8163 reloc = (arelent *) xmalloc (sizeof (arelent));
8164
8165 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
8166 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
8167 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
8168
8169 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
8170#ifndef OBJ_ELF
8171 if (fixp->fx_pcrel == 0)
8172 reloc->addend = fixp->fx_offset;
8173 else
8174 reloc->addend = fixp->fx_offset = reloc->address;
8175#else /* OBJ_ELF */
8176 reloc->addend = fixp->fx_offset;
8177#endif
8178
8179 switch (fixp->fx_r_type)
8180 {
8181 case BFD_RELOC_8:
8182 if (fixp->fx_pcrel)
8183 {
8184 code = BFD_RELOC_8_PCREL;
8185 break;
8186 }
8187
8188 case BFD_RELOC_16:
8189 if (fixp->fx_pcrel)
8190 {
8191 code = BFD_RELOC_16_PCREL;
8192 break;
8193 }
8194
8195 case BFD_RELOC_32:
8196 if (fixp->fx_pcrel)
8197 {
8198 code = BFD_RELOC_32_PCREL;
8199 break;
8200 }
8201
8202 case BFD_RELOC_ARM_PCREL_BRANCH:
8203 case BFD_RELOC_ARM_PCREL_BLX:
8204 case BFD_RELOC_RVA:
8205 case BFD_RELOC_THUMB_PCREL_BRANCH9:
8206 case BFD_RELOC_THUMB_PCREL_BRANCH12:
8207 case BFD_RELOC_THUMB_PCREL_BRANCH23:
8208 case BFD_RELOC_THUMB_PCREL_BLX:
8209 case BFD_RELOC_VTABLE_ENTRY:
8210 case BFD_RELOC_VTABLE_INHERIT:
8211 code = fixp->fx_r_type;
8212 break;
8213
8214 case BFD_RELOC_ARM_LITERAL:
8215 case BFD_RELOC_ARM_HWLITERAL:
8216 /* If this is called then the a literal has been referenced across
8217 a section boundary - possibly due to an implicit dump. */
8218 as_bad_where (fixp->fx_file, fixp->fx_line,
8219 _("Literal referenced across section boundary (Implicit dump?)"));
8220 return NULL;
8221
8222#ifdef OBJ_ELF
8223 case BFD_RELOC_ARM_GOT32:
8224 case BFD_RELOC_ARM_GOTOFF:
8225 case BFD_RELOC_ARM_PLT32:
8226 code = fixp->fx_r_type;
8227 break;
8228#endif
8229
8230 case BFD_RELOC_ARM_IMMEDIATE:
8231 as_bad_where (fixp->fx_file, fixp->fx_line,
8232 _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
8233 fixp->fx_r_type);
8234 return NULL;
8235
8236 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
8237 as_bad_where (fixp->fx_file, fixp->fx_line,
8238 _("ADRL used for a symbol not defined in the same file"));
8239 return NULL;
8240
8241 case BFD_RELOC_ARM_OFFSET_IMM:
8242 as_bad_where (fixp->fx_file, fixp->fx_line,
8243 _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
8244 fixp->fx_r_type);
8245 return NULL;
8246
8247 default:
8248 {
8249 char * type;
8250
8251 switch (fixp->fx_r_type)
8252 {
8253 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
8254 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
8255 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
8256 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
8257 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
8258 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
8259 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
8260 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
8261 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
8262 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
8263 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
8264 default: type = _("<unknown>"); break;
8265 }
8266 as_bad_where (fixp->fx_file, fixp->fx_line,
8267 _("Cannot represent %s relocation in this object file format"),
8268 type);
8269 return NULL;
8270 }
8271 }
8272
8273#ifdef OBJ_ELF
8274 if (code == BFD_RELOC_32_PCREL
8275 && GOT_symbol
8276 && fixp->fx_addsy == GOT_symbol)
8277 {
8278 code = BFD_RELOC_ARM_GOTPC;
8279 reloc->addend = fixp->fx_offset = reloc->address;
8280 }
8281#endif
8282
8283 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
8284
8285 if (reloc->howto == NULL)
8286 {
8287 as_bad_where (fixp->fx_file, fixp->fx_line,
8288 _("Can not represent %s relocation in this object file format"),
8289 bfd_get_reloc_code_name (code));
8290 return NULL;
8291 }
8292
8293 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
8294 vtable entry to be used in the relocation's section offset. */
8295 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
8296 reloc->address = fixp->fx_offset;
8297
8298 return reloc;
8299}
8300
8301int
8302md_estimate_size_before_relax (fragP, segtype)
8303 fragS * fragP ATTRIBUTE_UNUSED;
8304 segT segtype ATTRIBUTE_UNUSED;
8305{
8306 as_fatal (_("md_estimate_size_before_relax\n"));
8307 return 1;
8308}
8309
8310static void
8311output_inst PARAMS ((void))
8312{
8313 char * to = NULL;
8314
8315 if (inst.error)
8316 {
8317 as_bad (inst.error);
8318 return;
8319 }
8320
8321 to = frag_more (inst.size);
8322
8323 if (thumb_mode && (inst.size > THUMB_SIZE))
8324 {
8325 assert (inst.size == (2 * THUMB_SIZE));
8326 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
8327 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
8328 }
8329 else if (inst.size > INSN_SIZE)
8330 {
8331 assert (inst.size == (2 * INSN_SIZE));
8332 md_number_to_chars (to, inst.instruction, INSN_SIZE);
8333 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
8334 }
8335 else
8336 md_number_to_chars (to, inst.instruction, inst.size);
8337
8338 if (inst.reloc.type != BFD_RELOC_NONE)
8339 fix_new_arm (frag_now, to - frag_now->fr_literal,
8340 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
8341 inst.reloc.type);
8342
8343#ifdef OBJ_ELF
8344 dwarf2_emit_insn (inst.size);
8345#endif
8346}
8347
8348void
8349md_assemble (str)
8350 char * str;
8351{
8352 char c;
8353 char * p;
8354 char * q;
8355 char * start;
8356
8357 /* Align the instruction.
8358 This may not be the right thing to do but ... */
8359#if 0
8360 arm_align (2, 0);
8361#endif
8362 listing_prev_line (); /* Defined in listing.h. */
8363
8364 /* Align the previous label if needed. */
8365 if (last_label_seen != NULL)
8366 {
8367 symbol_set_frag (last_label_seen, frag_now);
8368 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
8369 S_SET_SEGMENT (last_label_seen, now_seg);
8370 }
8371
8372 memset (&inst, '\0', sizeof (inst));
8373 inst.reloc.type = BFD_RELOC_NONE;
8374
8375 skip_whitespace (str);
8376
8377 /* Scan up to the end of the op-code, which must end in white space or
8378 end of string. */
8379 for (start = p = str; *p != '\0'; p++)
8380 if (*p == ' ')
8381 break;
8382
8383 if (p == str)
8384 {
8385 as_bad (_("No operator -- statement `%s'\n"), str);
8386 return;
8387 }
8388
8389 if (thumb_mode)
8390 {
8391 CONST struct thumb_opcode * opcode;
8392
8393 c = *p;
8394 *p = '\0';
8395 opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
8396 *p = c;
8397
8398 if (opcode)
8399 {
8400 /* Check that this instruction is supported for this CPU. */
8401 if (thumb_mode == 1 && (opcode->variants & cpu_variant) == 0)
8402 {
8403 as_bad (_("selected processor does not support this opcode"));
8404 return;
8405 }
8406
8407 inst.instruction = opcode->value;
8408 inst.size = opcode->size;
8409 (*opcode->parms) (p);
8410 output_inst ();
8411 return;
8412 }
8413 }
8414 else
8415 {
8416 CONST struct asm_opcode * opcode;
8417 unsigned long cond_code;
8418
8419 inst.size = INSN_SIZE;
8420 /* P now points to the end of the opcode, probably white space, but we
8421 have to break the opcode up in case it contains condionals and flags;
8422 keep trying with progressively smaller basic instructions until one
8423 matches, or we run out of opcode. */
8424 q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
8425
8426 for (; q != str; q--)
8427 {
8428 c = *q;
8429 *q = '\0';
8430
8431 opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
8432 *q = c;
8433
8434 if (opcode && opcode->template)
8435 {
8436 unsigned long flag_bits = 0;
8437 char * r;
8438
8439 /* Check that this instruction is supported for this CPU. */
8440 if ((opcode->variants & cpu_variant) == 0)
8441 goto try_shorter;
8442
8443 inst.instruction = opcode->value;
8444 if (q == p) /* Just a simple opcode. */
8445 {
8446 if (opcode->comp_suffix)
8447 {
8448 if (*opcode->comp_suffix != '\0')
8449 as_bad (_("Opcode `%s' must have suffix from list: <%s>"),
8450 str, opcode->comp_suffix);
8451 else
8452 /* Not a conditional instruction. */
8453 (*opcode->parms) (q, 0);
8454 }
8455 else
8456 {
8457 /* A conditional instruction with default condition. */
8458 inst.instruction |= COND_ALWAYS;
8459 (*opcode->parms) (q, 0);
8460 }
8461 output_inst ();
8462 return;
8463 }
8464
8465 /* Not just a simple opcode. Check if extra is a
8466 conditional. */
8467 r = q;
8468 if (p - r >= 2)
8469 {
8470 CONST struct asm_cond *cond;
8471 char d = *(r + 2);
8472
8473 *(r + 2) = '\0';
8474 cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
8475 *(r + 2) = d;
8476 if (cond)
8477 {
8478 if (cond->value == 0xf0000000)
8479 as_tsktsk (
8480_("Warning: Use of the 'nv' conditional is deprecated\n"));
8481
8482 cond_code = cond->value;
8483 r += 2;
8484 }
8485 else
8486 cond_code = COND_ALWAYS;
8487 }
8488 else
8489 cond_code = COND_ALWAYS;
8490
8491 /* Apply the conditional, or complain it's not allowed. */
8492 if (opcode->comp_suffix && *opcode->comp_suffix == '\0')
8493 {
8494 /* Instruction isn't conditional. */
8495 if (cond_code != COND_ALWAYS)
8496 {
8497 as_bad (_("Opcode `%s' is unconditional\n"), str);
8498 return;
8499 }
8500 }
8501 else
8502 /* Instruction is conditional: set the condition into it. */
8503 inst.instruction |= cond_code;
8504
8505 /* If there is a compulsory suffix, it should come here
8506 before any optional flags. */
8507 if (opcode->comp_suffix && *opcode->comp_suffix != '\0')
8508 {
8509 CONST char *s = opcode->comp_suffix;
8510
8511 while (*s)
8512 {
8513 inst.suffix++;
8514 if (*r == *s)
8515 break;
8516 s++;
8517 }
8518
8519 if (*s == '\0')
8520 {
8521 as_bad (_("Opcode `%s' must have suffix from <%s>\n"),
8522 str, opcode->comp_suffix);
8523 return;
8524 }
8525
8526 r++;
8527 }
8528
8529 /* The remainder, if any should now be flags for the instruction;
8530 Scan these checking each one found with the opcode. */
8531 if (r != p)
8532 {
8533 char d;
8534 CONST struct asm_flg *flag = opcode->flags;
8535
8536 if (flag)
8537 {
8538 int flagno;
8539
8540 d = *p;
8541 *p = '\0';
8542
8543 for (flagno = 0; flag[flagno].template; flagno++)
8544 {
8545 if (streq (r, flag[flagno].template))
8546 {
8547 flag_bits |= flag[flagno].set_bits;
8548 break;
8549 }
8550 }
8551
8552 *p = d;
8553 if (! flag[flagno].template)
8554 goto try_shorter;
8555 }
8556 else
8557 goto try_shorter;
8558 }
8559
8560 (*opcode->parms) (p, flag_bits);
8561 output_inst ();
8562 return;
8563 }
8564
8565 try_shorter:
8566 ;
8567 }
8568 }
8569
8570 /* It wasn't an instruction, but it might be a register alias of the form
8571 alias .req reg. */
8572 q = p;
8573 skip_whitespace (q);
8574
8575 c = *p;
8576 *p = '\0';
8577
8578 if (*q && !strncmp (q, ".req ", 4))
8579 {
8580 int reg;
8581 char * copy_of_str;
8582 char * r;
8583
8584#ifdef IGNORE_OPCODE_CASE
8585 str = original_case_string;
8586#endif
8587 copy_of_str = str;
8588
8589 q += 4;
8590 skip_whitespace (q);
8591
8592 for (r = q; *r != '\0'; r++)
8593 if (*r == ' ')
8594 break;
8595
8596 if (r != q)
8597 {
8598 int regnum;
8599 char d = *r;
8600
8601 *r = '\0';
8602 regnum = arm_reg_parse (& q);
8603 *r = d;
8604
8605 reg = arm_reg_parse (& str);
8606
8607 if (reg == FAIL)
8608 {
8609 if (regnum != FAIL)
8610 insert_reg_alias (str, regnum);
8611 else
8612 as_warn (_("register '%s' does not exist\n"), q);
8613 }
8614 else if (regnum != FAIL)
8615 {
8616 if (reg != regnum)
8617 as_warn (_("ignoring redefinition of register alias '%s'"),
8618 copy_of_str);
8619
8620 /* Do not warn about redefinitions to the same alias. */
8621 }
8622 else
8623 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
8624 copy_of_str, q);
8625 }
8626 else
8627 as_warn (_("ignoring incomplete .req pseuso op"));
8628
8629 *p = c;
8630 return;
8631 }
8632
8633 *p = c;
8634 as_bad (_("bad instruction `%s'"), start);
8635}
8636
8637/* md_parse_option
8638 Invocation line includes a switch not recognized by the base assembler.
8639 See if it's a processor-specific option. These are:
8640 Cpu variants, the arm part is optional:
8641 -m[arm]1 Currently not supported.
8642 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
8643 -m[arm]3 Arm 3 processor
8644 -m[arm]6[xx], Arm 6 processors
8645 -m[arm]7[xx][t][[d]m] Arm 7 processors
8646 -m[arm]8[10] Arm 8 processors
8647 -m[arm]9[20][tdmi] Arm 9 processors
404ff6b5 8648 -marm9e Allow Cirrus/DSP instructions
b99bd4ef
NC
8649 -mstrongarm[110[0]] StrongARM processors
8650 -mxscale XScale processors
8651 -m[arm]v[2345[t[e]]] Arm architectures
8652 -mall All (except the ARM1)
8653 FP variants:
8654 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
8655 -mfpe-old (No float load/store multiples)
8656 -mno-fpu Disable all floating point instructions
8657 Run-time endian selection:
8658 -EB big endian cpu
8659 -EL little endian cpu
8660 ARM Procedure Calling Standard:
8661 -mapcs-32 32 bit APCS
8662 -mapcs-26 26 bit APCS
8663 -mapcs-float Pass floats in float regs
8664 -mapcs-reentrant Position independent code
8665 -mthumb-interwork Code supports Arm/Thumb interworking
8666 -matpcs ARM/Thumb Procedure Call Standard
8667 -moabi Old ELF ABI */
8668
8669CONST char * md_shortopts = "m:k";
8670
8671struct option md_longopts[] =
8672{
8673#ifdef ARM_BI_ENDIAN
8674#define OPTION_EB (OPTION_MD_BASE + 0)
8675 {"EB", no_argument, NULL, OPTION_EB},
8676#define OPTION_EL (OPTION_MD_BASE + 1)
8677 {"EL", no_argument, NULL, OPTION_EL},
8678#ifdef OBJ_ELF
8679#define OPTION_OABI (OPTION_MD_BASE +2)
8680 {"oabi", no_argument, NULL, OPTION_OABI},
8681#endif
8682#endif
8683 {NULL, no_argument, NULL, 0}
8684};
8685
8686size_t md_longopts_size = sizeof (md_longopts);
8687
8688int
8689md_parse_option (c, arg)
8690 int c;
8691 char * arg;
8692{
8693 char * str = arg;
8694
8695 switch (c)
8696 {
8697#ifdef ARM_BI_ENDIAN
8698 case OPTION_EB:
8699 target_big_endian = 1;
8700 break;
8701 case OPTION_EL:
8702 target_big_endian = 0;
8703 break;
8704#endif
8705
8706 case 'm':
8707 switch (*str)
8708 {
8709 case 'f':
8710 if (streq (str, "fpa10"))
8711 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10;
8712 else if (streq (str, "fpa11"))
8713 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11;
8714 else if (streq (str, "fpe-old"))
8715 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE;
8716 else
8717 goto bad;
8718 break;
8719
8720 case 'n':
8721 if (streq (str, "no-fpu"))
8722 cpu_variant &= ~FPU_ALL;
8723 break;
8724
8725#ifdef OBJ_ELF
8726 case 'o':
8727 if (streq (str, "oabi"))
8728 target_oabi = true;
8729 break;
8730#endif
8731
8732 case 't':
8733 /* Limit assembler to generating only Thumb instructions: */
8734 if (streq (str, "thumb"))
8735 {
8736 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_EXT_THUMB;
8737 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
8738 thumb_mode = 1;
8739 }
8740 else if (streq (str, "thumb-interwork"))
8741 {
8742 if ((cpu_variant & ARM_EXT_THUMB) == 0)
8743 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T;
8744#if defined OBJ_COFF || defined OBJ_ELF
8745 support_interwork = true;
8746#endif
8747 }
8748 else
8749 goto bad;
8750 break;
8751
8752 default:
8753 if (streq (str, "all"))
8754 {
8755 cpu_variant = ARM_ALL | FPU_ALL;
8756 return 1;
8757 }
8758#if defined OBJ_COFF || defined OBJ_ELF
8759 if (! strncmp (str, "apcs-", 5))
8760 {
8761 /* GCC passes on all command line options starting "-mapcs-..."
8762 to us, so we must parse them here. */
8763
8764 str += 5;
8765
8766 if (streq (str, "32"))
8767 {
8768 uses_apcs_26 = false;
8769 return 1;
8770 }
8771 else if (streq (str, "26"))
8772 {
8773 uses_apcs_26 = true;
8774 return 1;
8775 }
8776 else if (streq (str, "frame"))
8777 {
8778 /* Stack frames are being generated - does not affect
8779 linkage of code. */
8780 return 1;
8781 }
8782 else if (streq (str, "stack-check"))
8783 {
8784 /* Stack checking is being performed - does not affect
8785 linkage, but does require that the functions
8786 __rt_stkovf_split_small and __rt_stkovf_split_big be
8787 present in the final link. */
8788
8789 return 1;
8790 }
8791 else if (streq (str, "float"))
8792 {
8793 /* Floating point arguments are being passed in the floating
8794 point registers. This does affect linking, since this
8795 version of the APCS is incompatible with the version that
8796 passes floating points in the integer registers. */
8797
8798 uses_apcs_float = true;
8799 return 1;
8800 }
8801 else if (streq (str, "reentrant"))
8802 {
8803 /* Reentrant code has been generated. This does affect
8804 linking, since there is no point in linking reentrant/
8805 position independent code with absolute position code. */
8806 pic_code = true;
8807 return 1;
8808 }
8809
8810 as_bad (_("Unrecognised APCS switch -m%s"), arg);
8811 return 0;
8812 }
8813
8814 if (! strcmp (str, "atpcs"))
8815 {
8816 atpcs = true;
8817 return 1;
8818 }
8819#endif
8820 /* Strip off optional "arm". */
8821 if (! strncmp (str, "arm", 3))
8822 str += 3;
8823
8824 switch (*str)
8825 {
8826 case '1':
8827 if (streq (str, "1"))
8828 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
8829 else
8830 goto bad;
8831 break;
8832
8833 case '2':
8834 if (streq (str, "2"))
8835 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
8836 else if (streq (str, "250"))
8837 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
8838 else
8839 goto bad;
8840 break;
8841
8842 case '3':
8843 if (streq (str, "3"))
8844 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
8845 else
8846 goto bad;
8847 break;
8848
8849 case '6':
8850 switch (strtol (str, NULL, 10))
8851 {
8852 case 6:
8853 case 60:
8854 case 600:
8855 case 610:
8856 case 620:
8857 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
8858 break;
8859 default:
8860 goto bad;
8861 }
8862 break;
8863
8864 case '7':
8865 /* Eat the processor name. */
8866 switch (strtol (str, & str, 10))
8867 {
8868 case 7:
8869 case 70:
8870 case 700:
8871 case 710:
8872 case 720:
8873 case 7100:
8874 case 7500:
8875 break;
8876 default:
8877 goto bad;
8878 }
8879 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
8880 for (; *str; str++)
8881 {
8882 switch (*str)
8883 {
8884 case 't':
8885 cpu_variant |= ARM_ARCH_V4T;
8886 break;
8887
8888 case 'm':
8889 cpu_variant |= ARM_EXT_LONGMUL;
8890 break;
8891
8892 case 'f': /* fe => fp enabled cpu. */
8893 if (str[1] == 'e')
8894 ++ str;
8895 else
8896 goto bad;
8897
8898 case 'c': /* Left over from 710c processor name. */
8899 case 'd': /* Debug. */
8900 case 'i': /* Embedded ICE. */
8901 /* Included for completeness in ARM processor naming. */
8902 break;
8903
8904 default:
8905 goto bad;
8906 }
8907 }
8908 break;
8909
8910 case '8':
8911 if (streq (str, "8") || streq (str, "810"))
8912 cpu_variant = (cpu_variant & ~ARM_ANY)
8913 | ARM_8 | ARM_ARCH_V4;
8914 else
8915 goto bad;
8916 break;
8917
8918 case '9':
8919 if (streq (str, "9"))
8920 cpu_variant = (cpu_variant & ~ARM_ANY)
8921 | ARM_9 | ARM_ARCH_V4T;
8922 else if (streq (str, "920"))
8923 cpu_variant = (cpu_variant & ~ARM_ANY)
8924 | ARM_9 | ARM_ARCH_V4;
8925 else if (streq (str, "920t"))
8926 cpu_variant = (cpu_variant & ~ARM_ANY)
8927 | ARM_9 | ARM_ARCH_V4T;
8928 else if (streq (str, "9tdmi"))
8929 cpu_variant = (cpu_variant & ~ARM_ANY)
8930 | ARM_9 | ARM_ARCH_V4T;
404ff6b5
AH
8931 else if (streq (str, "9e"))
8932 cpu_variant = (cpu_variant & ~ARM_ANY)
90f9b791 8933 | ARM_9 | ARM_ARCH_V4T | ARM_EXT_MAVERICK;
b99bd4ef
NC
8934 else
8935 goto bad;
8936 break;
8937
8938 case 's':
8939 if (streq (str, "strongarm")
8940 || streq (str, "strongarm110")
8941 || streq (str, "strongarm1100"))
8942 cpu_variant = (cpu_variant & ~ARM_ANY)
8943 | ARM_8 | ARM_ARCH_V4;
8944 else
8945 goto bad;
8946 break;
8947
8948 case 'x':
8949 if (streq (str, "xscale"))
8950 cpu_variant = ARM_9 | ARM_ARCH_XSCALE;
8951 else
8952 goto bad;
8953 break;
8954
8955 case 'v':
8956 /* Select variant based on architecture rather than
8957 processor. */
8958 switch (*++str)
8959 {
8960 case '2':
8961 switch (*++str)
8962 {
8963 case 'a':
8964 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
8965 break;
8966 case 0:
8967 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
8968 break;
8969 default:
8970 as_bad (_("Invalid architecture variant -m%s"), arg);
8971 break;
8972 }
8973 break;
8974
8975 case '3':
8976 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
8977
8978 switch (*++str)
8979 {
8980 case 'm': cpu_variant |= ARM_EXT_LONGMUL; break;
8981 case 0: break;
8982 default:
8983 as_bad (_("Invalid architecture variant -m%s"), arg);
8984 break;
8985 }
8986 break;
8987
8988 case '4':
8989 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCH_V4;
8990
8991 switch (*++str)
8992 {
8993 case 't': cpu_variant |= ARM_EXT_THUMB; break;
8994 case 0: break;
8995 default:
8996 as_bad (_("Invalid architecture variant -m%s"), arg);
8997 break;
8998 }
8999 break;
9000
9001 case '5':
9002 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V5;
9003 switch (*++str)
9004 {
9005 case 't': cpu_variant |= ARM_EXT_THUMB; break;
9006 case 'e': cpu_variant |= ARM_EXT_V5E; break;
9007 case 0: break;
9008 default:
9009 as_bad (_("Invalid architecture variant -m%s"), arg);
9010 break;
9011 }
9012 break;
9013
9014 default:
9015 as_bad (_("Invalid architecture variant -m%s"), arg);
9016 break;
9017 }
9018 break;
9019
9020 default:
9021 bad:
9022 as_bad (_("Invalid processor variant -m%s"), arg);
9023 return 0;
9024 }
9025 }
9026 break;
9027
9028#if defined OBJ_ELF || defined OBJ_COFF
9029 case 'k':
9030 pic_code = 1;
9031 break;
9032#endif
9033
9034 default:
9035 return 0;
9036 }
9037
9038 return 1;
9039}
9040
9041void
9042md_show_usage (fp)
9043 FILE * fp;
9044{
9045 fprintf (fp, _("\
9046 ARM Specific Assembler Options:\n\
9047 -m[arm][<processor name>] select processor variant\n\
9048 -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
404ff6b5 9049 -marm9e allow Cirrus/DSP instructions\n\
b99bd4ef
NC
9050 -mthumb only allow Thumb instructions\n\
9051 -mthumb-interwork mark the assembled code as supporting interworking\n\
9052 -mall allow any instruction\n\
9053 -mfpa10, -mfpa11 select floating point architecture\n\
9054 -mfpe-old don't allow floating-point multiple instructions\n\
9055 -mno-fpu don't allow any floating-point instructions.\n\
9056 -k generate PIC code.\n"));
9057#if defined OBJ_COFF || defined OBJ_ELF
9058 fprintf (fp, _("\
9059 -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n\
9060 -matpcs use ARM/Thumb Procedure Calling Standard\n\
9061 -mapcs-float floating point args are passed in FP regs\n\
9062 -mapcs-reentrant the code is position independent/reentrant\n"));
9063#endif
9064#ifdef OBJ_ELF
9065 fprintf (fp, _("\
9066 -moabi support the old ELF ABI\n"));
9067#endif
9068#ifdef ARM_BI_ENDIAN
9069 fprintf (fp, _("\
9070 -EB assemble code for a big endian cpu\n\
9071 -EL assemble code for a little endian cpu\n"));
9072#endif
9073}
9074
9075/* We need to be able to fix up arbitrary expressions in some statements.
9076 This is so that we can handle symbols that are an arbitrary distance from
9077 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
9078 which returns part of an address in a form which will be valid for
9079 a data instruction. We do this by pushing the expression into a symbol
9080 in the expr_section, and creating a fix for that. */
9081
9082static void
9083fix_new_arm (frag, where, size, exp, pc_rel, reloc)
9084 fragS * frag;
9085 int where;
9086 short int size;
9087 expressionS * exp;
9088 int pc_rel;
9089 int reloc;
9090{
9091 fixS * new_fix;
9092 arm_fix_data * arm_data;
9093
9094 switch (exp->X_op)
9095 {
9096 case O_constant:
9097 case O_symbol:
9098 case O_add:
9099 case O_subtract:
9100 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
9101 break;
9102
9103 default:
9104 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
9105 pc_rel, reloc);
9106 break;
9107 }
9108
9109 /* Mark whether the fix is to a THUMB instruction, or an ARM
9110 instruction. */
9111 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
9112 new_fix->tc_fix_data = (PTR) arm_data;
9113 arm_data->thumb_mode = thumb_mode;
9114
9115 return;
9116}
9117
9118/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
9119
9120void
9121cons_fix_new_arm (frag, where, size, exp)
9122 fragS * frag;
9123 int where;
9124 int size;
9125 expressionS * exp;
9126{
9127 bfd_reloc_code_real_type type;
9128 int pcrel = 0;
9129
9130 /* Pick a reloc.
9131 FIXME: @@ Should look at CPU word size. */
9132 switch (size)
9133 {
9134 case 1:
9135 type = BFD_RELOC_8;
9136 break;
9137 case 2:
9138 type = BFD_RELOC_16;
9139 break;
9140 case 4:
9141 default:
9142 type = BFD_RELOC_32;
9143 break;
9144 case 8:
9145 type = BFD_RELOC_64;
9146 break;
9147 }
9148
9149 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
9150}
9151
9152/* A good place to do this, although this was probably not intended
9153 for this kind of use. We need to dump the literal pool before
9154 references are made to a null symbol pointer. */
9155
9156void
9157arm_cleanup ()
9158{
9159 if (current_poolP == NULL)
9160 return;
9161
9162 /* Put it at the end of text section. */
9163 subseg_set (text_section, 0);
9164 s_ltorg (0);
9165 listing_prev_line ();
9166}
9167
9168void
9169arm_start_line_hook ()
9170{
9171 last_label_seen = NULL;
9172}
9173
9174void
9175arm_frob_label (sym)
9176 symbolS * sym;
9177{
9178 last_label_seen = sym;
9179
9180 ARM_SET_THUMB (sym, thumb_mode);
9181
9182#if defined OBJ_COFF || defined OBJ_ELF
9183 ARM_SET_INTERWORK (sym, support_interwork);
9184#endif
9185
9186 /* Note - do not allow local symbols (.Lxxx) to be labeled
9187 as Thumb functions. This is because these labels, whilst
9188 they exist inside Thumb code, are not the entry points for
9189 possible ARM->Thumb calls. Also, these labels can be used
9190 as part of a computed goto or switch statement. eg gcc
9191 can generate code that looks like this:
9192
9193 ldr r2, [pc, .Laaa]
9194 lsl r3, r3, #2
9195 ldr r2, [r3, r2]
9196 mov pc, r2
9197
9198 .Lbbb: .word .Lxxx
9199 .Lccc: .word .Lyyy
9200 ..etc...
9201 .Laaa: .word Lbbb
9202
9203 The first instruction loads the address of the jump table.
9204 The second instruction converts a table index into a byte offset.
9205 The third instruction gets the jump address out of the table.
9206 The fourth instruction performs the jump.
9207
9208 If the address stored at .Laaa is that of a symbol which has the
9209 Thumb_Func bit set, then the linker will arrange for this address
9210 to have the bottom bit set, which in turn would mean that the
9211 address computation performed by the third instruction would end
9212 up with the bottom bit set. Since the ARM is capable of unaligned
9213 word loads, the instruction would then load the incorrect address
9214 out of the jump table, and chaos would ensue. */
9215 if (label_is_thumb_function_name
9216 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
9217 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
9218 {
9219 /* When the address of a Thumb function is taken the bottom
9220 bit of that address should be set. This will allow
9221 interworking between Arm and Thumb functions to work
9222 correctly. */
9223
9224 THUMB_SET_FUNC (sym, 1);
9225
9226 label_is_thumb_function_name = false;
9227 }
9228}
9229
9230/* Adjust the symbol table. This marks Thumb symbols as distinct from
9231 ARM ones. */
9232
9233void
9234arm_adjust_symtab ()
9235{
9236#ifdef OBJ_COFF
9237 symbolS * sym;
9238
9239 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9240 {
9241 if (ARM_IS_THUMB (sym))
9242 {
9243 if (THUMB_IS_FUNC (sym))
9244 {
9245 /* Mark the symbol as a Thumb function. */
9246 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
9247 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
9248 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
9249
9250 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
9251 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
9252 else
9253 as_bad (_("%s: unexpected function type: %d"),
9254 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
9255 }
9256 else switch (S_GET_STORAGE_CLASS (sym))
9257 {
9258 case C_EXT:
9259 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
9260 break;
9261 case C_STAT:
9262 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
9263 break;
9264 case C_LABEL:
9265 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
9266 break;
9267 default:
9268 /* Do nothing. */
9269 break;
9270 }
9271 }
9272
9273 if (ARM_IS_INTERWORK (sym))
9274 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
9275 }
9276#endif
9277#ifdef OBJ_ELF
9278 symbolS * sym;
9279 char bind;
9280
9281 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
9282 {
9283 if (ARM_IS_THUMB (sym))
9284 {
9285 elf_symbol_type * elf_sym;
9286
9287 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
9288 bind = ELF_ST_BIND (elf_sym);
9289
9290 /* If it's a .thumb_func, declare it as so,
9291 otherwise tag label as .code 16. */
9292 if (THUMB_IS_FUNC (sym))
9293 elf_sym->internal_elf_sym.st_info =
9294 ELF_ST_INFO (bind, STT_ARM_TFUNC);
9295 else
9296 elf_sym->internal_elf_sym.st_info =
9297 ELF_ST_INFO (bind, STT_ARM_16BIT);
9298 }
9299 }
9300#endif
9301}
9302
9303int
9304arm_data_in_code ()
9305{
9306 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
9307 {
9308 *input_line_pointer = '/';
9309 input_line_pointer += 5;
9310 *input_line_pointer = 0;
9311 return 1;
9312 }
9313
9314 return 0;
9315}
9316
9317char *
9318arm_canonicalize_symbol_name (name)
9319 char * name;
9320{
9321 int len;
9322
9323 if (thumb_mode && (len = strlen (name)) > 5
9324 && streq (name + len - 5, "/data"))
9325 *(name + len - 5) = 0;
9326
9327 return name;
9328}
9329
9330boolean
9331arm_validate_fix (fixP)
9332 fixS * fixP;
9333{
9334 /* If the destination of the branch is a defined symbol which does not have
9335 the THUMB_FUNC attribute, then we must be calling a function which has
9336 the (interfacearm) attribute. We look for the Thumb entry point to that
9337 function and change the branch to refer to that function instead. */
9338 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
9339 && fixP->fx_addsy != NULL
9340 && S_IS_DEFINED (fixP->fx_addsy)
9341 && ! THUMB_IS_FUNC (fixP->fx_addsy))
9342 {
9343 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
9344 return true;
9345 }
9346
9347 return false;
9348}
9349
9350#ifdef OBJ_COFF
9351/* This is a little hack to help the gas/arm/adrl.s test. It prevents
9352 local labels from being added to the output symbol table when they
9353 are used with the ADRL pseudo op. The ADRL relocation should always
9354 be resolved before the binbary is emitted, so it is safe to say that
9355 it is adjustable. */
9356
9357boolean
9358arm_fix_adjustable (fixP)
9359 fixS * fixP;
9360{
9361 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
9362 return 1;
9363 return 0;
9364}
9365#endif
9366#ifdef OBJ_ELF
9367/* Relocations against Thumb function names must be left unadjusted,
9368 so that the linker can use this information to correctly set the
9369 bottom bit of their addresses. The MIPS version of this function
9370 also prevents relocations that are mips-16 specific, but I do not
9371 know why it does this.
9372
9373 FIXME:
9374 There is one other problem that ought to be addressed here, but
9375 which currently is not: Taking the address of a label (rather
9376 than a function) and then later jumping to that address. Such
9377 addresses also ought to have their bottom bit set (assuming that
9378 they reside in Thumb code), but at the moment they will not. */
9379
9380boolean
9381arm_fix_adjustable (fixP)
9382 fixS * fixP;
9383{
9384 if (fixP->fx_addsy == NULL)
9385 return 1;
9386
9387 /* Prevent all adjustments to global symbols. */
9388 if (S_IS_EXTERN (fixP->fx_addsy))
9389 return 0;
9390
9391 if (S_IS_WEAK (fixP->fx_addsy))
9392 return 0;
9393
9394 if (THUMB_IS_FUNC (fixP->fx_addsy)
9395 && fixP->fx_subsy == NULL)
9396 return 0;
9397
9398 /* We need the symbol name for the VTABLE entries. */
9399 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
9400 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
9401 return 0;
9402
9403 return 1;
9404}
9405
9406const char *
9407elf32_arm_target_format ()
9408{
9409 if (target_big_endian)
9410 {
9411 if (target_oabi)
9412 return "elf32-bigarm-oabi";
9413 else
9414 return "elf32-bigarm";
9415 }
9416 else
9417 {
9418 if (target_oabi)
9419 return "elf32-littlearm-oabi";
9420 else
9421 return "elf32-littlearm";
9422 }
9423}
9424
9425void
9426armelf_frob_symbol (symp, puntp)
9427 symbolS * symp;
9428 int * puntp;
9429{
9430 elf_frob_symbol (symp, puntp);
9431}
9432
9433int
9434arm_force_relocation (fixp)
9435 struct fix * fixp;
9436{
9437 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
9438 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
9439 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
9440 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
9441 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
9442 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
9443 return 1;
9444
9445 return 0;
9446}
9447
9448static bfd_reloc_code_real_type
9449arm_parse_reloc ()
9450{
9451 char id [16];
9452 char * ip;
9453 unsigned int i;
9454 static struct
9455 {
9456 char * str;
9457 int len;
9458 bfd_reloc_code_real_type reloc;
9459 }
9460 reloc_map[] =
9461 {
9462#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
9463 MAP ("(got)", BFD_RELOC_ARM_GOT32),
9464 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
9465 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
9466 branch instructions generated by GCC for PLT relocs. */
9467 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
9468 { NULL, 0, BFD_RELOC_UNUSED }
9469#undef MAP
9470 };
9471
9472 for (i = 0, ip = input_line_pointer;
3882b010 9473 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 9474 i++, ip++)
3882b010 9475 id[i] = TOLOWER (*ip);
b99bd4ef
NC
9476
9477 for (i = 0; reloc_map[i].str; i++)
9478 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
9479 break;
9480
9481 input_line_pointer += reloc_map[i].len;
9482
9483 return reloc_map[i].reloc;
9484}
9485
9486static void
9487s_arm_elf_cons (nbytes)
9488 int nbytes;
9489{
9490 expressionS exp;
9491
9492#ifdef md_flush_pending_output
9493 md_flush_pending_output ();
9494#endif
9495
9496 if (is_it_end_of_statement ())
9497 {
9498 demand_empty_rest_of_line ();
9499 return;
9500 }
9501
9502#ifdef md_cons_align
9503 md_cons_align (nbytes);
9504#endif
9505
9506 do
9507 {
9508 bfd_reloc_code_real_type reloc;
9509
9510 expression (& exp);
9511
9512 if (exp.X_op == O_symbol
9513 && * input_line_pointer == '('
9514 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
9515 {
9516 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
9517 int size = bfd_get_reloc_size (howto);
9518
9519 if (size > nbytes)
9520 as_bad ("%s relocations do not fit in %d bytes",
9521 howto->name, nbytes);
9522 else
9523 {
9524 register char *p = frag_more ((int) nbytes);
9525 int offset = nbytes - size;
9526
9527 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
9528 &exp, 0, reloc);
9529 }
9530 }
9531 else
9532 emit_expr (&exp, (unsigned int) nbytes);
9533 }
9534 while (*input_line_pointer++ == ',');
9535
9536 /* Put terminator back into stream. */
9537 input_line_pointer --;
9538 demand_empty_rest_of_line ();
9539}
9540
9541#endif /* OBJ_ELF */
9542
9543/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
9544 of an rs_align_code fragment. */
9545
9546void
9547arm_handle_align (fragP)
9548 fragS *fragP;
9549{
9550 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
9551 static char const thumb_noop[2] = { 0xc0, 0x46 };
9552 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
9553 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
9554
9555 int bytes, fix, noop_size;
9556 char * p;
9557 const char * noop;
9558
9559 if (fragP->fr_type != rs_align_code)
9560 return;
9561
9562 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
9563 p = fragP->fr_literal + fragP->fr_fix;
9564 fix = 0;
9565
9566 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
9567 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
9568
9569 if (fragP->tc_frag_data)
9570 {
9571 if (target_big_endian)
9572 noop = thumb_bigend_noop;
9573 else
9574 noop = thumb_noop;
9575 noop_size = sizeof (thumb_noop);
9576 }
9577 else
9578 {
9579 if (target_big_endian)
9580 noop = arm_bigend_noop;
9581 else
9582 noop = arm_noop;
9583 noop_size = sizeof (arm_noop);
9584 }
9585
9586 if (bytes & (noop_size - 1))
9587 {
9588 fix = bytes & (noop_size - 1);
9589 memset (p, 0, fix);
9590 p += fix;
9591 bytes -= fix;
9592 }
9593
9594 while (bytes >= noop_size)
9595 {
9596 memcpy (p, noop, noop_size);
9597 p += noop_size;
9598 bytes -= noop_size;
9599 fix += noop_size;
9600 }
9601
9602 fragP->fr_fix += fix;
9603 fragP->fr_var = noop_size;
9604}
9605
9606/* Called from md_do_align. Used to create an alignment
9607 frag in a code section. */
9608
9609void
9610arm_frag_align_code (n, max)
9611 int n;
9612 int max;
9613{
9614 char * p;
9615
9616 /* We assume that there will never be a requirment
9617 to support alignments greater than 32 bytes. */
9618 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
9619 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
9620
9621 p = frag_var (rs_align_code,
9622 MAX_MEM_FOR_RS_ALIGN_CODE,
9623 1,
9624 (relax_substateT) max,
9625 (symbolS *) NULL,
9626 (offsetT) n,
9627 (char *) NULL);
9628 *p = 0;
9629
9630}
9631
9632/* Perform target specific initialisation of a frag. */
9633
9634void
9635arm_init_frag (fragP)
9636 fragS *fragP;
9637{
9638 /* Record whether this frag is in an ARM or a THUMB area. */
9639 fragP->tc_frag_data = thumb_mode;
9640}