Add support for WinCE targeted toolchains.
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
252b5132
RH
1/* tc-arm.c -- Assemble for the ARM
2 Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
3 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4 Modified by David Taylor (dtaylor@armltd.co.uk)
5
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
22
23#include <ctype.h>
24#include <string.h>
25#define NO_RELOC 0
26#include "as.h"
27
28/* need TARGET_CPU */
29#include "config.h"
30#include "subsegs.h"
31#include "obstack.h"
32#include "symbols.h"
33#include "listing.h"
34
35#ifdef OBJ_ELF
36#include "elf/arm.h"
37#endif
38
39/* Types of processor to assemble for. */
40#define ARM_1 0x00000001
41#define ARM_2 0x00000002
42#define ARM_3 0x00000004
43#define ARM_250 ARM_3
44#define ARM_6 0x00000008
45#define ARM_7 ARM_6 /* same core instruction set */
46#define ARM_8 ARM_6 /* same core instruction set */
47#define ARM_9 ARM_6 /* same core instruction set */
48#define ARM_CPU_MASK 0x0000000f
49
50/* The following bitmasks control CPU extensions (ARM7 onwards): */
51#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
52#define ARM_HALFWORD 0x00000020 /* allow half word loads */
53#define ARM_THUMB 0x00000040 /* allow BX instruction */
49a5575c 54#define ARM_EXT_V5 0x00000080 /* allow CLZ etc */
92a66162 55#define ARM_EXT_V5E 0x00000200 /* "El Segundo" */
252b5132 56
49a5575c
NC
57/* Architectures are the sum of the base and extensions */
58#define ARM_ARCH_V4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD)
59#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_THUMB)
858f4ff6 60#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
49a5575c 61#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_THUMB)
252b5132
RH
62
63/* Some useful combinations: */
64#define ARM_ANY 0x00ffffff
49a5575c 65#define ARM_2UP (ARM_ANY - ARM_1)
252b5132
RH
66#define ARM_ALL ARM_2UP /* Not arm1 only */
67#define ARM_3UP 0x00fffffc
68#define ARM_6UP 0x00fffff8 /* Includes ARM7 */
69
70#define FPU_CORE 0x80000000
71#define FPU_FPA10 0x40000000
72#define FPU_FPA11 0x40000000
73#define FPU_NONE 0
74
75/* Some useful combinations */
76#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */
77#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */
78
79
80#ifndef CPU_DEFAULT
81#if defined __thumb__
49a5575c 82#define CPU_DEFAULT (ARM_ARCH_V4 | ARM_THUMB)
252b5132
RH
83#else
84#define CPU_DEFAULT ARM_ALL
85#endif
86#endif
87
88#ifndef FPU_DEFAULT
89#define FPU_DEFAULT FPU_ALL
90#endif
91
ae5ad4ad
NC
92#define streq(a, b) (strcmp (a, b) == 0)
93#define skip_whitespace(str) while (* (str) == ' ') ++ (str)
252b5132
RH
94
95static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
96static int target_oabi = 0;
97
98#if defined OBJ_COFF || defined OBJ_ELF
99/* Flags stored in private area of BFD structure */
100static boolean uses_apcs_26 = false;
101static boolean support_interwork = false;
102static boolean uses_apcs_float = false;
103static boolean pic_code = false;
104#endif
105
106/* This array holds the chars that always start a comment. If the
107 pre-processor is disabled, these aren't very useful */
108CONST char comment_chars[] = "@";
109
110/* This array holds the chars that only start a comment at the beginning of
111 a line. If the line seems to have the form '# 123 filename'
112 .line and .file directives will appear in the pre-processed output */
113/* Note that input_file.c hand checks for '#' at the beginning of the
114 first line of the input file. This is because the compiler outputs
115 #NO_APP at the beginning of its output. */
116/* Also note that comments like this one will always work. */
117CONST char line_comment_chars[] = "#";
118
119#ifdef TE_LINUX
120CONST char line_separator_chars[] = ";";
121#else
122CONST char line_separator_chars[] = "";
123#endif
124
125/* Chars that can be used to separate mant from exp in floating point nums */
126CONST char EXP_CHARS[] = "eE";
127
128/* Chars that mean this number is a floating point constant */
129/* As in 0f12.456 */
130/* or 0d1.2345e12 */
131
132CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
133
134/* Prefix characters that indicate the start of an immediate
135 value. */
136#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
137
138#ifdef OBJ_ELF
139symbolS * GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
140#endif
141
a64bcdd8 142CONST int md_reloc_size = 8; /* Size of relocation record */
252b5132 143
a64bcdd8
NC
144static int thumb_mode = 0; /* 0: assemble for ARM, 1: assemble for Thumb,
145 2: assemble for Thumb even though target cpu
146 does not support thumb instructions */
252b5132
RH
147typedef struct arm_fix
148{
149 int thumb_mode;
150} arm_fix_data;
151
152struct arm_it
153{
154 CONST char * error;
155 unsigned long instruction;
156 int suffix;
157 int size;
158 struct
159 {
160 bfd_reloc_code_real_type type;
161 expressionS exp;
162 int pc_rel;
163 } reloc;
164};
165
166struct arm_it inst;
167
168struct asm_shift
169{
170 CONST char * template;
171 unsigned long value;
172};
173
174static CONST struct asm_shift shift[] =
175{
176 {"asl", 0},
177 {"lsl", 0},
178 {"lsr", 0x00000020},
179 {"asr", 0x00000040},
180 {"ror", 0x00000060},
181 {"rrx", 0x00000060},
182 {"ASL", 0},
183 {"LSL", 0},
184 {"LSR", 0x00000020},
185 {"ASR", 0x00000040},
186 {"ROR", 0x00000060},
187 {"RRX", 0x00000060}
188};
189
190#define NO_SHIFT_RESTRICT 1
191#define SHIFT_RESTRICT 0
192
193#define NUM_FLOAT_VALS 8
194
195CONST char * fp_const[] =
196{
197 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
198};
199
200/* Number of littlenums required to hold an extended precision number */
201#define MAX_LITTLENUMS 6
202
203LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
204
205#define FAIL (-1)
206#define SUCCESS (0)
207
208#define SUFF_S 1
209#define SUFF_D 2
210#define SUFF_E 3
211#define SUFF_P 4
212
213#define CP_T_X 0x00008000
214#define CP_T_Y 0x00400000
215#define CP_T_Pre 0x01000000
216#define CP_T_UD 0x00800000
217#define CP_T_WB 0x00200000
218
219#define CONDS_BIT (0x00100000)
220#define LOAD_BIT (0x00100000)
221#define TRANS_BIT (0x00200000)
222
223struct asm_cond
224{
225 CONST char * template;
226 unsigned long value;
227};
228
229/* This is to save a hash look-up in the common case */
230#define COND_ALWAYS 0xe0000000
231
232static CONST struct asm_cond conds[] =
233{
234 {"eq", 0x00000000},
235 {"ne", 0x10000000},
236 {"cs", 0x20000000}, {"hs", 0x20000000},
237 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
238 {"mi", 0x40000000},
239 {"pl", 0x50000000},
240 {"vs", 0x60000000},
241 {"vc", 0x70000000},
242 {"hi", 0x80000000},
243 {"ls", 0x90000000},
244 {"ge", 0xa0000000},
245 {"lt", 0xb0000000},
246 {"gt", 0xc0000000},
247 {"le", 0xd0000000},
248 {"al", 0xe0000000},
249 {"nv", 0xf0000000}
250};
251
252/* Warning: If the top bit of the set_bits is set, then the standard
253 instruction bitmask is ignored, and the new bitmask is taken from
254 the set_bits: */
255struct asm_flg
256{
257 CONST char * template; /* Basic flag string */
258 unsigned long set_bits; /* Bits to set */
259};
260
261static CONST struct asm_flg s_flag[] =
262{
263 {"s", CONDS_BIT},
264 {NULL, 0}
265};
266
267static CONST struct asm_flg ldr_flags[] =
268{
269 {"b", 0x00400000},
270 {"t", TRANS_BIT},
271 {"bt", 0x00400000 | TRANS_BIT},
272 {"h", 0x801000b0},
273 {"sh", 0x801000f0},
274 {"sb", 0x801000d0},
275 {NULL, 0}
276};
277
278static CONST struct asm_flg str_flags[] =
279{
280 {"b", 0x00400000},
281 {"t", TRANS_BIT},
282 {"bt", 0x00400000 | TRANS_BIT},
283 {"h", 0x800000b0},
284 {NULL, 0}
285};
286
287static CONST struct asm_flg byte_flag[] =
288{
289 {"b", 0x00400000},
290 {NULL, 0}
291};
292
293static CONST struct asm_flg cmp_flags[] =
294{
295 {"s", CONDS_BIT},
296 {"p", 0x0010f000},
297 {NULL, 0}
298};
299
300static CONST struct asm_flg ldm_flags[] =
301{
302 {"ed", 0x01800000},
303 {"fd", 0x00800000},
304 {"ea", 0x01000000},
305 {"fa", 0x08000000},
306 {"ib", 0x01800000},
307 {"ia", 0x00800000},
308 {"db", 0x01000000},
309 {"da", 0x08000000},
310 {NULL, 0}
311};
312
313static CONST struct asm_flg stm_flags[] =
314{
315 {"ed", 0x08000000},
316 {"fd", 0x01000000},
317 {"ea", 0x00800000},
318 {"fa", 0x01800000},
319 {"ib", 0x01800000},
320 {"ia", 0x00800000},
321 {"db", 0x01000000},
322 {"da", 0x08000000},
323 {NULL, 0}
324};
325
326static CONST struct asm_flg lfm_flags[] =
327{
328 {"fd", 0x00800000},
329 {"ea", 0x01000000},
330 {NULL, 0}
331};
332
333static CONST struct asm_flg sfm_flags[] =
334{
335 {"fd", 0x01000000},
336 {"ea", 0x00800000},
337 {NULL, 0}
338};
339
340static CONST struct asm_flg round_flags[] =
341{
342 {"p", 0x00000020},
343 {"m", 0x00000040},
344 {"z", 0x00000060},
345 {NULL, 0}
346};
347
348/* The implementation of the FIX instruction is broken on some assemblers,
349 in that it accepts a precision specifier as well as a rounding specifier,
350 despite the fact that this is meaningless. To be more compatible, we
351 accept it as well, though of course it does not set any bits. */
352static CONST struct asm_flg fix_flags[] =
353{
354 {"p", 0x00000020},
355 {"m", 0x00000040},
356 {"z", 0x00000060},
357 {"sp", 0x00000020},
358 {"sm", 0x00000040},
359 {"sz", 0x00000060},
360 {"dp", 0x00000020},
361 {"dm", 0x00000040},
362 {"dz", 0x00000060},
363 {"ep", 0x00000020},
364 {"em", 0x00000040},
365 {"ez", 0x00000060},
366 {NULL, 0}
367};
368
369static CONST struct asm_flg except_flag[] =
370{
371 {"e", 0x00400000},
372 {NULL, 0}
373};
374
375static CONST struct asm_flg cplong_flag[] =
376{
377 {"l", 0x00400000},
378 {NULL, 0}
379};
380
381struct asm_psr
382{
383 CONST char * template;
384 unsigned long number;
385};
386
387#define PSR_FIELD_MASK 0x000f0000
388
389#define PSR_FLAGS 0x00080000
390#define PSR_CONTROL 0x00010000 /* Undocumented instruction, its use is discouraged by ARM */
391#define PSR_ALL 0x00090000
392
393#define CPSR_ALL 0
394#define SPSR_ALL 1
395#define CPSR_FLG 2
396#define SPSR_FLG 3
397#define CPSR_CTL 4
398#define SPSR_CTL 5
399
400static CONST struct asm_psr psrs[] =
401{
402 /* Valid <psr>'s */
403 {"cpsr", CPSR_ALL},
404 {"cpsr_all", CPSR_ALL},
405 {"spsr", SPSR_ALL},
406 {"spsr_all", SPSR_ALL},
407
408 /* Valid <psrf>'s */
409 {"cpsr_flg", CPSR_FLG},
410 {"spsr_flg", SPSR_FLG},
411
412 /* Valid <psrc>'s */
413 {"cpsr_c", CPSR_CTL},
414 {"cpsr_ctl", CPSR_CTL},
415 {"spsr_c", SPSR_CTL},
416 {"spsr_ctl", SPSR_CTL}
417};
418
419/* Functions called by parser */
420/* ARM instructions */
ae5ad4ad
NC
421static void do_arit PARAMS ((char *, unsigned long));
422static void do_cmp PARAMS ((char *, unsigned long));
423static void do_mov PARAMS ((char *, unsigned long));
424static void do_ldst PARAMS ((char *, unsigned long));
425static void do_ldmstm PARAMS ((char *, unsigned long));
426static void do_branch PARAMS ((char *, unsigned long));
427static void do_swi PARAMS ((char *, unsigned long));
428/* Pseudo Op codes */
429static void do_adr PARAMS ((char *, unsigned long));
430static void do_adrl PARAMS ((char *, unsigned long));
431static void do_nop PARAMS ((char *, unsigned long));
432/* ARM 2 */
433static void do_mul PARAMS ((char *, unsigned long));
434static void do_mla PARAMS ((char *, unsigned long));
435/* ARM 3 */
436static void do_swap PARAMS ((char *, unsigned long));
437/* ARM 6 */
438static void do_msr PARAMS ((char *, unsigned long));
439static void do_mrs PARAMS ((char *, unsigned long));
440/* ARM 7M */
441static void do_mull PARAMS ((char *, unsigned long));
442/* ARM THUMB */
443static void do_bx PARAMS ((char *, unsigned long));
92a66162 444
ae5ad4ad
NC
445
446/* Coprocessor Instructions */
447static void do_cdp PARAMS ((char *, unsigned long));
448static void do_lstc PARAMS ((char *, unsigned long));
449static void do_co_reg PARAMS ((char *, unsigned long));
450static void do_fp_ctrl PARAMS ((char *, unsigned long));
451static void do_fp_ldst PARAMS ((char *, unsigned long));
452static void do_fp_ldmstm PARAMS ((char *, unsigned long));
453static void do_fp_dyadic PARAMS ((char *, unsigned long));
454static void do_fp_monadic PARAMS ((char *, unsigned long));
455static void do_fp_cmp PARAMS ((char *, unsigned long));
456static void do_fp_from_reg PARAMS ((char *, unsigned long));
457static void do_fp_to_reg PARAMS ((char *, unsigned long));
458
459static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *, int, int));
460static int arm_reg_parse PARAMS ((char **));
461static int arm_psr_parse PARAMS ((char **));
462static void symbol_locate PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *));
252b5132 463static int add_to_lit_pool PARAMS ((void));
ae5ad4ad
NC
464static unsigned validate_immediate PARAMS ((unsigned));
465static unsigned validate_immediate_twopart PARAMS ((unsigned int, unsigned int *));
276b1dc2 466static int validate_offset_imm PARAMS ((unsigned int, int));
252b5132
RH
467static void opcode_select PARAMS ((int));
468static void end_of_line PARAMS ((char *));
469static int reg_required_here PARAMS ((char **, int));
470static int psr_required_here PARAMS ((char **, int, int));
471static int co_proc_number PARAMS ((char **));
472static int cp_opc_expr PARAMS ((char **, int, int));
473static int cp_reg_required_here PARAMS ((char **, int));
474static int fp_reg_required_here PARAMS ((char **, int));
475static int cp_address_offset PARAMS ((char **));
476static int cp_address_required_here PARAMS ((char **));
477static int my_get_float_expression PARAMS ((char **));
478static int skip_past_comma PARAMS ((char **));
479static int walk_no_bignums PARAMS ((symbolS *));
ae5ad4ad 480static int negate_data_op PARAMS ((unsigned long *, unsigned long));
252b5132
RH
481static int data_op2 PARAMS ((char **));
482static int fp_op2 PARAMS ((char **));
483static long reg_list PARAMS ((char **));
484static void thumb_load_store PARAMS ((char *, int, int));
485static int decode_shift PARAMS ((char **, int));
486static int ldst_extend PARAMS ((char **, int));
487static void thumb_add_sub PARAMS ((char *, int));
488static void insert_reg PARAMS ((int));
489static void thumb_shift PARAMS ((char *, int));
490static void thumb_mov_compare PARAMS ((char *, int));
491static void set_constant_flonums PARAMS ((void));
492static valueT md_chars_to_number PARAMS ((char *, int));
493static void insert_reg_alias PARAMS ((char *, int));
49a5575c 494static void output_inst PARAMS ((void));
252b5132 495#ifdef OBJ_ELF
661e4995 496static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
252b5132
RH
497#endif
498
499/* ARM instructions take 4bytes in the object file, Thumb instructions
500 take 2: */
501#define INSN_SIZE 4
502
503/* LONGEST_INST is the longest basic instruction name without conditions or
504 * flags.
505 * ARM7M has 4 of length 5
506 */
507
508#define LONGEST_INST 5
509
92a66162 510
252b5132
RH
511struct asm_opcode
512{
513 CONST char * template; /* Basic string to match */
514 unsigned long value; /* Basic instruction code */
92a66162
DL
515
516 /* Compulsory suffix that must follow conds. If "", then the
517 instruction is not conditional and must have no suffix. */
518 CONST char * comp_suffix;
519
252b5132
RH
520 CONST struct asm_flg * flags; /* Bits to toggle if flag 'n' set */
521 unsigned long variants; /* Which CPU variants this exists for */
522 /* Function to call to parse args */
523 void (* parms) PARAMS ((char *, unsigned long));
524};
525
526static CONST struct asm_opcode insns[] =
527{
528/* ARM Instructions */
529 {"and", 0x00000000, NULL, s_flag, ARM_ANY, do_arit},
530 {"eor", 0x00200000, NULL, s_flag, ARM_ANY, do_arit},
531 {"sub", 0x00400000, NULL, s_flag, ARM_ANY, do_arit},
532 {"rsb", 0x00600000, NULL, s_flag, ARM_ANY, do_arit},
533 {"add", 0x00800000, NULL, s_flag, ARM_ANY, do_arit},
534 {"adc", 0x00a00000, NULL, s_flag, ARM_ANY, do_arit},
535 {"sbc", 0x00c00000, NULL, s_flag, ARM_ANY, do_arit},
536 {"rsc", 0x00e00000, NULL, s_flag, ARM_ANY, do_arit},
537 {"orr", 0x01800000, NULL, s_flag, ARM_ANY, do_arit},
538 {"bic", 0x01c00000, NULL, s_flag, ARM_ANY, do_arit},
539 {"tst", 0x01000000, NULL, cmp_flags, ARM_ANY, do_cmp},
540 {"teq", 0x01200000, NULL, cmp_flags, ARM_ANY, do_cmp},
541 {"cmp", 0x01400000, NULL, cmp_flags, ARM_ANY, do_cmp},
542 {"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp},
543 {"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov},
544 {"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov},
545 {"str", 0x04000000, NULL, str_flags, ARM_ANY, do_ldst},
546 {"ldr", 0x04100000, NULL, ldr_flags, ARM_ANY, do_ldst},
547 {"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm},
548 {"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm},
549 {"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi},
550 {"bl", 0x0bfffffe, NULL, NULL, ARM_ANY, do_branch},
551 {"b", 0x0afffffe, NULL, NULL, ARM_ANY, do_branch},
552
553/* Pseudo ops */
554 {"adr", 0x028f0000, NULL, NULL, ARM_ANY, do_adr},
49a5575c 555 {"adrl", 0x028f0000, NULL, NULL, ARM_ANY, do_adrl},
252b5132
RH
556 {"nop", 0x01a00000, NULL, NULL, ARM_ANY, do_nop},
557
558/* ARM 2 multiplies */
559 {"mul", 0x00000090, NULL, s_flag, ARM_2UP, do_mul},
560 {"mla", 0x00200090, NULL, s_flag, ARM_2UP, do_mla},
561
562/* ARM 3 - swp instructions */
563 {"swp", 0x01000090, NULL, byte_flag, ARM_3UP, do_swap},
564
565/* ARM 6 Coprocessor instructions */
566 {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
567 {"msr", 0x0120f000, NULL, NULL, ARM_6UP, do_msr},
568/* ScottB: our code uses 0x0128f000 for msr.
569 NickC: but this is wrong because the bits 16 and 19 are handled
570 by the PSR_xxx defines above. */
571
572/* ARM 7M long multiplies - need signed/unsigned flags! */
573 {"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull},
574 {"umull", 0x00800090, NULL, s_flag, ARM_LONGMUL, do_mull},
575 {"smlal", 0x00e00090, NULL, s_flag, ARM_LONGMUL, do_mull},
576 {"umlal", 0x00a00090, NULL, s_flag, ARM_LONGMUL, do_mull},
577
578/* ARM THUMB interworking */
579 {"bx", 0x012fff10, NULL, NULL, ARM_THUMB, do_bx},
580
581/* Floating point instructions */
582 {"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl},
583 {"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl},
584 {"wfc", 0x0e400110, NULL, NULL, FPU_ALL, do_fp_ctrl},
585 {"rfc", 0x0e500110, NULL, NULL, FPU_ALL, do_fp_ctrl},
586 {"ldf", 0x0c100100, "sdep", NULL, FPU_ALL, do_fp_ldst},
587 {"stf", 0x0c000100, "sdep", NULL, FPU_ALL, do_fp_ldst},
588 {"lfm", 0x0c100200, NULL, lfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
589 {"sfm", 0x0c000200, NULL, sfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
590 {"mvf", 0x0e008100, "sde", round_flags, FPU_ALL, do_fp_monadic},
591 {"mnf", 0x0e108100, "sde", round_flags, FPU_ALL, do_fp_monadic},
592 {"abs", 0x0e208100, "sde", round_flags, FPU_ALL, do_fp_monadic},
593 {"rnd", 0x0e308100, "sde", round_flags, FPU_ALL, do_fp_monadic},
594 {"sqt", 0x0e408100, "sde", round_flags, FPU_ALL, do_fp_monadic},
595 {"log", 0x0e508100, "sde", round_flags, FPU_ALL, do_fp_monadic},
596 {"lgn", 0x0e608100, "sde", round_flags, FPU_ALL, do_fp_monadic},
597 {"exp", 0x0e708100, "sde", round_flags, FPU_ALL, do_fp_monadic},
598 {"sin", 0x0e808100, "sde", round_flags, FPU_ALL, do_fp_monadic},
599 {"cos", 0x0e908100, "sde", round_flags, FPU_ALL, do_fp_monadic},
600 {"tan", 0x0ea08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
601 {"asn", 0x0eb08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
602 {"acs", 0x0ec08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
603 {"atn", 0x0ed08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
604 {"urd", 0x0ee08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
605 {"nrm", 0x0ef08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
606 {"adf", 0x0e000100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
607 {"suf", 0x0e200100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
608 {"rsf", 0x0e300100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
609 {"muf", 0x0e100100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
610 {"dvf", 0x0e400100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
611 {"rdf", 0x0e500100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
612 {"pow", 0x0e600100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
613 {"rpw", 0x0e700100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
614 {"rmf", 0x0e800100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
615 {"fml", 0x0e900100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
616 {"fdv", 0x0ea00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
617 {"frd", 0x0eb00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
618 {"pol", 0x0ec00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
619 {"cmf", 0x0e90f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
620 {"cnf", 0x0eb0f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
621/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
622 be an optional suffix, but part of the instruction. To be compatible,
623 we accept either. */
624 {"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
625 {"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
626 {"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg},
627 {"fix", 0x0e100110, NULL, fix_flags, FPU_ALL, do_fp_to_reg},
628
629/* Generic copressor instructions */
630 {"cdp", 0x0e000000, NULL, NULL, ARM_2UP, do_cdp},
631 {"ldc", 0x0c100000, NULL, cplong_flag, ARM_2UP, do_lstc},
632 {"stc", 0x0c000000, NULL, cplong_flag, ARM_2UP, do_lstc},
633 {"mcr", 0x0e000010, NULL, NULL, ARM_2UP, do_co_reg},
634 {"mrc", 0x0e100010, NULL, NULL, ARM_2UP, do_co_reg},
635};
636
637/* defines for various bits that we will want to toggle */
638
639#define INST_IMMEDIATE 0x02000000
640#define OFFSET_REG 0x02000000
641#define HWOFFSET_IMM 0x00400000
642#define SHIFT_BY_REG 0x00000010
643#define PRE_INDEX 0x01000000
644#define INDEX_UP 0x00800000
645#define WRITE_BACK 0x00200000
913f265c 646#define LDM_TYPE_2_OR_3 0x00400000
252b5132
RH
647
648#define LITERAL_MASK 0xf000f000
649#define COND_MASK 0xf0000000
650#define OPCODE_MASK 0xfe1fffff
651#define DATA_OP_SHIFT 21
652
653/* Codes to distinguish the arithmetic instructions */
654
655#define OPCODE_AND 0
656#define OPCODE_EOR 1
657#define OPCODE_SUB 2
658#define OPCODE_RSB 3
659#define OPCODE_ADD 4
660#define OPCODE_ADC 5
661#define OPCODE_SBC 6
662#define OPCODE_RSC 7
663#define OPCODE_TST 8
664#define OPCODE_TEQ 9
665#define OPCODE_CMP 10
666#define OPCODE_CMN 11
667#define OPCODE_ORR 12
668#define OPCODE_MOV 13
669#define OPCODE_BIC 14
670#define OPCODE_MVN 15
671
ae5ad4ad
NC
672static void do_t_nop PARAMS ((char *));
673static void do_t_arit PARAMS ((char *));
674static void do_t_add PARAMS ((char *));
675static void do_t_asr PARAMS ((char *));
676static void do_t_branch9 PARAMS ((char *));
677static void do_t_branch12 PARAMS ((char *));
678static void do_t_branch23 PARAMS ((char *));
679static void do_t_bx PARAMS ((char *));
680static void do_t_compare PARAMS ((char *));
681static void do_t_ldmstm PARAMS ((char *));
682static void do_t_ldr PARAMS ((char *));
683static void do_t_ldrb PARAMS ((char *));
684static void do_t_ldrh PARAMS ((char *));
685static void do_t_lds PARAMS ((char *));
686static void do_t_lsl PARAMS ((char *));
687static void do_t_lsr PARAMS ((char *));
688static void do_t_mov PARAMS ((char *));
689static void do_t_push_pop PARAMS ((char *));
690static void do_t_str PARAMS ((char *));
691static void do_t_strb PARAMS ((char *));
692static void do_t_strh PARAMS ((char *));
693static void do_t_sub PARAMS ((char *));
694static void do_t_swi PARAMS ((char *));
695static void do_t_adr PARAMS ((char *));
252b5132
RH
696
697#define T_OPCODE_MUL 0x4340
698#define T_OPCODE_TST 0x4200
699#define T_OPCODE_CMN 0x42c0
700#define T_OPCODE_NEG 0x4240
701#define T_OPCODE_MVN 0x43c0
702
703#define T_OPCODE_ADD_R3 0x1800
704#define T_OPCODE_SUB_R3 0x1a00
705#define T_OPCODE_ADD_HI 0x4400
706#define T_OPCODE_ADD_ST 0xb000
707#define T_OPCODE_SUB_ST 0xb080
708#define T_OPCODE_ADD_SP 0xa800
709#define T_OPCODE_ADD_PC 0xa000
710#define T_OPCODE_ADD_I8 0x3000
711#define T_OPCODE_SUB_I8 0x3800
712#define T_OPCODE_ADD_I3 0x1c00
713#define T_OPCODE_SUB_I3 0x1e00
714
715#define T_OPCODE_ASR_R 0x4100
716#define T_OPCODE_LSL_R 0x4080
717#define T_OPCODE_LSR_R 0x40c0
718#define T_OPCODE_ASR_I 0x1000
719#define T_OPCODE_LSL_I 0x0000
720#define T_OPCODE_LSR_I 0x0800
721
722#define T_OPCODE_MOV_I8 0x2000
723#define T_OPCODE_CMP_I8 0x2800
724#define T_OPCODE_CMP_LR 0x4280
725#define T_OPCODE_MOV_HR 0x4600
726#define T_OPCODE_CMP_HR 0x4500
727
728#define T_OPCODE_LDR_PC 0x4800
729#define T_OPCODE_LDR_SP 0x9800
730#define T_OPCODE_STR_SP 0x9000
731#define T_OPCODE_LDR_IW 0x6800
732#define T_OPCODE_STR_IW 0x6000
733#define T_OPCODE_LDR_IH 0x8800
734#define T_OPCODE_STR_IH 0x8000
735#define T_OPCODE_LDR_IB 0x7800
736#define T_OPCODE_STR_IB 0x7000
737#define T_OPCODE_LDR_RW 0x5800
738#define T_OPCODE_STR_RW 0x5000
739#define T_OPCODE_LDR_RH 0x5a00
740#define T_OPCODE_STR_RH 0x5200
741#define T_OPCODE_LDR_RB 0x5c00
742#define T_OPCODE_STR_RB 0x5400
743
744#define T_OPCODE_PUSH 0xb400
745#define T_OPCODE_POP 0xbc00
746
747#define T_OPCODE_BRANCH 0xe7fe
748
749static int thumb_reg PARAMS ((char ** str, int hi_lo));
750
751#define THUMB_SIZE 2 /* Size of thumb instruction */
752#define THUMB_REG_LO 0x1
753#define THUMB_REG_HI 0x2
754#define THUMB_REG_ANY 0x3
755
756#define THUMB_H1 0x0080
757#define THUMB_H2 0x0040
758
759#define THUMB_ASR 0
760#define THUMB_LSL 1
761#define THUMB_LSR 2
762
763#define THUMB_MOVE 0
764#define THUMB_COMPARE 1
765
766#define THUMB_LOAD 0
767#define THUMB_STORE 1
768
769#define THUMB_PP_PC_LR 0x0100
770
771/* These three are used for immediate shifts, do not alter */
772#define THUMB_WORD 2
773#define THUMB_HALFWORD 1
774#define THUMB_BYTE 0
775
776struct thumb_opcode
777{
778 CONST char * template; /* Basic string to match */
779 unsigned long value; /* Basic instruction code */
780 int size;
b49cfa5d 781 unsigned long variants; /* Which CPU variants this exists for */
252b5132
RH
782 void (* parms) PARAMS ((char *)); /* Function to call to parse args */
783};
784
785static CONST struct thumb_opcode tinsns[] =
786{
b49cfa5d
JL
787 {"adc", 0x4140, 2, ARM_THUMB, do_t_arit},
788 {"add", 0x0000, 2, ARM_THUMB, do_t_add},
789 {"and", 0x4000, 2, ARM_THUMB, do_t_arit},
790 {"asr", 0x0000, 2, ARM_THUMB, do_t_asr},
791 {"b", T_OPCODE_BRANCH, 2, ARM_THUMB, do_t_branch12},
792 {"beq", 0xd0fe, 2, ARM_THUMB, do_t_branch9},
793 {"bne", 0xd1fe, 2, ARM_THUMB, do_t_branch9},
794 {"bcs", 0xd2fe, 2, ARM_THUMB, do_t_branch9},
795 {"bhs", 0xd2fe, 2, ARM_THUMB, do_t_branch9},
796 {"bcc", 0xd3fe, 2, ARM_THUMB, do_t_branch9},
797 {"bul", 0xd3fe, 2, ARM_THUMB, do_t_branch9},
798 {"blo", 0xd3fe, 2, ARM_THUMB, do_t_branch9},
799 {"bmi", 0xd4fe, 2, ARM_THUMB, do_t_branch9},
800 {"bpl", 0xd5fe, 2, ARM_THUMB, do_t_branch9},
801 {"bvs", 0xd6fe, 2, ARM_THUMB, do_t_branch9},
802 {"bvc", 0xd7fe, 2, ARM_THUMB, do_t_branch9},
803 {"bhi", 0xd8fe, 2, ARM_THUMB, do_t_branch9},
804 {"bls", 0xd9fe, 2, ARM_THUMB, do_t_branch9},
805 {"bge", 0xdafe, 2, ARM_THUMB, do_t_branch9},
806 {"blt", 0xdbfe, 2, ARM_THUMB, do_t_branch9},
807 {"bgt", 0xdcfe, 2, ARM_THUMB, do_t_branch9},
808 {"ble", 0xddfe, 2, ARM_THUMB, do_t_branch9},
809 {"bic", 0x4380, 2, ARM_THUMB, do_t_arit},
810 {"bl", 0xf7fffffe, 4, ARM_THUMB, do_t_branch23},
811 {"bx", 0x4700, 2, ARM_THUMB, do_t_bx},
812 {"cmn", T_OPCODE_CMN, 2, ARM_THUMB, do_t_arit},
813 {"cmp", 0x0000, 2, ARM_THUMB, do_t_compare},
814 {"eor", 0x4040, 2, ARM_THUMB, do_t_arit},
815 {"ldmia", 0xc800, 2, ARM_THUMB, do_t_ldmstm},
816 {"ldr", 0x0000, 2, ARM_THUMB, do_t_ldr},
817 {"ldrb", 0x0000, 2, ARM_THUMB, do_t_ldrb},
818 {"ldrh", 0x0000, 2, ARM_THUMB, do_t_ldrh},
819 {"ldrsb", 0x5600, 2, ARM_THUMB, do_t_lds},
820 {"ldrsh", 0x5e00, 2, ARM_THUMB, do_t_lds},
821 {"ldsb", 0x5600, 2, ARM_THUMB, do_t_lds},
822 {"ldsh", 0x5e00, 2, ARM_THUMB, do_t_lds},
823 {"lsl", 0x0000, 2, ARM_THUMB, do_t_lsl},
824 {"lsr", 0x0000, 2, ARM_THUMB, do_t_lsr},
825 {"mov", 0x0000, 2, ARM_THUMB, do_t_mov},
826 {"mul", T_OPCODE_MUL, 2, ARM_THUMB, do_t_arit},
827 {"mvn", T_OPCODE_MVN, 2, ARM_THUMB, do_t_arit},
828 {"neg", T_OPCODE_NEG, 2, ARM_THUMB, do_t_arit},
829 {"orr", 0x4300, 2, ARM_THUMB, do_t_arit},
830 {"pop", 0xbc00, 2, ARM_THUMB, do_t_push_pop},
831 {"push", 0xb400, 2, ARM_THUMB, do_t_push_pop},
832 {"ror", 0x41c0, 2, ARM_THUMB, do_t_arit},
833 {"sbc", 0x4180, 2, ARM_THUMB, do_t_arit},
834 {"stmia", 0xc000, 2, ARM_THUMB, do_t_ldmstm},
835 {"str", 0x0000, 2, ARM_THUMB, do_t_str},
836 {"strb", 0x0000, 2, ARM_THUMB, do_t_strb},
837 {"strh", 0x0000, 2, ARM_THUMB, do_t_strh},
838 {"swi", 0xdf00, 2, ARM_THUMB, do_t_swi},
839 {"sub", 0x0000, 2, ARM_THUMB, do_t_sub},
840 {"tst", T_OPCODE_TST, 2, ARM_THUMB, do_t_arit},
252b5132 841 /* Pseudo ops: */
b49cfa5d
JL
842 {"adr", 0x0000, 2, ARM_THUMB, do_t_adr},
843 {"nop", 0x46C0, 2, ARM_THUMB, do_t_nop}, /* mov r8,r8 */
252b5132
RH
844};
845
846struct reg_entry
847{
848 CONST char * name;
849 int number;
850};
851
852#define int_register(reg) ((reg) >= 0 && (reg) <= 15)
853#define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
854#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
855
856#define REG_PC 15
857#define REG_LR 14
858#define REG_SP 13
859
557537a5 860/* These are the standard names. Users can add aliases with .req */
252b5132
RH
861static CONST struct reg_entry reg_table[] =
862{
557537a5 863 /* Processor Register Numbers. */
252b5132
RH
864 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
865 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
866 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
867 {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
557537a5 868 /* APCS conventions. */
252b5132
RH
869 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
870 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
871 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
872 {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
557537a5
NC
873 /* ATPCS additions to APCS conventions. */
874 {"wr", 7}, {"v8", 11},
875 /* FP Registers. */
252b5132
RH
876 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
877 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
878 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
879 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
880 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
881 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
882 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
883 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
884 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
885 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
557537a5
NC
886 /* ATPCS additions to float register names. */
887 {"s0",16}, {"s1",17}, {"s2",18}, {"s3",19},
888 {"s4",20}, {"s5",21}, {"s6",22}, {"s7",23},
889 {"d0",16}, {"d1",17}, {"d2",18}, {"d3",19},
890 {"d4",20}, {"d5",21}, {"d6",22}, {"d7",23},
891 /* FIXME: At some point we need to add VFP register names. */
892 /* Array terminator. */
252b5132
RH
893 {NULL, 0}
894};
895
92a66162
DL
896#define BAD_ARGS _("Bad arguments to instruction")
897#define BAD_PC _("r15 not allowed here")
898#define BAD_FLAGS _("Instruction should not have flags")
899#define BAD_COND _("Instruction is not conditional")
252b5132
RH
900
901static struct hash_control * arm_ops_hsh = NULL;
902static struct hash_control * arm_tops_hsh = NULL;
903static struct hash_control * arm_cond_hsh = NULL;
904static struct hash_control * arm_shift_hsh = NULL;
905static struct hash_control * arm_reg_hsh = NULL;
906static struct hash_control * arm_psr_hsh = NULL;
907
908/* This table describes all the machine specific pseudo-ops the assembler
909 has to support. The fields are:
910 pseudo-op name without dot
911 function to call to execute this pseudo-op
912 Integer arg to pass to the function
913 */
914
915static void s_req PARAMS ((int));
916static void s_align PARAMS ((int));
917static void s_bss PARAMS ((int));
918static void s_even PARAMS ((int));
919static void s_ltorg PARAMS ((int));
920static void s_arm PARAMS ((int));
921static void s_thumb PARAMS ((int));
922static void s_code PARAMS ((int));
923static void s_force_thumb PARAMS ((int));
924static void s_thumb_func PARAMS ((int));
fed881b1
NC
925static void s_thumb_set PARAMS ((int));
926static void arm_s_text PARAMS ((int));
927static void arm_s_data PARAMS ((int));
252b5132 928#ifdef OBJ_ELF
fed881b1 929static void arm_s_section PARAMS ((int));
252b5132
RH
930static void s_arm_elf_cons PARAMS ((int));
931#endif
932
933static int my_get_expression PARAMS ((expressionS *, char **));
934
935CONST pseudo_typeS md_pseudo_table[] =
936{
fed881b1
NC
937 { "req", s_req, 0 }, /* Never called becasue '.req' does not start line */
938 { "bss", s_bss, 0 },
939 { "align", s_align, 0 },
940 { "arm", s_arm, 0 },
941 { "thumb", s_thumb, 0 },
942 { "code", s_code, 0 },
943 { "force_thumb", s_force_thumb, 0 },
944 { "thumb_func", s_thumb_func, 0 },
945 { "thumb_set", s_thumb_set, 0 },
946 { "even", s_even, 0 },
947 { "ltorg", s_ltorg, 0 },
948 { "pool", s_ltorg, 0 },
949 /* Allow for the effect of section changes. */
950 { "text", arm_s_text, 0 },
951 { "data", arm_s_data, 0 },
252b5132 952#ifdef OBJ_ELF
fed881b1
NC
953 { "section", arm_s_section, 0 },
954 { "section.s", arm_s_section, 0 },
955 { "sect", arm_s_section, 0 },
956 { "sect.s", arm_s_section, 0 },
957 { "word", s_arm_elf_cons, 4 },
958 { "long", s_arm_elf_cons, 4 },
252b5132 959#else
fed881b1 960 { "word", cons, 4},
252b5132 961#endif
fed881b1
NC
962 { "extend", float_cons, 'x' },
963 { "ldouble", float_cons, 'x' },
964 { "packed", float_cons, 'p' },
965 { 0, 0, 0 }
252b5132
RH
966};
967
968/* Stuff needed to resolve the label ambiguity
969 As:
970 ...
971 label: <insn>
972 may differ from:
973 ...
974 label:
975 <insn>
976*/
977
978symbolS * last_label_seen;
979static int label_is_thumb_function_name = false;
980
981/* Literal stuff */
982
983#define MAX_LITERAL_POOL_SIZE 1024
984
985typedef struct literalS
986{
987 struct expressionS exp;
988 struct arm_it * inst;
989} literalT;
990
991literalT literals[MAX_LITERAL_POOL_SIZE];
992int next_literal_pool_place = 0; /* Next free entry in the pool */
993int lit_pool_num = 1; /* Next literal pool number */
994symbolS * current_poolP = NULL;
252b5132
RH
995
996static int
997add_to_lit_pool ()
998{
999 int lit_count = 0;
1000
1001 if (current_poolP == NULL)
174419c1
ILT
1002 current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section,
1003 (valueT) 0, &zero_address_frag);
252b5132
RH
1004
1005 /* Check if this literal value is already in the pool: */
1006 while (lit_count < next_literal_pool_place)
1007 {
1008 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
1009 && inst.reloc.exp.X_op == O_constant
1010 && literals[lit_count].exp.X_add_number == inst.reloc.exp.X_add_number
1011 && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
1012 break;
1013 lit_count++;
1014 }
1015
1016 if (lit_count == next_literal_pool_place) /* new entry */
1017 {
1018 if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
1019 {
1020 inst.error = _("Literal Pool Overflow");
1021 return FAIL;
1022 }
1023
1024 literals[next_literal_pool_place].exp = inst.reloc.exp;
1025 lit_count = next_literal_pool_place++;
1026 }
1027
1028 inst.reloc.exp.X_op = O_symbol;
1029 inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
1030 inst.reloc.exp.X_add_symbol = current_poolP;
1031
1032 return SUCCESS;
1033}
1034
1035/* Can't use symbol_new here, so have to create a symbol and then at
1036 a later date assign it a value. Thats what these functions do. */
1037static void
1038symbol_locate (symbolP, name, segment, valu, frag)
1039 symbolS * symbolP;
1040 CONST char * name; /* It is copied, the caller can modify */
1041 segT segment; /* Segment identifier (SEG_<something>) */
1042 valueT valu; /* Symbol value */
1043 fragS * frag; /* Associated fragment */
1044{
1045 unsigned int name_length;
1046 char * preserved_copy_of_name;
1047
1048 name_length = strlen (name) + 1; /* +1 for \0 */
1049 obstack_grow (&notes, name, name_length);
1050 preserved_copy_of_name = obstack_finish (&notes);
1051#ifdef STRIP_UNDERSCORE
1052 if (preserved_copy_of_name[0] == '_')
1053 preserved_copy_of_name++;
1054#endif
1055
1056#ifdef tc_canonicalize_symbol_name
1057 preserved_copy_of_name =
1058 tc_canonicalize_symbol_name (preserved_copy_of_name);
1059#endif
1060
1061 S_SET_NAME (symbolP, preserved_copy_of_name);
1062
1063 S_SET_SEGMENT (symbolP, segment);
1064 S_SET_VALUE (symbolP, valu);
1065 symbol_clear_list_pointers(symbolP);
1066
174419c1 1067 symbol_set_frag (symbolP, frag);
252b5132
RH
1068
1069 /* Link to end of symbol chain. */
1070 {
1071 extern int symbol_table_frozen;
1072 if (symbol_table_frozen)
1073 abort ();
1074 }
1075
1076 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1077
1078 obj_symbol_new_hook (symbolP);
1079
1080#ifdef tc_symbol_new_hook
1081 tc_symbol_new_hook (symbolP);
1082#endif
1083
1084#ifdef DEBUG_SYMS
1085 verify_symbol_chain (symbol_rootP, symbol_lastP);
1086#endif /* DEBUG_SYMS */
1087}
1088
252b5132
RH
1089/* Check that an immediate is valid, and if so, convert it to the right format. */
1090
1091static unsigned int
1092validate_immediate (val)
1093 unsigned int val;
1094{
1095 unsigned int a;
1096 unsigned int i;
1097
1098#define rotate_left(v, n) (v << n | v >> (32 - n))
1099
1100 for (i = 0; i < 32; i += 2)
1101 if ((a = rotate_left (val, i)) <= 0xff)
1102 return a | (i << 7); /* 12-bit pack: [shift-cnt,const] */
1103
1104 return FAIL;
1105}
1106
49a5575c
NC
1107/* Check to see if an immediate can be computed as two seperate immediate
1108 values, added together. We already know that this value cannot be
1109 computed by just one ARM instruction. */
1110
1111static unsigned int
1112validate_immediate_twopart (val, highpart)
1113 unsigned int val;
1114 unsigned int * highpart;
1115{
1116 unsigned int a;
1117 unsigned int i;
1118
1119 for (i = 0; i < 32; i += 2)
1120 if (((a = rotate_left (val, i)) & 0xff) != 0)
1121 {
1122 if (a & 0xff00)
1123 {
1124 if (a & ~ 0xffff)
1125 continue;
1126 * highpart = (a >> 8) | ((i + 24) << 7);
1127 }
1128 else if (a & 0xff0000)
1129 {
1130 if (a & 0xff000000)
1131 continue;
1132
1133 * highpart = (a >> 16) | ((i + 16) << 7);
1134 }
1135 else
1136 {
1137 assert (a & 0xff000000);
1138
1139 * highpart = (a >> 24) | ((i + 8) << 7);
1140 }
1141
1142 return (a & 0xff) | (i << 7);
1143 }
1144
1145 return FAIL;
1146}
1147
252b5132
RH
1148static int
1149validate_offset_imm (val, hwse)
276b1dc2 1150 unsigned int val;
252b5132
RH
1151 int hwse;
1152{
276b1dc2 1153 if ((hwse && val > 255) || val > 4095)
252b5132
RH
1154 return FAIL;
1155 return val;
1156}
1157
1158
1159static void
1160s_req (a)
1161 int a;
1162{
1163 as_bad (_("Invalid syntax for .req directive."));
1164}
1165
1166static void
1167s_bss (ignore)
1168 int ignore;
1169{
1170 /* We don't support putting frags in the BSS segment, we fake it by
1171 marking in_bss, then looking at s_skip for clues?.. */
1172 subseg_set (bss_section, 0);
1173 demand_empty_rest_of_line ();
1174}
1175
1176static void
1177s_even (ignore)
1178 int ignore;
1179{
1180 if (!need_pass_2) /* Never make frag if expect extra pass. */
1181 frag_align (1, 0, 0);
1182
1183 record_alignment (now_seg, 1);
1184
1185 demand_empty_rest_of_line ();
1186}
1187
1188static void
fed881b1
NC
1189s_ltorg (ignored)
1190 int ignored;
252b5132
RH
1191{
1192 int lit_count = 0;
1193 char sym_name[20];
1194
1195 if (current_poolP == NULL)
fed881b1 1196 return;
252b5132
RH
1197
1198 /* Align pool as you have word accesses */
1199 /* Only make a frag if we have to ... */
1200 if (!need_pass_2)
1201 frag_align (2, 0, 0);
1202
1203 record_alignment (now_seg, 2);
1204
252b5132
RH
1205 sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
1206
1207 symbol_locate (current_poolP, sym_name, now_seg,
1208 (valueT) frag_now_fix (), frag_now);
1209 symbol_table_insert (current_poolP);
1210
1211 ARM_SET_THUMB (current_poolP, thumb_mode);
1212
1213#if defined OBJ_COFF || defined OBJ_ELF
1214 ARM_SET_INTERWORK (current_poolP, support_interwork);
1215#endif
1216
1217 while (lit_count < next_literal_pool_place)
1218 /* First output the expression in the instruction to the pool */
1219 emit_expr (&(literals[lit_count++].exp), 4); /* .word */
1220
1221 next_literal_pool_place = 0;
1222 current_poolP = NULL;
1223}
1224
1225static void
1226s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
1227 int unused;
1228{
1229 register int temp;
1230 register long temp_fill;
1231 long max_alignment = 15;
1232
1233 temp = get_absolute_expression ();
1234 if (temp > max_alignment)
1235 as_bad (_("Alignment too large: %d. assumed."), temp = max_alignment);
1236 else if (temp < 0)
1237 {
1238 as_bad (_("Alignment negative. 0 assumed."));
1239 temp = 0;
1240 }
1241
1242 if (*input_line_pointer == ',')
1243 {
1244 input_line_pointer++;
1245 temp_fill = get_absolute_expression ();
1246 }
1247 else
1248 temp_fill = 0;
1249
1250 if (!temp)
1251 temp = 2;
1252
1253 /* Only make a frag if we HAVE to. . . */
1254 if (temp && !need_pass_2)
1255 frag_align (temp, (int) temp_fill, 0);
1256 demand_empty_rest_of_line ();
1257
1258 record_alignment (now_seg, temp);
1259}
1260
1261static void
1262s_force_thumb (ignore)
1263 int ignore;
1264{
1265 /* If we are not already in thumb mode go into it, EVEN if
1266 the target processor does not support thumb instructions.
1267 This is used by gcc/config/arm/lib1funcs.asm for example
1268 to compile interworking support functions even if the
1269 target processor should not support interworking. */
1270
1271 if (! thumb_mode)
1272 {
a64bcdd8 1273 thumb_mode = 2;
252b5132
RH
1274
1275 record_alignment (now_seg, 1);
1276 }
1277
1278 demand_empty_rest_of_line ();
1279}
1280
1281static void
1282s_thumb_func (ignore)
1283 int ignore;
1284{
1285 /* The following label is the name/address of the start of a Thumb function.
1286 We need to know this for the interworking support. */
1287
1288 label_is_thumb_function_name = true;
1289
1290 demand_empty_rest_of_line ();
1291}
1292
fed881b1
NC
1293/* Perform a .set directive, but also mark the alias as
1294 being a thumb function. */
1295
1296static void
1297s_thumb_set (equiv)
1298 int equiv;
1299{
1300 /* XXX the following is a duplicate of the code for s_set() in read.c
1301 We cannot just call that code as we need to get at the symbol that
1302 is created. */
1303 register char * name;
1304 register char delim;
1305 register char * end_name;
1306 register symbolS * symbolP;
1307
1308 /*
1309 * Especial apologies for the random logic:
1310 * this just grew, and could be parsed much more simply!
1311 * Dean in haste.
1312 */
1313 name = input_line_pointer;
1314 delim = get_symbol_end ();
1315 end_name = input_line_pointer;
1316 *end_name = delim;
1317
1318 SKIP_WHITESPACE ();
1319
1320 if (*input_line_pointer != ',')
1321 {
1322 *end_name = 0;
1323 as_bad (_("Expected comma after name \"%s\""), name);
1324 *end_name = delim;
1325 ignore_rest_of_line ();
1326 return;
1327 }
1328
1329 input_line_pointer++;
1330 *end_name = 0;
1331
1332 if (name[0] == '.' && name[1] == '\0')
1333 {
1334 /* XXX - this should not happen to .thumb_set */
1335 abort ();
1336 }
1337
1338 if ((symbolP = symbol_find (name)) == NULL
1339 && (symbolP = md_undefined_symbol (name)) == NULL)
1340 {
1341#ifndef NO_LISTING
1342 /* When doing symbol listings, play games with dummy fragments living
1343 outside the normal fragment chain to record the file and line info
1344 for this symbol. */
1345 if (listing & LISTING_SYMBOLS)
1346 {
1347 extern struct list_info_struct * listing_tail;
1348 fragS * dummy_frag = (fragS *) xmalloc (sizeof(fragS));
1349 memset (dummy_frag, 0, sizeof(fragS));
1350 dummy_frag->fr_type = rs_fill;
1351 dummy_frag->line = listing_tail;
1352 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1353 dummy_frag->fr_symbol = symbolP;
1354 }
1355 else
1356#endif
1357 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1358
1359#ifdef OBJ_COFF
1360 /* "set" symbols are local unless otherwise specified. */
1361 SF_SET_LOCAL (symbolP);
1362#endif /* OBJ_COFF */
1363 } /* make a new symbol */
1364
1365 symbol_table_insert (symbolP);
1366
1367 * end_name = delim;
1368
1369 if (equiv
1370 && S_IS_DEFINED (symbolP)
1371 && S_GET_SEGMENT (symbolP) != reg_section)
1372 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1373
1374 pseudo_set (symbolP);
1375
1376 demand_empty_rest_of_line ();
1377
ae5ad4ad 1378 /* XXX Now we come to the Thumb specific bit of code. */
fed881b1
NC
1379
1380 THUMB_SET_FUNC (symbolP, 1);
1381 ARM_SET_THUMB (symbolP, 1);
92a66162 1382#if defined OBJ_ELF || defined OBJ_COFF
fed881b1 1383 ARM_SET_INTERWORK (symbolP, support_interwork);
325188ec 1384#endif
fed881b1
NC
1385}
1386
1387/* If we change section we must dump the literal pool first. */
1388static void
1389arm_s_text (ignore)
1390 int ignore;
1391{
1392 if (now_seg != text_section)
1393 s_ltorg (0);
1394
df32bc61
NC
1395#ifdef OBJ_ELF
1396 obj_elf_text (ignore);
1397#else
fed881b1 1398 s_text (ignore);
df32bc61 1399#endif
fed881b1
NC
1400}
1401
1402static void
1403arm_s_data (ignore)
1404 int ignore;
1405{
1406 if (flag_readonly_data_in_text)
1407 {
1408 if (now_seg != text_section)
1409 s_ltorg (0);
1410 }
1411 else if (now_seg != data_section)
1412 s_ltorg (0);
1413
df32bc61
NC
1414#ifdef OBJ_ELF
1415 obj_elf_data (ignore);
1416#else
fed881b1 1417 s_data (ignore);
df32bc61 1418#endif
fed881b1
NC
1419}
1420
1421#ifdef OBJ_ELF
1422static void
1423arm_s_section (ignore)
1424 int ignore;
1425{
1426 s_ltorg (0);
1427
1428 obj_elf_section (ignore);
1429}
1430#endif
1431
252b5132
RH
1432static void
1433opcode_select (width)
1434 int width;
1435{
1436 switch (width)
1437 {
1438 case 16:
1439 if (! thumb_mode)
1440 {
1441 if (! (cpu_variant & ARM_THUMB))
1442 as_bad (_("selected processor does not support THUMB opcodes"));
1443 thumb_mode = 1;
1444 /* No need to force the alignment, since we will have been
1445 coming from ARM mode, which is word-aligned. */
1446 record_alignment (now_seg, 1);
1447 }
1448 break;
1449
1450 case 32:
1451 if (thumb_mode)
1452 {
1453 if ((cpu_variant & ARM_ANY) == ARM_THUMB)
1454 as_bad (_("selected processor does not support ARM opcodes"));
1455 thumb_mode = 0;
1456 if (!need_pass_2)
1457 frag_align (2, 0, 0);
1458 record_alignment (now_seg, 1);
1459 }
1460 break;
1461
1462 default:
1463 as_bad (_("invalid instruction size selected (%d)"), width);
1464 }
1465}
1466
1467static void
1468s_arm (ignore)
1469 int ignore;
1470{
1471 opcode_select (32);
1472 demand_empty_rest_of_line ();
1473}
1474
1475static void
1476s_thumb (ignore)
1477 int ignore;
1478{
1479 opcode_select (16);
1480 demand_empty_rest_of_line ();
1481}
1482
1483static void
1484s_code (unused)
1485 int unused;
1486{
1487 register int temp;
1488
1489 temp = get_absolute_expression ();
1490 switch (temp)
1491 {
1492 case 16:
1493 case 32:
1494 opcode_select (temp);
1495 break;
1496
1497 default:
1498 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1499 }
1500}
1501
1502static void
1503end_of_line (str)
1504 char * str;
1505{
ae5ad4ad 1506 skip_whitespace (str);
252b5132 1507
ae5ad4ad 1508 if (* str != '\0')
252b5132
RH
1509 inst.error = _("Garbage following instruction");
1510}
1511
1512static int
1513skip_past_comma (str)
1514 char ** str;
1515{
1516 char *p = *str, c;
1517 int comma = 0;
1518
1519 while ((c = *p) == ' ' || c == ',')
1520 {
1521 p++;
1522 if (c == ',' && comma++)
1523 return FAIL;
1524 }
1525
1526 if (c == '\0')
1527 return FAIL;
1528
1529 *str = p;
1530 return comma ? SUCCESS : FAIL;
1531}
1532
acb56623
JL
1533/* A standard register must be given at this point.
1534 Shift is the place to put it in inst.instruction.
1535 Restores input start point on err.
1536 Returns the reg#, or FAIL. */
252b5132
RH
1537
1538static int
1539reg_required_here (str, shift)
1540 char ** str;
1541 int shift;
1542{
1543 static char buff [128]; /* XXX */
1544 int reg;
1545 char * start = *str;
1546
1547 if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
1548 {
1549 if (shift >= 0)
1550 inst.instruction |= reg << shift;
1551 return reg;
1552 }
1553
1554 /* Restore the start point, we may have got a reg of the wrong class. */
1555 *str = start;
1556
1557 /* In the few cases where we might be able to accept something else
ae5ad4ad 1558 this error can be overridden. */
252b5132
RH
1559 sprintf (buff, _("Register expected, not '%.100s'"), start);
1560 inst.error = buff;
1561
1562 return FAIL;
1563}
1564
1565static int
1566psr_required_here (str, cpsr, spsr)
1567 char ** str;
1568 int cpsr;
1569 int spsr;
1570{
1571 int psr;
1572 char * start = *str;
1573 psr = arm_psr_parse (str);
1574
1575 if (psr == cpsr || psr == spsr)
1576 {
1577 if (psr == spsr)
1578 inst.instruction |= 1 << 22;
1579
1580 return SUCCESS;
1581 }
1582
1583 /* In the few cases where we might be able to accept something else
ae5ad4ad 1584 this error can be overridden. */
252b5132
RH
1585 inst.error = _("<psr(f)> expected");
1586
1587 /* Restore the start point. */
1588 *str = start;
1589 return FAIL;
1590}
1591
1592static int
1593co_proc_number (str)
ae5ad4ad 1594 char ** str;
252b5132
RH
1595{
1596 int processor, pchar;
1597
ae5ad4ad 1598 skip_whitespace (* str);
252b5132
RH
1599
1600 /* The data sheet seems to imply that just a number on its own is valid
1601 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
1602 accept either. */
1603 if (**str == 'p' || **str == 'P')
1604 (*str)++;
1605
1606 pchar = *(*str)++;
1607 if (pchar >= '0' && pchar <= '9')
1608 {
1609 processor = pchar - '0';
1610 if (**str >= '0' && **str <= '9')
1611 {
1612 processor = processor * 10 + *(*str)++ - '0';
1613 if (processor > 15)
1614 {
1615 inst.error = _("Illegal co-processor number");
1616 return FAIL;
1617 }
1618 }
1619 }
1620 else
1621 {
1622 inst.error = _("Bad or missing co-processor number");
1623 return FAIL;
1624 }
1625
1626 inst.instruction |= processor << 8;
1627 return SUCCESS;
1628}
1629
1630static int
1631cp_opc_expr (str, where, length)
1632 char ** str;
1633 int where;
1634 int length;
1635{
1636 expressionS expr;
1637
ae5ad4ad 1638 skip_whitespace (* str);
252b5132
RH
1639
1640 memset (&expr, '\0', sizeof (expr));
1641
1642 if (my_get_expression (&expr, str))
1643 return FAIL;
1644 if (expr.X_op != O_constant)
1645 {
1646 inst.error = _("bad or missing expression");
1647 return FAIL;
1648 }
1649
1650 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
1651 {
1652 inst.error = _("immediate co-processor expression too large");
1653 return FAIL;
1654 }
1655
1656 inst.instruction |= expr.X_add_number << where;
1657 return SUCCESS;
1658}
1659
1660static int
1661cp_reg_required_here (str, where)
1662 char ** str;
1663 int where;
1664{
1665 int reg;
1666 char * start = *str;
1667
1668 if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
1669 {
1670 reg &= 15;
1671 inst.instruction |= reg << where;
1672 return reg;
1673 }
1674
1675 /* In the few cases where we might be able to accept something else
ae5ad4ad 1676 this error can be overridden. */
252b5132
RH
1677 inst.error = _("Co-processor register expected");
1678
ae5ad4ad 1679 /* Restore the start point. */
252b5132
RH
1680 *str = start;
1681 return FAIL;
1682}
1683
1684static int
1685fp_reg_required_here (str, where)
1686 char ** str;
1687 int where;
1688{
1689 int reg;
1690 char * start = *str;
1691
1692 if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
1693 {
1694 reg &= 7;
1695 inst.instruction |= reg << where;
1696 return reg;
1697 }
1698
1699 /* In the few cases where we might be able to accept something else
ae5ad4ad 1700 this error can be overridden. */
252b5132
RH
1701 inst.error = _("Floating point register expected");
1702
ae5ad4ad 1703 /* Restore the start point. */
252b5132
RH
1704 *str = start;
1705 return FAIL;
1706}
1707
1708static int
1709cp_address_offset (str)
1710 char ** str;
1711{
1712 int offset;
1713
ae5ad4ad 1714 skip_whitespace (* str);
252b5132
RH
1715
1716 if (! is_immediate_prefix (**str))
1717 {
1718 inst.error = _("immediate expression expected");
1719 return FAIL;
1720 }
1721
1722 (*str)++;
1723
1724 if (my_get_expression (& inst.reloc.exp, str))
1725 return FAIL;
1726
1727 if (inst.reloc.exp.X_op == O_constant)
1728 {
1729 offset = inst.reloc.exp.X_add_number;
1730
1731 if (offset & 3)
1732 {
1733 inst.error = _("co-processor address must be word aligned");
1734 return FAIL;
1735 }
1736
1737 if (offset > 1023 || offset < -1023)
1738 {
1739 inst.error = _("offset too large");
1740 return FAIL;
1741 }
1742
1743 if (offset >= 0)
1744 inst.instruction |= INDEX_UP;
1745 else
1746 offset = -offset;
1747
1748 inst.instruction |= offset >> 2;
1749 }
1750 else
1751 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
1752
1753 return SUCCESS;
1754}
1755
1756static int
1757cp_address_required_here (str)
1758 char ** str;
1759{
1760 char * p = * str;
1761 int pre_inc = 0;
1762 int write_back = 0;
1763
1764 if (*p == '[')
1765 {
1766 int reg;
1767
1768 p++;
ae5ad4ad 1769 skip_whitespace (p);
252b5132
RH
1770
1771 if ((reg = reg_required_here (& p, 16)) == FAIL)
1772 return FAIL;
1773
ae5ad4ad 1774 skip_whitespace (p);
252b5132
RH
1775
1776 if (*p == ']')
1777 {
1778 p++;
1779
1780 if (skip_past_comma (& p) == SUCCESS)
1781 {
1782 /* [Rn], #expr */
1783 write_back = WRITE_BACK;
1784
1785 if (reg == REG_PC)
1786 {
1787 inst.error = _("pc may not be used in post-increment");
1788 return FAIL;
1789 }
1790
1791 if (cp_address_offset (& p) == FAIL)
1792 return FAIL;
1793 }
1794 else
1795 pre_inc = PRE_INDEX | INDEX_UP;
1796 }
1797 else
1798 {
1799 /* '['Rn, #expr']'[!] */
1800
1801 if (skip_past_comma (& p) == FAIL)
1802 {
1803 inst.error = _("pre-indexed expression expected");
1804 return FAIL;
1805 }
1806
1807 pre_inc = PRE_INDEX;
1808
1809 if (cp_address_offset (& p) == FAIL)
1810 return FAIL;
1811
ae5ad4ad 1812 skip_whitespace (p);
252b5132
RH
1813
1814 if (*p++ != ']')
1815 {
1816 inst.error = _("missing ]");
1817 return FAIL;
1818 }
1819
ae5ad4ad 1820 skip_whitespace (p);
252b5132
RH
1821
1822 if (*p == '!')
1823 {
1824 if (reg == REG_PC)
1825 {
1826 inst.error = _("pc may not be used with write-back");
1827 return FAIL;
1828 }
1829
1830 p++;
1831 write_back = WRITE_BACK;
1832 }
1833 }
1834 }
1835 else
1836 {
1837 if (my_get_expression (&inst.reloc.exp, &p))
1838 return FAIL;
1839
1840 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
1841 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
1842 inst.reloc.pc_rel = 1;
1843 inst.instruction |= (REG_PC << 16);
1844 pre_inc = PRE_INDEX;
1845 }
1846
1847 inst.instruction |= write_back | pre_inc;
1848 *str = p;
1849 return SUCCESS;
1850}
1851
1852static void
1853do_nop (str, flags)
1854 char * str;
1855 unsigned long flags;
1856{
ae5ad4ad
NC
1857 /* Do nothing really. */
1858 inst.instruction |= flags; /* This is pointless. */
252b5132
RH
1859 end_of_line (str);
1860 return;
1861}
1862
1863static void
1864do_mrs (str, flags)
1865 char *str;
1866 unsigned long flags;
1867{
ae5ad4ad
NC
1868 /* Only one syntax. */
1869 skip_whitespace (str);
252b5132
RH
1870
1871 if (reg_required_here (&str, 12) == FAIL)
1872 {
90ca882f 1873 inst.error = BAD_ARGS;
252b5132
RH
1874 return;
1875 }
1876
1877 if (skip_past_comma (&str) == FAIL
1878 || psr_required_here (& str, CPSR_ALL, SPSR_ALL) == FAIL)
1879 {
1880 inst.error = _("<psr> expected");
1881 return;
1882 }
1883
1884 inst.instruction |= flags;
1885 end_of_line (str);
1886 return;
1887}
1888
ae5ad4ad 1889/* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression". */
252b5132
RH
1890static void
1891do_msr (str, flags)
1892 char * str;
1893 unsigned long flags;
1894{
1895 int reg;
1896
ae5ad4ad 1897 skip_whitespace (str);
252b5132
RH
1898
1899 if (psr_required_here (&str, CPSR_ALL, SPSR_ALL) == SUCCESS)
1900 {
1901 inst.instruction |= PSR_ALL;
1902
1903 /* Sytax should be "<psr>, Rm" */
1904 if (skip_past_comma (&str) == FAIL
1905 || (reg = reg_required_here (&str, 0)) == FAIL)
1906 {
90ca882f 1907 inst.error = BAD_ARGS;
252b5132
RH
1908 return;
1909 }
1910 }
1911 else
1912 {
1913 if (psr_required_here (& str, CPSR_FLG, SPSR_FLG) == SUCCESS)
1914 inst.instruction |= PSR_FLAGS;
1915 else if (psr_required_here (& str, CPSR_CTL, SPSR_CTL) == SUCCESS)
1916 inst.instruction |= PSR_CONTROL;
1917 else
1918 {
90ca882f 1919 inst.error = BAD_ARGS;
252b5132
RH
1920 return;
1921 }
1922
1923 if (skip_past_comma (&str) == FAIL)
1924 {
90ca882f 1925 inst.error = BAD_ARGS;
252b5132
RH
1926 return;
1927 }
1928
1929 /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
1930
1931 if ((reg = reg_required_here (& str, 0)) != FAIL)
1932 ;
ae5ad4ad 1933 /* Immediate expression. */
252b5132
RH
1934 else if (is_immediate_prefix (* str))
1935 {
1936 str ++;
1937 inst.error = NULL;
1938
1939 if (my_get_expression (& inst.reloc.exp, & str))
1940 {
1941 inst.error = _("Register or shift expression expected");
1942 return;
1943 }
1944
1945 if (inst.reloc.exp.X_add_symbol)
1946 {
1947 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
1948 inst.reloc.pc_rel = 0;
1949 }
1950 else
1951 {
1952 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
1953 if (value == FAIL)
1954 {
1955 inst.error = _("Invalid constant");
1956 return;
1957 }
1958
1959 inst.instruction |= value;
1960 }
1961
1962 flags |= INST_IMMEDIATE;
1963 }
1964 else
1965 {
1966 inst.error = _("Error: unrecognised syntax for second argument to msr instruction");
1967 return;
1968 }
1969 }
1970
1971 inst.error = NULL;
1972 inst.instruction |= flags;
1973 end_of_line (str);
1974 return;
1975}
1976
1977/* Long Multiply Parser
1978 UMULL RdLo, RdHi, Rm, Rs
1979 SMULL RdLo, RdHi, Rm, Rs
1980 UMLAL RdLo, RdHi, Rm, Rs
1981 SMLAL RdLo, RdHi, Rm, Rs
1982*/
1983static void
1984do_mull (str, flags)
1985 char * str;
1986 unsigned long flags;
1987{
1988 int rdlo, rdhi, rm, rs;
1989
ae5ad4ad
NC
1990 /* Only one format "rdlo, rdhi, rm, rs" */
1991 skip_whitespace (str);
252b5132
RH
1992
1993 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
1994 {
90ca882f 1995 inst.error = BAD_ARGS;
252b5132
RH
1996 return;
1997 }
1998
1999 if (skip_past_comma (&str) == FAIL
2000 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2001 {
90ca882f 2002 inst.error = BAD_ARGS;
252b5132
RH
2003 return;
2004 }
2005
2006 if (skip_past_comma (&str) == FAIL
2007 || (rm = reg_required_here (&str, 0)) == FAIL)
2008 {
90ca882f 2009 inst.error = BAD_ARGS;
252b5132
RH
2010 return;
2011 }
2012
2013 /* rdhi, rdlo and rm must all be different */
2014 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2015 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2016
2017 if (skip_past_comma (&str) == FAIL
2018 || (rs = reg_required_here (&str, 8)) == FAIL)
2019 {
90ca882f 2020 inst.error = BAD_ARGS;
252b5132
RH
2021 return;
2022 }
2023
2024 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2025 {
90ca882f 2026 inst.error = BAD_PC;
252b5132
RH
2027 return;
2028 }
2029
2030 inst.instruction |= flags;
2031 end_of_line (str);
2032 return;
2033}
2034
2035static void
2036do_mul (str, flags)
2037 char * str;
2038 unsigned long flags;
2039{
2040 int rd, rm;
2041
ae5ad4ad
NC
2042 /* Only one format "rd, rm, rs" */
2043 skip_whitespace (str);
252b5132
RH
2044
2045 if ((rd = reg_required_here (&str, 16)) == FAIL)
2046 {
90ca882f 2047 inst.error = BAD_ARGS;
252b5132
RH
2048 return;
2049 }
2050
2051 if (rd == REG_PC)
2052 {
90ca882f 2053 inst.error = BAD_PC;
252b5132
RH
2054 return;
2055 }
2056
2057 if (skip_past_comma (&str) == FAIL
2058 || (rm = reg_required_here (&str, 0)) == FAIL)
2059 {
90ca882f 2060 inst.error = BAD_ARGS;
252b5132
RH
2061 return;
2062 }
2063
2064 if (rm == REG_PC)
2065 {
90ca882f 2066 inst.error = BAD_PC;
252b5132
RH
2067 return;
2068 }
2069
2070 if (rm == rd)
2071 as_tsktsk (_("rd and rm should be different in mul"));
2072
2073 if (skip_past_comma (&str) == FAIL
2074 || (rm = reg_required_here (&str, 8)) == FAIL)
2075 {
90ca882f 2076 inst.error = BAD_ARGS;
252b5132
RH
2077 return;
2078 }
2079
2080 if (rm == REG_PC)
2081 {
90ca882f 2082 inst.error = BAD_PC;
252b5132
RH
2083 return;
2084 }
2085
2086 inst.instruction |= flags;
2087 end_of_line (str);
2088 return;
2089}
2090
2091static void
2092do_mla (str, flags)
2093 char * str;
2094 unsigned long flags;
2095{
2096 int rd, rm;
2097
ae5ad4ad
NC
2098 /* Only one format "rd, rm, rs, rn" */
2099 skip_whitespace (str);
252b5132
RH
2100
2101 if ((rd = reg_required_here (&str, 16)) == FAIL)
2102 {
90ca882f 2103 inst.error = BAD_ARGS;
252b5132
RH
2104 return;
2105 }
2106
2107 if (rd == REG_PC)
2108 {
90ca882f 2109 inst.error = BAD_PC;
252b5132
RH
2110 return;
2111 }
2112
2113 if (skip_past_comma (&str) == FAIL
2114 || (rm = reg_required_here (&str, 0)) == FAIL)
2115 {
90ca882f 2116 inst.error = BAD_ARGS;
252b5132
RH
2117 return;
2118 }
2119
2120 if (rm == REG_PC)
2121 {
90ca882f 2122 inst.error = BAD_PC;
252b5132
RH
2123 return;
2124 }
2125
2126 if (rm == rd)
2127 as_tsktsk (_("rd and rm should be different in mla"));
2128
2129 if (skip_past_comma (&str) == FAIL
2130 || (rd = reg_required_here (&str, 8)) == FAIL
2131 || skip_past_comma (&str) == FAIL
2132 || (rm = reg_required_here (&str, 12)) == FAIL)
2133 {
90ca882f 2134 inst.error = BAD_ARGS;
252b5132
RH
2135 return;
2136 }
2137
2138 if (rd == REG_PC || rm == REG_PC)
2139 {
90ca882f 2140 inst.error = BAD_PC;
252b5132
RH
2141 return;
2142 }
2143
2144 inst.instruction |= flags;
2145 end_of_line (str);
2146 return;
2147}
2148
2149/* Returns the index into fp_values of a floating point number, or -1 if
2150 not in the table. */
2151static int
2152my_get_float_expression (str)
2153 char ** str;
2154{
2155 LITTLENUM_TYPE words[MAX_LITTLENUMS];
2156 char * save_in;
2157 expressionS exp;
2158 int i;
2159 int j;
2160
2161 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
2162 /* Look for a raw floating point number */
2163 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
2164 && (is_end_of_line [(int)(*save_in)] || *save_in == '\0'))
2165 {
2166 for (i = 0; i < NUM_FLOAT_VALS; i++)
2167 {
2168 for (j = 0; j < MAX_LITTLENUMS; j++)
2169 {
2170 if (words[j] != fp_values[i][j])
2171 break;
2172 }
2173
2174 if (j == MAX_LITTLENUMS)
2175 {
2176 *str = save_in;
2177 return i;
2178 }
2179 }
2180 }
2181
2182 /* Try and parse a more complex expression, this will probably fail
2183 unless the code uses a floating point prefix (eg "0f") */
2184 save_in = input_line_pointer;
2185 input_line_pointer = *str;
2186 if (expression (&exp) == absolute_section
2187 && exp.X_op == O_big
2188 && exp.X_add_number < 0)
2189 {
2190 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
2191 Ditto for 15. */
2192 if (gen_to_words (words, 5, (long)15) == 0)
2193 {
2194 for (i = 0; i < NUM_FLOAT_VALS; i++)
2195 {
2196 for (j = 0; j < MAX_LITTLENUMS; j++)
2197 {
2198 if (words[j] != fp_values[i][j])
2199 break;
2200 }
2201
2202 if (j == MAX_LITTLENUMS)
2203 {
2204 *str = input_line_pointer;
2205 input_line_pointer = save_in;
2206 return i;
2207 }
2208 }
2209 }
2210 }
2211
2212 *str = input_line_pointer;
2213 input_line_pointer = save_in;
2214 return -1;
2215}
2216
2217/* Return true if anything in the expression is a bignum */
2218static int
2219walk_no_bignums (sp)
2220 symbolS * sp;
2221{
174419c1 2222 if (symbol_get_value_expression (sp)->X_op == O_big)
252b5132
RH
2223 return 1;
2224
174419c1 2225 if (symbol_get_value_expression (sp)->X_add_symbol)
252b5132 2226 {
174419c1
ILT
2227 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
2228 || (symbol_get_value_expression (sp)->X_op_symbol
2229 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
252b5132
RH
2230 }
2231
2232 return 0;
2233}
2234
2235static int
2236my_get_expression (ep, str)
2237 expressionS * ep;
2238 char ** str;
2239{
2240 char * save_in;
2241 segT seg;
2242
2243 save_in = input_line_pointer;
2244 input_line_pointer = *str;
2245 seg = expression (ep);
2246
2247#ifdef OBJ_AOUT
2248 if (seg != absolute_section
2249 && seg != text_section
2250 && seg != data_section
2251 && seg != bss_section
2252 && seg != undefined_section)
2253 {
2254 inst.error = _("bad_segment");
2255 *str = input_line_pointer;
2256 input_line_pointer = save_in;
2257 return 1;
2258 }
2259#endif
2260
2261 /* Get rid of any bignums now, so that we don't generate an error for which
2262 we can't establish a line number later on. Big numbers are never valid
2263 in instructions, which is where this routine is always called. */
2264 if (ep->X_op == O_big
2265 || (ep->X_add_symbol
2266 && (walk_no_bignums (ep->X_add_symbol)
2267 || (ep->X_op_symbol
2268 && walk_no_bignums (ep->X_op_symbol)))))
2269 {
2270 inst.error = _("Invalid constant");
2271 *str = input_line_pointer;
2272 input_line_pointer = save_in;
2273 return 1;
2274 }
2275
2276 *str = input_line_pointer;
2277 input_line_pointer = save_in;
2278 return 0;
2279}
2280
2281/* unrestrict should be one if <shift> <register> is permitted for this
2282 instruction */
2283
2284static int
2285decode_shift (str, unrestrict)
2286 char ** str;
2287 int unrestrict;
2288{
2289 struct asm_shift * shft;
2290 char * p;
2291 char c;
2292
ae5ad4ad 2293 skip_whitespace (* str);
252b5132
RH
2294
2295 for (p = *str; isalpha (*p); p++)
2296 ;
2297
2298 if (p == *str)
2299 {
2300 inst.error = _("Shift expression expected");
2301 return FAIL;
2302 }
2303
2304 c = *p;
2305 *p = '\0';
2306 shft = (struct asm_shift *) hash_find (arm_shift_hsh, *str);
2307 *p = c;
2308 if (shft)
2309 {
2310 if (!strncmp (*str, "rrx", 3)
2311 || !strncmp (*str, "RRX", 3))
2312 {
2313 *str = p;
2314 inst.instruction |= shft->value;
2315 return SUCCESS;
2316 }
2317
ae5ad4ad
NC
2318 skip_whitespace (p);
2319
252b5132
RH
2320 if (unrestrict && reg_required_here (&p, 8) != FAIL)
2321 {
2322 inst.instruction |= shft->value | SHIFT_BY_REG;
2323 *str = p;
2324 return SUCCESS;
2325 }
2326 else if (is_immediate_prefix (* p))
2327 {
2328 inst.error = NULL;
2329 p++;
2330 if (my_get_expression (&inst.reloc.exp, &p))
2331 return FAIL;
2332
2333 /* Validate some simple #expressions */
2334 if (inst.reloc.exp.X_op == O_constant)
2335 {
2336 unsigned num = inst.reloc.exp.X_add_number;
2337
2338 /* Reject operations greater than 32, or lsl #32 */
2339 if (num > 32 || (num == 32 && shft->value == 0))
2340 {
2341 inst.error = _("Invalid immediate shift");
2342 return FAIL;
2343 }
2344
2345 /* Shifts of zero should be converted to lsl (which is zero)*/
2346 if (num == 0)
2347 {
2348 *str = p;
2349 return SUCCESS;
2350 }
2351
2352 /* Shifts of 32 are encoded as 0, for those shifts that
2353 support it. */
2354 if (num == 32)
2355 num = 0;
2356
2357 inst.instruction |= (num << 7) | shft->value;
2358 *str = p;
2359 return SUCCESS;
2360 }
2361
2362 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
2363 inst.reloc.pc_rel = 0;
2364 inst.instruction |= shft->value;
2365 *str = p;
2366 return SUCCESS;
2367 }
2368 else
2369 {
2370 inst.error = unrestrict ? _("shift requires register or #expression")
2371 : _("shift requires #expression");
2372 *str = p;
2373 return FAIL;
2374 }
2375 }
2376
2377 inst.error = _("Shift expression expected");
2378 return FAIL;
2379}
2380
2381/* Do those data_ops which can take a negative immediate constant */
2382/* by altering the instuction. A bit of a hack really */
2383/* MOV <-> MVN
2384 AND <-> BIC
2385 ADC <-> SBC
2386 by inverting the second operand, and
2387 ADD <-> SUB
2388 CMP <-> CMN
2389 by negating the second operand.
2390*/
2391static int
2392negate_data_op (instruction, value)
2393 unsigned long * instruction;
2394 unsigned long value;
2395{
2396 int op, new_inst;
2397 unsigned long negated, inverted;
2398
2399 negated = validate_immediate (-value);
2400 inverted = validate_immediate (~value);
2401
2402 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
2403 switch (op)
2404 {
2405 /* First negates */
2406 case OPCODE_SUB: /* ADD <-> SUB */
2407 new_inst = OPCODE_ADD;
2408 value = negated;
2409 break;
2410
2411 case OPCODE_ADD:
2412 new_inst = OPCODE_SUB;
2413 value = negated;
2414 break;
2415
2416 case OPCODE_CMP: /* CMP <-> CMN */
2417 new_inst = OPCODE_CMN;
2418 value = negated;
2419 break;
2420
2421 case OPCODE_CMN:
2422 new_inst = OPCODE_CMP;
2423 value = negated;
2424 break;
2425
2426 /* Now Inverted ops */
2427 case OPCODE_MOV: /* MOV <-> MVN */
2428 new_inst = OPCODE_MVN;
2429 value = inverted;
2430 break;
2431
2432 case OPCODE_MVN:
2433 new_inst = OPCODE_MOV;
2434 value = inverted;
2435 break;
2436
2437 case OPCODE_AND: /* AND <-> BIC */
2438 new_inst = OPCODE_BIC;
2439 value = inverted;
2440 break;
2441
2442 case OPCODE_BIC:
2443 new_inst = OPCODE_AND;
2444 value = inverted;
2445 break;
2446
2447 case OPCODE_ADC: /* ADC <-> SBC */
2448 new_inst = OPCODE_SBC;
2449 value = inverted;
2450 break;
2451
2452 case OPCODE_SBC:
2453 new_inst = OPCODE_ADC;
2454 value = inverted;
2455 break;
2456
2457 /* We cannot do anything */
2458 default:
2459 return FAIL;
2460 }
2461
2462 if (value == FAIL)
2463 return FAIL;
2464
2465 *instruction &= OPCODE_MASK;
2466 *instruction |= new_inst << DATA_OP_SHIFT;
2467 return value;
2468}
2469
2470static int
2471data_op2 (str)
2472 char ** str;
2473{
2474 int value;
2475 expressionS expr;
2476
ae5ad4ad 2477 skip_whitespace (* str);
252b5132
RH
2478
2479 if (reg_required_here (str, 0) != FAIL)
2480 {
2481 if (skip_past_comma (str) == SUCCESS)
ae5ad4ad
NC
2482 /* Shift operation on register. */
2483 return decode_shift (str, NO_SHIFT_RESTRICT);
2484
252b5132
RH
2485 return SUCCESS;
2486 }
2487 else
2488 {
2489 /* Immediate expression */
2490 if (is_immediate_prefix (**str))
2491 {
2492 (*str)++;
2493 inst.error = NULL;
ae5ad4ad 2494
252b5132
RH
2495 if (my_get_expression (&inst.reloc.exp, str))
2496 return FAIL;
2497
2498 if (inst.reloc.exp.X_add_symbol)
2499 {
2500 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2501 inst.reloc.pc_rel = 0;
2502 }
2503 else
2504 {
2505 if (skip_past_comma (str) == SUCCESS)
2506 {
2507 /* #x, y -- ie explicit rotation by Y */
2508 if (my_get_expression (&expr, str))
2509 return FAIL;
2510
2511 if (expr.X_op != O_constant)
2512 {
2513 inst.error = _("Constant expression expected");
2514 return FAIL;
2515 }
2516
2517 /* Rotate must be a multiple of 2 */
2518 if (((unsigned) expr.X_add_number) > 30
2519 || (expr.X_add_number & 1) != 0
2520 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
2521 {
2522 inst.error = _("Invalid constant");
2523 return FAIL;
2524 }
2525 inst.instruction |= INST_IMMEDIATE;
2526 inst.instruction |= inst.reloc.exp.X_add_number;
2527 inst.instruction |= expr.X_add_number << 7;
2528 return SUCCESS;
2529 }
2530
2531 /* Implicit rotation, select a suitable one */
2532 value = validate_immediate (inst.reloc.exp.X_add_number);
2533
2534 if (value == FAIL)
2535 {
2536 /* Can't be done, perhaps the code reads something like
2537 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be ok */
2538 if ((value = negate_data_op (&inst.instruction,
2539 inst.reloc.exp.X_add_number))
2540 == FAIL)
2541 {
2542 inst.error = _("Invalid constant");
2543 return FAIL;
2544 }
2545 }
2546
2547 inst.instruction |= value;
2548 }
2549
2550 inst.instruction |= INST_IMMEDIATE;
2551 return SUCCESS;
2552 }
2553
2554 (*str)++;
2555 inst.error = _("Register or shift expression expected");
2556 return FAIL;
2557 }
2558}
2559
2560static int
2561fp_op2 (str)
2562 char ** str;
2563{
ae5ad4ad 2564 skip_whitespace (* str);
252b5132
RH
2565
2566 if (fp_reg_required_here (str, 0) != FAIL)
2567 return SUCCESS;
2568 else
2569 {
2570 /* Immediate expression */
2571 if (*((*str)++) == '#')
2572 {
2573 int i;
2574
2575 inst.error = NULL;
276b1dc2 2576
ae5ad4ad 2577 skip_whitespace (* str);
252b5132
RH
2578
2579 /* First try and match exact strings, this is to guarantee that
2580 some formats will work even for cross assembly */
2581
2582 for (i = 0; fp_const[i]; i++)
2583 {
2584 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
2585 {
2586 char *start = *str;
2587
2588 *str += strlen (fp_const[i]);
2589 if (is_end_of_line[(int)**str] || **str == '\0')
2590 {
2591 inst.instruction |= i + 8;
2592 return SUCCESS;
2593 }
2594 *str = start;
2595 }
2596 }
2597
2598 /* Just because we didn't get a match doesn't mean that the
2599 constant isn't valid, just that it is in a format that we
2600 don't automatically recognize. Try parsing it with
2601 the standard expression routines. */
2602 if ((i = my_get_float_expression (str)) >= 0)
2603 {
2604 inst.instruction |= i + 8;
2605 return SUCCESS;
2606 }
2607
2608 inst.error = _("Invalid floating point immediate expression");
2609 return FAIL;
2610 }
2611 inst.error = _("Floating point register or immediate expression expected");
2612 return FAIL;
2613 }
2614}
2615
2616static void
2617do_arit (str, flags)
2618 char * str;
2619 unsigned long flags;
2620{
ae5ad4ad 2621 skip_whitespace (str);
252b5132
RH
2622
2623 if (reg_required_here (&str, 12) == FAIL
2624 || skip_past_comma (&str) == FAIL
2625 || reg_required_here (&str, 16) == FAIL
2626 || skip_past_comma (&str) == FAIL
2627 || data_op2 (&str) == FAIL)
2628 {
2629 if (!inst.error)
90ca882f 2630 inst.error = BAD_ARGS;
252b5132
RH
2631 return;
2632 }
2633
2634 inst.instruction |= flags;
2635 end_of_line (str);
2636 return;
2637}
2638
2639static void
2640do_adr (str, flags)
2641 char * str;
2642 unsigned long flags;
2643{
2644 /* This is a pseudo-op of the form "adr rd, label" to be converted
2645 into a relative address of the form "add rd, pc, #label-.-8" */
2646
ae5ad4ad 2647 skip_whitespace (str);
252b5132
RH
2648
2649 if (reg_required_here (&str, 12) == FAIL
2650 || skip_past_comma (&str) == FAIL
2651 || my_get_expression (&inst.reloc.exp, &str))
2652 {
2653 if (!inst.error)
90ca882f 2654 inst.error = BAD_ARGS;
252b5132
RH
2655 return;
2656 }
2657 /* Frag hacking will turn this into a sub instruction if the offset turns
2658 out to be negative. */
2659 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2660 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
2661 inst.reloc.pc_rel = 1;
2662 inst.instruction |= flags;
2663 end_of_line (str);
2664 return;
2665}
2666
49a5575c
NC
2667static void
2668do_adrl (str, flags)
2669 char * str;
2670 unsigned long flags;
2671{
2672 /* This is a pseudo-op of the form "adrl rd, label" to be converted
2673 into a relative address of the form:
2674 add rd, pc, #low(label-.-8)"
2675 add rd, rd, #high(label-.-8)" */
2676
ae5ad4ad 2677 skip_whitespace (str);
49a5575c
NC
2678
2679 if (reg_required_here (& str, 12) == FAIL
2680 || skip_past_comma (& str) == FAIL
2681 || my_get_expression (& inst.reloc.exp, & str))
2682 {
2683 if (!inst.error)
90ca882f 2684 inst.error = BAD_ARGS;
49a5575c
NC
2685 return;
2686 }
2687
2688 end_of_line (str);
2689
2690 /* Frag hacking will turn this into a sub instruction if the offset turns
2691 out to be negative. */
2692 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
2693 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
2694 inst.reloc.pc_rel = 1;
2695 inst.instruction |= flags;
2696 inst.size = INSN_SIZE * 2;
2697
2698 return;
2699}
2700
252b5132
RH
2701static void
2702do_cmp (str, flags)
2703 char * str;
2704 unsigned long flags;
2705{
ae5ad4ad 2706 skip_whitespace (str);
252b5132
RH
2707
2708 if (reg_required_here (&str, 16) == FAIL)
2709 {
2710 if (!inst.error)
90ca882f 2711 inst.error = BAD_ARGS;
252b5132
RH
2712 return;
2713 }
2714
2715 if (skip_past_comma (&str) == FAIL
2716 || data_op2 (&str) == FAIL)
2717 {
2718 if (!inst.error)
90ca882f 2719 inst.error = BAD_ARGS;
252b5132
RH
2720 return;
2721 }
2722
2723 inst.instruction |= flags;
2724 if ((flags & 0x0000f000) == 0)
2725 inst.instruction |= CONDS_BIT;
2726
2727 end_of_line (str);
2728 return;
2729}
2730
2731static void
2732do_mov (str, flags)
2733 char * str;
2734 unsigned long flags;
2735{
ae5ad4ad 2736 skip_whitespace (str);
252b5132
RH
2737
2738 if (reg_required_here (&str, 12) == FAIL)
2739 {
2740 if (!inst.error)
90ca882f 2741 inst.error = BAD_ARGS;
252b5132
RH
2742 return;
2743 }
2744
2745 if (skip_past_comma (&str) == FAIL
2746 || data_op2 (&str) == FAIL)
2747 {
2748 if (!inst.error)
90ca882f 2749 inst.error = BAD_ARGS;
252b5132
RH
2750 return;
2751 }
2752
2753 inst.instruction |= flags;
2754 end_of_line (str);
2755 return;
2756}
2757
2758static int
2759ldst_extend (str, hwse)
2760 char ** str;
2761 int hwse;
2762{
2763 int add = INDEX_UP;
2764
2765 switch (**str)
2766 {
2767 case '#':
2768 case '$':
2769 (*str)++;
2770 if (my_get_expression (& inst.reloc.exp, str))
2771 return FAIL;
2772
2773 if (inst.reloc.exp.X_op == O_constant)
2774 {
2775 int value = inst.reloc.exp.X_add_number;
2776
2777 if ((hwse && (value < -255 || value > 255))
2778 || (value < -4095 || value > 4095))
2779 {
2780 inst.error = _("address offset too large");
2781 return FAIL;
2782 }
2783
2784 if (value < 0)
2785 {
2786 value = -value;
2787 add = 0;
2788 }
2789
2790 /* Halfword and signextension instructions have the
2791 immediate value split across bits 11..8 and bits 3..0 */
2792 if (hwse)
3d103319 2793 inst.instruction |= add | HWOFFSET_IMM | ((value >> 4) << 8) | (value & 0xF);
252b5132
RH
2794 else
2795 inst.instruction |= add | value;
2796 }
2797 else
2798 {
2799 if (hwse)
2800 {
2801 inst.instruction |= HWOFFSET_IMM;
2802 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2803 }
2804 else
2805 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
2806 inst.reloc.pc_rel = 0;
2807 }
2808 return SUCCESS;
2809
2810 case '-':
2811 add = 0; /* and fall through */
2812 case '+':
2813 (*str)++; /* and fall through */
2814 default:
2815 if (reg_required_here (str, 0) == FAIL)
2816 return FAIL;
2817
2818 if (hwse)
2819 inst.instruction |= add;
2820 else
2821 {
2822 inst.instruction |= add | OFFSET_REG;
2823 if (skip_past_comma (str) == SUCCESS)
2824 return decode_shift (str, SHIFT_RESTRICT);
2825 }
2826
2827 return SUCCESS;
2828 }
2829}
2830
2831static void
2832do_ldst (str, flags)
2833 char * str;
2834 unsigned long flags;
2835{
2836 int halfword = 0;
2837 int pre_inc = 0;
2838 int conflict_reg;
2839 int value;
2840
2841 /* This is not ideal, but it is the simplest way of dealing with the
2842 ARM7T halfword instructions (since they use a different
2843 encoding, but the same mnemonic): */
3d103319
ILT
2844 halfword = (flags & 0x80000000) != 0;
2845 if (halfword)
252b5132
RH
2846 {
2847 /* This is actually a load/store of a halfword, or a
2848 signed-extension load */
2849 if ((cpu_variant & ARM_HALFWORD) == 0)
2850 {
2851 inst.error
2852 = _("Processor does not support halfwords or signed bytes");
2853 return;
2854 }
2855
2856 inst.instruction = (inst.instruction & COND_MASK)
2857 | (flags & ~COND_MASK);
2858
2859 flags = 0;
2860 }
2861
ae5ad4ad 2862 skip_whitespace (str);
252b5132
RH
2863
2864 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
2865 {
2866 if (!inst.error)
90ca882f 2867 inst.error = BAD_ARGS;
252b5132
RH
2868 return;
2869 }
2870
2871 if (skip_past_comma (& str) == FAIL)
2872 {
2873 inst.error = _("Address expected");
2874 return;
2875 }
2876
2877 if (*str == '[')
2878 {
2879 int reg;
2880
2881 str++;
276b1dc2 2882
ae5ad4ad 2883 skip_whitespace (str);
252b5132
RH
2884
2885 if ((reg = reg_required_here (&str, 16)) == FAIL)
2886 return;
2887
11450271
NC
2888 /* Conflicts can occur on stores as well as loads. */
2889 conflict_reg = (conflict_reg == reg);
252b5132 2890
ae5ad4ad 2891 skip_whitespace (str);
252b5132
RH
2892
2893 if (*str == ']')
2894 {
11450271
NC
2895 str ++;
2896
252b5132
RH
2897 if (skip_past_comma (&str) == SUCCESS)
2898 {
2899 /* [Rn],... (post inc) */
2900 if (ldst_extend (&str, halfword) == FAIL)
2901 return;
2902 if (conflict_reg)
11450271
NC
2903 as_warn (_("%s register same as write-back base"),
2904 (inst.instruction & LOAD_BIT) ? _("destination") : _("source") );
252b5132
RH
2905 }
2906 else
2907 {
2908 /* [Rn] */
2909 if (halfword)
2910 inst.instruction |= HWOFFSET_IMM;
2911
ae5ad4ad 2912 skip_whitespace (str);
252b5132
RH
2913
2914 if (*str == '!')
2915 {
2916 if (conflict_reg)
11450271
NC
2917 as_warn (_("%s register same as write-back base"),
2918 (inst.instruction & LOAD_BIT) ? _("destination") : _("source") );
252b5132
RH
2919 str++;
2920 inst.instruction |= WRITE_BACK;
2921 }
2922
2923 flags |= INDEX_UP;
2924 if (! (flags & TRANS_BIT))
2925 pre_inc = 1;
2926 }
2927 }
2928 else
2929 {
2930 /* [Rn,...] */
2931 if (skip_past_comma (&str) == FAIL)
2932 {
2933 inst.error = _("pre-indexed expression expected");
2934 return;
2935 }
2936
2937 pre_inc = 1;
2938 if (ldst_extend (&str, halfword) == FAIL)
2939 return;
2940
ae5ad4ad 2941 skip_whitespace (str);
252b5132
RH
2942
2943 if (*str++ != ']')
2944 {
2945 inst.error = _("missing ]");
2946 return;
2947 }
2948
ae5ad4ad 2949 skip_whitespace (str);
252b5132
RH
2950
2951 if (*str == '!')
2952 {
2953 if (conflict_reg)
11450271
NC
2954 as_warn (_("%s register same as write-back base"),
2955 (inst.instruction & LOAD_BIT) ? _("destination") : _("source") );
252b5132
RH
2956 str++;
2957 inst.instruction |= WRITE_BACK;
2958 }
2959 }
2960 }
2961 else if (*str == '=')
2962 {
2963 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
2964 str++;
2965
ae5ad4ad 2966 skip_whitespace (str);
252b5132
RH
2967
2968 if (my_get_expression (&inst.reloc.exp, &str))
2969 return;
2970
2971 if (inst.reloc.exp.X_op != O_constant
2972 && inst.reloc.exp.X_op != O_symbol)
2973 {
2974 inst.error = _("Constant expression expected");
2975 return;
2976 }
2977
2978 if (inst.reloc.exp.X_op == O_constant
2979 && (value = validate_immediate(inst.reloc.exp.X_add_number)) != FAIL)
2980 {
2981 /* This can be done with a mov instruction */
2982 inst.instruction &= LITERAL_MASK;
2983 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
2984 inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
2985 end_of_line(str);
2986 return;
2987 }
2988 else
2989 {
2990 /* Insert into literal pool */
2991 if (add_to_lit_pool () == FAIL)
2992 {
2993 if (!inst.error)
2994 inst.error = _("literal pool insertion failed");
2995 return;
2996 }
2997
2998 /* Change the instruction exp to point to the pool */
2999 if (halfword)
3000 {
3001 inst.instruction |= HWOFFSET_IMM;
3002 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
3003 }
3004 else
3005 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
3006 inst.reloc.pc_rel = 1;
3007 inst.instruction |= (REG_PC << 16);
3008 pre_inc = 1;
3009 }
3010 }
3011 else
3012 {
3013 if (my_get_expression (&inst.reloc.exp, &str))
3014 return;
3015
3016 if (halfword)
3017 {
3018 inst.instruction |= HWOFFSET_IMM;
3019 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3020 }
3021 else
3022 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
3023 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
3024 inst.reloc.pc_rel = 1;
3025 inst.instruction |= (REG_PC << 16);
3026 pre_inc = 1;
3027 }
3028
3029 if (pre_inc && (flags & TRANS_BIT))
3030 inst.error = _("Pre-increment instruction with translate");
3031
3032 inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0);
3033 end_of_line (str);
3034 return;
3035}
3036
3037static long
3038reg_list (strp)
3039 char ** strp;
3040{
3041 char * str = *strp;
3042 long range = 0;
3043 int another_range;
3044
3045 /* We come back here if we get ranges concatenated by '+' or '|' */
3046 do
3047 {
3048 another_range = 0;
3049
3050 if (*str == '{')
3051 {
3052 int in_range = 0;
3053 int cur_reg = -1;
3054
3055 str++;
3056 do
3057 {
3058 int reg;
3059
ae5ad4ad 3060 skip_whitespace (str);
252b5132
RH
3061
3062 if ((reg = reg_required_here (& str, -1)) == FAIL)
3063 return FAIL;
3064
3065 if (in_range)
3066 {
3067 int i;
3068
3069 if (reg <= cur_reg)
3070 {
3071 inst.error = _("Bad range in register list");
3072 return FAIL;
3073 }
3074
3075 for (i = cur_reg + 1; i < reg; i++)
3076 {
3077 if (range & (1 << i))
3078 as_tsktsk
3079 (_("Warning: Duplicated register (r%d) in register list"),
3080 i);
3081 else
3082 range |= 1 << i;
3083 }
3084 in_range = 0;
3085 }
3086
3087 if (range & (1 << reg))
3088 as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
3089 reg);
3090 else if (reg <= cur_reg)
3091 as_tsktsk (_("Warning: Register range not in ascending order"));
3092
3093 range |= 1 << reg;
3094 cur_reg = reg;
3095 } while (skip_past_comma (&str) != FAIL
3096 || (in_range = 1, *str++ == '-'));
3097 str--;
ae5ad4ad 3098 skip_whitespace (str);
252b5132
RH
3099
3100 if (*str++ != '}')
3101 {
3102 inst.error = _("Missing `}'");
3103 return FAIL;
3104 }
3105 }
3106 else
3107 {
3108 expressionS expr;
3109
3110 if (my_get_expression (&expr, &str))
3111 return FAIL;
3112
3113 if (expr.X_op == O_constant)
3114 {
3115 if (expr.X_add_number
3116 != (expr.X_add_number & 0x0000ffff))
3117 {
3118 inst.error = _("invalid register mask");
3119 return FAIL;
3120 }
3121
3122 if ((range & expr.X_add_number) != 0)
3123 {
3124 int regno = range & expr.X_add_number;
3125
3126 regno &= -regno;
3127 regno = (1 << regno) - 1;
3128 as_tsktsk
3129 (_("Warning: Duplicated register (r%d) in register list"),
3130 regno);
3131 }
3132
3133 range |= expr.X_add_number;
3134 }
3135 else
3136 {
3137 if (inst.reloc.type != 0)
3138 {
3139 inst.error = _("expression too complex");
3140 return FAIL;
3141 }
3142
3143 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
3144 inst.reloc.type = BFD_RELOC_ARM_MULTI;
3145 inst.reloc.pc_rel = 0;
3146 }
3147 }
3148
ae5ad4ad 3149 skip_whitespace (str);
252b5132
RH
3150
3151 if (*str == '|' || *str == '+')
3152 {
3153 str++;
3154 another_range = 1;
3155 }
3156 } while (another_range);
3157
3158 *strp = str;
3159 return range;
3160}
3161
3162static void
3163do_ldmstm (str, flags)
3164 char * str;
3165 unsigned long flags;
3166{
3167 int base_reg;
3168 long range;
3169
ae5ad4ad 3170 skip_whitespace (str);
252b5132
RH
3171
3172 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
3173 return;
3174
3175 if (base_reg == REG_PC)
3176 {
3177 inst.error = _("r15 not allowed as base register");
3178 return;
3179 }
3180
ae5ad4ad
NC
3181 skip_whitespace (str);
3182
252b5132
RH
3183 if (*str == '!')
3184 {
3185 flags |= WRITE_BACK;
3186 str++;
3187 }
3188
3189 if (skip_past_comma (&str) == FAIL
3190 || (range = reg_list (&str)) == FAIL)
3191 {
3192 if (! inst.error)
90ca882f 3193 inst.error = BAD_ARGS;
252b5132
RH
3194 return;
3195 }
3196
3197 if (*str == '^')
3198 {
3199 str++;
913f265c 3200 flags |= LDM_TYPE_2_OR_3;
252b5132
RH
3201 }
3202
3203 inst.instruction |= flags | range;
3204 end_of_line (str);
3205 return;
3206}
3207
3208static void
3209do_swi (str, flags)
3210 char * str;
3211 unsigned long flags;
3212{
ae5ad4ad 3213 skip_whitespace (str);
252b5132
RH
3214
3215 /* Allow optional leading '#'. */
3216 if (is_immediate_prefix (*str))
3217 str++;
3218
3219 if (my_get_expression (& inst.reloc.exp, & str))
3220 return;
3221
3222 inst.reloc.type = BFD_RELOC_ARM_SWI;
3223 inst.reloc.pc_rel = 0;
3224 inst.instruction |= flags;
3225
3226 end_of_line (str);
3227
3228 return;
3229}
3230
3231static void
3232do_swap (str, flags)
3233 char * str;
3234 unsigned long flags;
3235{
3236 int reg;
3237
ae5ad4ad 3238 skip_whitespace (str);
252b5132
RH
3239
3240 if ((reg = reg_required_here (&str, 12)) == FAIL)
3241 return;
3242
3243 if (reg == REG_PC)
3244 {
3245 inst.error = _("r15 not allowed in swap");
3246 return;
3247 }
3248
3249 if (skip_past_comma (&str) == FAIL
3250 || (reg = reg_required_here (&str, 0)) == FAIL)
3251 {
3252 if (!inst.error)
90ca882f 3253 inst.error = BAD_ARGS;
252b5132
RH
3254 return;
3255 }
3256
3257 if (reg == REG_PC)
3258 {
3259 inst.error = _("r15 not allowed in swap");
3260 return;
3261 }
3262
3263 if (skip_past_comma (&str) == FAIL
3264 || *str++ != '[')
3265 {
90ca882f 3266 inst.error = BAD_ARGS;
252b5132
RH
3267 return;
3268 }
3269
ae5ad4ad 3270 skip_whitespace (str);
252b5132
RH
3271
3272 if ((reg = reg_required_here (&str, 16)) == FAIL)
3273 return;
3274
3275 if (reg == REG_PC)
3276 {
90ca882f 3277 inst.error = BAD_PC;
252b5132
RH
3278 return;
3279 }
3280
ae5ad4ad 3281 skip_whitespace (str);
252b5132
RH
3282
3283 if (*str++ != ']')
3284 {
3285 inst.error = _("missing ]");
3286 return;
3287 }
3288
3289 inst.instruction |= flags;
3290 end_of_line (str);
3291 return;
3292}
3293
3294static void
3295do_branch (str, flags)
3296 char * str;
3297 unsigned long flags;
3298{
3299 if (my_get_expression (&inst.reloc.exp, &str))
3300 return;
3301
3302#ifdef OBJ_ELF
3303 {
3304 char * save_in;
3305
3306 /* ScottB: February 5, 1998 */
3307 /* Check to see of PLT32 reloc required for the instruction. */
3308
3309 /* arm_parse_reloc() works on input_line_pointer.
3310 We actually want to parse the operands to the branch instruction
3311 passed in 'str'. Save the input pointer and restore it later. */
3312 save_in = input_line_pointer;
3313 input_line_pointer = str;
3314 if (inst.reloc.exp.X_op == O_symbol
3315 && *str == '('
3316 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
3317 {
3318 inst.reloc.type = BFD_RELOC_ARM_PLT32;
3319 inst.reloc.pc_rel = 0;
3320 /* Modify str to point to after parsed operands, otherwise
3321 end_of_line() will complain about the (PLT) left in str. */
3322 str = input_line_pointer;
3323 }
3324 else
3325 {
3326 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
3327 inst.reloc.pc_rel = 1;
3328 }
3329 input_line_pointer = save_in;
3330 }
3331#else
3332 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
3333 inst.reloc.pc_rel = 1;
3334#endif /* OBJ_ELF */
3335
3336 end_of_line (str);
3337 return;
3338}
3339
3340static void
3341do_bx (str, flags)
3342 char * str;
3343 unsigned long flags;
3344{
3345 int reg;
3346
ae5ad4ad 3347 skip_whitespace (str);
252b5132
RH
3348
3349 if ((reg = reg_required_here (&str, 0)) == FAIL)
92a66162
DL
3350 {
3351 inst.error = BAD_ARGS;
3352 return;
3353 }
252b5132
RH
3354
3355 if (reg == REG_PC)
92a66162 3356 inst.error = BAD_PC;
252b5132
RH
3357
3358 end_of_line (str);
252b5132
RH
3359}
3360
3361static void
3362do_cdp (str, flags)
3363 char * str;
3364 unsigned long flags;
3365{
3366 /* Co-processor data operation.
3367 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
ae5ad4ad 3368 skip_whitespace (str);
252b5132
RH
3369
3370 if (co_proc_number (&str) == FAIL)
3371 {
3372 if (!inst.error)
90ca882f 3373 inst.error = BAD_ARGS;
252b5132
RH
3374 return;
3375 }
3376
3377 if (skip_past_comma (&str) == FAIL
3378 || cp_opc_expr (&str, 20,4) == FAIL)
3379 {
3380 if (!inst.error)
90ca882f 3381 inst.error = BAD_ARGS;
252b5132
RH
3382 return;
3383 }
3384
3385 if (skip_past_comma (&str) == FAIL
3386 || cp_reg_required_here (&str, 12) == FAIL)
3387 {
3388 if (!inst.error)
90ca882f 3389 inst.error = BAD_ARGS;
252b5132
RH
3390 return;
3391 }
3392
3393 if (skip_past_comma (&str) == FAIL
3394 || cp_reg_required_here (&str, 16) == FAIL)
3395 {
3396 if (!inst.error)
90ca882f 3397 inst.error = BAD_ARGS;
252b5132
RH
3398 return;
3399 }
3400
3401 if (skip_past_comma (&str) == FAIL
3402 || cp_reg_required_here (&str, 0) == FAIL)
3403 {
3404 if (!inst.error)
90ca882f 3405 inst.error = BAD_ARGS;
252b5132
RH
3406 return;
3407 }
3408
3409 if (skip_past_comma (&str) == SUCCESS)
3410 {
3411 if (cp_opc_expr (&str, 5, 3) == FAIL)
3412 {
3413 if (!inst.error)
90ca882f 3414 inst.error = BAD_ARGS;
252b5132
RH
3415 return;
3416 }
3417 }
3418
3419 end_of_line (str);
3420 return;
3421}
3422
3423static void
3424do_lstc (str, flags)
3425 char * str;
3426 unsigned long flags;
3427{
3428 /* Co-processor register load/store.
3429 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
3430
ae5ad4ad 3431 skip_whitespace (str);
252b5132
RH
3432
3433 if (co_proc_number (&str) == FAIL)
3434 {
3435 if (!inst.error)
90ca882f 3436 inst.error = BAD_ARGS;
252b5132
RH
3437 return;
3438 }
3439
3440 if (skip_past_comma (&str) == FAIL
3441 || cp_reg_required_here (&str, 12) == FAIL)
3442 {
3443 if (!inst.error)
90ca882f 3444 inst.error = BAD_ARGS;
252b5132
RH
3445 return;
3446 }
3447
3448 if (skip_past_comma (&str) == FAIL
3449 || cp_address_required_here (&str) == FAIL)
3450 {
3451 if (! inst.error)
90ca882f 3452 inst.error = BAD_ARGS;
252b5132
RH
3453 return;
3454 }
3455
3456 inst.instruction |= flags;
3457 end_of_line (str);
3458 return;
3459}
3460
3461static void
3462do_co_reg (str, flags)
3463 char * str;
3464 unsigned long flags;
3465{
3466 /* Co-processor register transfer.
3467 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
3468
ae5ad4ad 3469 skip_whitespace (str);
252b5132
RH
3470
3471 if (co_proc_number (&str) == FAIL)
3472 {
3473 if (!inst.error)
90ca882f 3474 inst.error = BAD_ARGS;
252b5132
RH
3475 return;
3476 }
3477
3478 if (skip_past_comma (&str) == FAIL
3479 || cp_opc_expr (&str, 21, 3) == FAIL)
3480 {
3481 if (!inst.error)
90ca882f 3482 inst.error = BAD_ARGS;
252b5132
RH
3483 return;
3484 }
3485
3486 if (skip_past_comma (&str) == FAIL
3487 || reg_required_here (&str, 12) == FAIL)
3488 {
3489 if (!inst.error)
90ca882f 3490 inst.error = BAD_ARGS;
252b5132
RH
3491 return;
3492 }
3493
3494 if (skip_past_comma (&str) == FAIL
3495 || cp_reg_required_here (&str, 16) == FAIL)
3496 {
3497 if (!inst.error)
90ca882f 3498 inst.error = BAD_ARGS;
252b5132
RH
3499 return;
3500 }
3501
3502 if (skip_past_comma (&str) == FAIL
3503 || cp_reg_required_here (&str, 0) == FAIL)
3504 {
3505 if (!inst.error)
90ca882f 3506 inst.error = BAD_ARGS;
252b5132
RH
3507 return;
3508 }
3509
3510 if (skip_past_comma (&str) == SUCCESS)
3511 {
3512 if (cp_opc_expr (&str, 5, 3) == FAIL)
3513 {
3514 if (!inst.error)
90ca882f 3515 inst.error = BAD_ARGS;
252b5132
RH
3516 return;
3517 }
3518 }
92a66162
DL
3519 if (flags)
3520 {
3521 inst.error = BAD_COND;
3522 }
252b5132
RH
3523
3524 end_of_line (str);
3525 return;
3526}
3527
3528static void
3529do_fp_ctrl (str, flags)
3530 char * str;
3531 unsigned long flags;
3532{
3533 /* FP control registers.
3534 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
3535
ae5ad4ad 3536 skip_whitespace (str);
252b5132
RH
3537
3538 if (reg_required_here (&str, 12) == FAIL)
3539 {
3540 if (!inst.error)
90ca882f 3541 inst.error = BAD_ARGS;
252b5132
RH
3542 return;
3543 }
3544
3545 end_of_line (str);
3546 return;
3547}
3548
3549static void
3550do_fp_ldst (str, flags)
3551 char * str;
3552 unsigned long flags;
3553{
ae5ad4ad 3554 skip_whitespace (str);
252b5132
RH
3555
3556 switch (inst.suffix)
3557 {
3558 case SUFF_S:
3559 break;
3560 case SUFF_D:
3561 inst.instruction |= CP_T_X;
3562 break;
3563 case SUFF_E:
3564 inst.instruction |= CP_T_Y;
3565 break;
3566 case SUFF_P:
3567 inst.instruction |= CP_T_X | CP_T_Y;
3568 break;
3569 default:
3570 abort ();
3571 }
3572
3573 if (fp_reg_required_here (&str, 12) == FAIL)
3574 {
3575 if (!inst.error)
90ca882f 3576 inst.error = BAD_ARGS;
252b5132
RH
3577 return;
3578 }
3579
3580 if (skip_past_comma (&str) == FAIL
3581 || cp_address_required_here (&str) == FAIL)
3582 {
3583 if (!inst.error)
90ca882f 3584 inst.error = BAD_ARGS;
252b5132
RH
3585 return;
3586 }
3587
3588 end_of_line (str);
3589}
3590
3591static void
3592do_fp_ldmstm (str, flags)
3593 char * str;
3594 unsigned long flags;
3595{
3596 int num_regs;
3597
ae5ad4ad 3598 skip_whitespace (str);
252b5132
RH
3599
3600 if (fp_reg_required_here (&str, 12) == FAIL)
3601 {
3602 if (! inst.error)
90ca882f 3603 inst.error = BAD_ARGS;
252b5132
RH
3604 return;
3605 }
3606
3607 /* Get Number of registers to transfer */
3608 if (skip_past_comma (&str) == FAIL
3609 || my_get_expression (&inst.reloc.exp, &str))
3610 {
3611 if (! inst.error)
3612 inst.error = _("constant expression expected");
3613 return;
3614 }
3615
3616 if (inst.reloc.exp.X_op != O_constant)
3617 {
3618 inst.error = _("Constant value required for number of registers");
3619 return;
3620 }
3621
3622 num_regs = inst.reloc.exp.X_add_number;
3623
3624 if (num_regs < 1 || num_regs > 4)
3625 {
3626 inst.error = _("number of registers must be in the range [1:4]");
3627 return;
3628 }
3629
3630 switch (num_regs)
3631 {
3632 case 1:
3633 inst.instruction |= CP_T_X;
3634 break;
3635 case 2:
3636 inst.instruction |= CP_T_Y;
3637 break;
3638 case 3:
3639 inst.instruction |= CP_T_Y | CP_T_X;
3640 break;
3641 case 4:
3642 break;
3643 default:
3644 abort ();
3645 }
3646
3647 if (flags)
3648 {
3649 int reg;
3650 int write_back;
3651 int offset;
3652
3653 /* The instruction specified "ea" or "fd", so we can only accept
3654 [Rn]{!}. The instruction does not really support stacking or
3655 unstacking, so we have to emulate these by setting appropriate
3656 bits and offsets. */
3657 if (skip_past_comma (&str) == FAIL
3658 || *str != '[')
3659 {
3660 if (! inst.error)
90ca882f 3661 inst.error = BAD_ARGS;
252b5132
RH
3662 return;
3663 }
3664
3665 str++;
ae5ad4ad 3666 skip_whitespace (str);
252b5132
RH
3667
3668 if ((reg = reg_required_here (&str, 16)) == FAIL)
3669 return;
3670
ae5ad4ad 3671 skip_whitespace (str);
252b5132
RH
3672
3673 if (*str != ']')
3674 {
90ca882f 3675 inst.error = BAD_ARGS;
252b5132
RH
3676 return;
3677 }
3678
3679 str++;
3680 if (*str == '!')
3681 {
3682 write_back = 1;
3683 str++;
3684 if (reg == REG_PC)
3685 {
3686 inst.error = _("R15 not allowed as base register with write-back");
3687 return;
3688 }
3689 }
3690 else
3691 write_back = 0;
3692
3693 if (flags & CP_T_Pre)
3694 {
3695 /* Pre-decrement */
3696 offset = 3 * num_regs;
3697 if (write_back)
3698 flags |= CP_T_WB;
3699 }
3700 else
3701 {
3702 /* Post-increment */
3703 if (write_back)
3704 {
3705 flags |= CP_T_WB;
3706 offset = 3 * num_regs;
3707 }
3708 else
3709 {
3710 /* No write-back, so convert this into a standard pre-increment
3711 instruction -- aesthetically more pleasing. */
3712 flags = CP_T_Pre | CP_T_UD;
3713 offset = 0;
3714 }
3715 }
3716
3717 inst.instruction |= flags | offset;
3718 }
3719 else if (skip_past_comma (&str) == FAIL
3720 || cp_address_required_here (&str) == FAIL)
3721 {
3722 if (! inst.error)
90ca882f 3723 inst.error = BAD_ARGS;
252b5132
RH
3724 return;
3725 }
3726
3727 end_of_line (str);
3728}
3729
3730static void
3731do_fp_dyadic (str, flags)
3732 char * str;
3733 unsigned long flags;
3734{
ae5ad4ad 3735 skip_whitespace (str);
252b5132
RH
3736
3737 switch (inst.suffix)
3738 {
3739 case SUFF_S:
3740 break;
3741 case SUFF_D:
3742 inst.instruction |= 0x00000080;
3743 break;
3744 case SUFF_E:
3745 inst.instruction |= 0x00080000;
3746 break;
3747 default:
3748 abort ();
3749 }
3750
3751 if (fp_reg_required_here (&str, 12) == FAIL)
3752 {
3753 if (! inst.error)
90ca882f 3754 inst.error = BAD_ARGS;
252b5132
RH
3755 return;
3756 }
3757
3758 if (skip_past_comma (&str) == FAIL
3759 || fp_reg_required_here (&str, 16) == FAIL)
3760 {
3761 if (! inst.error)
90ca882f 3762 inst.error = BAD_ARGS;
252b5132
RH
3763 return;
3764 }
3765
3766 if (skip_past_comma (&str) == FAIL
3767 || fp_op2 (&str) == FAIL)
3768 {
3769 if (! inst.error)
90ca882f 3770 inst.error = BAD_ARGS;
252b5132
RH
3771 return;
3772 }
3773
3774 inst.instruction |= flags;
3775 end_of_line (str);
3776 return;
3777}
3778
3779static void
3780do_fp_monadic (str, flags)
3781 char * str;
3782 unsigned long flags;
3783{
ae5ad4ad 3784 skip_whitespace (str);
252b5132
RH
3785
3786 switch (inst.suffix)
3787 {
3788 case SUFF_S:
3789 break;
3790 case SUFF_D:
3791 inst.instruction |= 0x00000080;
3792 break;
3793 case SUFF_E:
3794 inst.instruction |= 0x00080000;
3795 break;
3796 default:
3797 abort ();
3798 }
3799
3800 if (fp_reg_required_here (&str, 12) == FAIL)
3801 {
3802 if (! inst.error)
90ca882f 3803 inst.error = BAD_ARGS;
252b5132
RH
3804 return;
3805 }
3806
3807 if (skip_past_comma (&str) == FAIL
3808 || fp_op2 (&str) == FAIL)
3809 {
3810 if (! inst.error)
90ca882f 3811 inst.error = BAD_ARGS;
252b5132
RH
3812 return;
3813 }
3814
3815 inst.instruction |= flags;
3816 end_of_line (str);
3817 return;
3818}
3819
3820static void
3821do_fp_cmp (str, flags)
3822 char * str;
3823 unsigned long flags;
3824{
ae5ad4ad 3825 skip_whitespace (str);
252b5132
RH
3826
3827 if (fp_reg_required_here (&str, 16) == FAIL)
3828 {
3829 if (! inst.error)
90ca882f 3830 inst.error = BAD_ARGS;
252b5132
RH
3831 return;
3832 }
3833
3834 if (skip_past_comma (&str) == FAIL
3835 || fp_op2 (&str) == FAIL)
3836 {
3837 if (! inst.error)
90ca882f 3838 inst.error = BAD_ARGS;
252b5132
RH
3839 return;
3840 }
3841
3842 inst.instruction |= flags;
3843 end_of_line (str);
3844 return;
3845}
3846
3847static void
3848do_fp_from_reg (str, flags)
3849 char * str;
3850 unsigned long flags;
3851{
ae5ad4ad 3852 skip_whitespace (str);
252b5132
RH
3853
3854 switch (inst.suffix)
3855 {
3856 case SUFF_S:
3857 break;
3858 case SUFF_D:
3859 inst.instruction |= 0x00000080;
3860 break;
3861 case SUFF_E:
3862 inst.instruction |= 0x00080000;
3863 break;
3864 default:
3865 abort ();
3866 }
3867
3868 if (fp_reg_required_here (&str, 16) == FAIL)
3869 {
3870 if (! inst.error)
90ca882f 3871 inst.error = BAD_ARGS;
252b5132
RH
3872 return;
3873 }
3874
3875 if (skip_past_comma (&str) == FAIL
3876 || reg_required_here (&str, 12) == FAIL)
3877 {
3878 if (! inst.error)
90ca882f 3879 inst.error = BAD_ARGS;
252b5132
RH
3880 return;
3881 }
3882
3883 inst.instruction |= flags;
3884 end_of_line (str);
3885 return;
3886}
3887
3888static void
3889do_fp_to_reg (str, flags)
3890 char * str;
3891 unsigned long flags;
3892{
ae5ad4ad 3893 skip_whitespace (str);
252b5132
RH
3894
3895 if (reg_required_here (&str, 12) == FAIL)
3896 return;
3897
3898 if (skip_past_comma (&str) == FAIL
3899 || fp_reg_required_here (&str, 0) == FAIL)
3900 {
3901 if (! inst.error)
90ca882f 3902 inst.error = BAD_ARGS;
252b5132
RH
3903 return;
3904 }
3905
3906 inst.instruction |= flags;
3907 end_of_line (str);
3908 return;
3909}
3910
3911/* Thumb specific routines */
3912
3913/* Parse and validate that a register is of the right form, this saves
3914 repeated checking of this information in many similar cases.
3915 Unlike the 32-bit case we do not insert the register into the opcode
3916 here, since the position is often unknown until the full instruction
3917 has been parsed. */
3918static int
3919thumb_reg (strp, hi_lo)
3920 char ** strp;
3921 int hi_lo;
3922{
3923 int reg;
3924
3925 if ((reg = reg_required_here (strp, -1)) == FAIL)
3926 return FAIL;
3927
3928 switch (hi_lo)
3929 {
3930 case THUMB_REG_LO:
3931 if (reg > 7)
3932 {
3933 inst.error = _("lo register required");
3934 return FAIL;
3935 }
3936 break;
3937
3938 case THUMB_REG_HI:
3939 if (reg < 8)
3940 {
3941 inst.error = _("hi register required");
3942 return FAIL;
3943 }
3944 break;
3945
3946 default:
3947 break;
3948 }
3949
3950 return reg;
3951}
3952
3953/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
3954 was SUB. */
3955static void
3956thumb_add_sub (str, subtract)
3957 char * str;
3958 int subtract;
3959{
3960 int Rd, Rs, Rn = FAIL;
3961
ae5ad4ad 3962 skip_whitespace (str);
252b5132
RH
3963
3964 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
3965 || skip_past_comma (&str) == FAIL)
3966 {
3967 if (! inst.error)
90ca882f 3968 inst.error = BAD_ARGS;
252b5132
RH
3969 return;
3970 }
3971
3972 if (is_immediate_prefix (*str))
3973 {
3974 Rs = Rd;
3975 str++;
3976 if (my_get_expression (&inst.reloc.exp, &str))
3977 return;
3978 }
3979 else
3980 {
3981 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
3982 return;
3983
3984 if (skip_past_comma (&str) == FAIL)
3985 {
3986 /* Two operand format, shuffle the registers and pretend there
3987 are 3 */
3988 Rn = Rs;
3989 Rs = Rd;
3990 }
3991 else if (is_immediate_prefix (*str))
3992 {
3993 str++;
3994 if (my_get_expression (&inst.reloc.exp, &str))
3995 return;
3996 }
3997 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
3998 return;
3999 }
4000
4001 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
4002 for the latter case, EXPR contains the immediate that was found. */
4003 if (Rn != FAIL)
4004 {
4005 /* All register format. */
4006 if (Rd > 7 || Rs > 7 || Rn > 7)
4007 {
4008 if (Rs != Rd)
4009 {
4010 inst.error = _("dest and source1 must be the same register");
4011 return;
4012 }
4013
4014 /* Can't do this for SUB */
4015 if (subtract)
4016 {
4017 inst.error = _("subtract valid only on lo regs");
4018 return;
4019 }
4020
4021 inst.instruction = (T_OPCODE_ADD_HI
4022 | (Rd > 7 ? THUMB_H1 : 0)
4023 | (Rn > 7 ? THUMB_H2 : 0));
4024 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
4025 }
4026 else
4027 {
4028 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
4029 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
4030 }
4031 }
4032 else
4033 {
4034 /* Immediate expression, now things start to get nasty. */
4035
4036 /* First deal with HI regs, only very restricted cases allowed:
4037 Adjusting SP, and using PC or SP to get an address. */
4038 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
4039 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
4040 {
4041 inst.error = _("invalid Hi register with immediate");
4042 return;
4043 }
4044
4045 if (inst.reloc.exp.X_op != O_constant)
4046 {
4047 /* Value isn't known yet, all we can do is store all the fragments
4048 we know about in the instruction and let the reloc hacking
4049 work it all out. */
4050 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
4051 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
4052 }
4053 else
4054 {
4055 int offset = inst.reloc.exp.X_add_number;
4056
4057 if (subtract)
4058 offset = -offset;
4059
4060 if (offset < 0)
4061 {
4062 offset = -offset;
4063 subtract = 1;
4064
4065 /* Quick check, in case offset is MIN_INT */
4066 if (offset < 0)
4067 {
4068 inst.error = _("immediate value out of range");
4069 return;
4070 }
4071 }
4072 else
4073 subtract = 0;
4074
4075 if (Rd == REG_SP)
4076 {
4077 if (offset & ~0x1fc)
4078 {
4079 inst.error = _("invalid immediate value for stack adjust");
4080 return;
4081 }
4082 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
4083 inst.instruction |= offset >> 2;
4084 }
4085 else if (Rs == REG_PC || Rs == REG_SP)
4086 {
4087 if (subtract
4088 || (offset & ~0x3fc))
4089 {
4090 inst.error = _("invalid immediate for address calculation");
4091 return;
4092 }
4093 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
4094 : T_OPCODE_ADD_SP);
4095 inst.instruction |= (Rd << 8) | (offset >> 2);
4096 }
4097 else if (Rs == Rd)
4098 {
4099 if (offset & ~0xff)
4100 {
4101 inst.error = _("immediate value out of range");
4102 return;
4103 }
4104 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
4105 inst.instruction |= (Rd << 8) | offset;
4106 }
4107 else
4108 {
4109 if (offset & ~0x7)
4110 {
4111 inst.error = _("immediate value out of range");
4112 return;
4113 }
4114 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
4115 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
4116 }
4117 }
4118 }
4119 end_of_line (str);
4120}
4121
4122static void
4123thumb_shift (str, shift)
4124 char * str;
4125 int shift;
4126{
4127 int Rd, Rs, Rn = FAIL;
4128
ae5ad4ad 4129 skip_whitespace (str);
252b5132
RH
4130
4131 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4132 || skip_past_comma (&str) == FAIL)
4133 {
4134 if (! inst.error)
90ca882f 4135 inst.error = BAD_ARGS;
252b5132
RH
4136 return;
4137 }
4138
4139 if (is_immediate_prefix (*str))
4140 {
4141 /* Two operand immediate format, set Rs to Rd. */
4142 Rs = Rd;
4143 str++;
4144 if (my_get_expression (&inst.reloc.exp, &str))
4145 return;
4146 }
4147 else
4148 {
4149 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4150 return;
4151
4152 if (skip_past_comma (&str) == FAIL)
4153 {
4154 /* Two operand format, shuffle the registers and pretend there
4155 are 3 */
4156 Rn = Rs;
4157 Rs = Rd;
4158 }
4159 else if (is_immediate_prefix (*str))
4160 {
4161 str++;
4162 if (my_get_expression (&inst.reloc.exp, &str))
4163 return;
4164 }
4165 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4166 return;
4167 }
4168
4169 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
4170 for the latter case, EXPR contains the immediate that was found. */
4171
4172 if (Rn != FAIL)
4173 {
4174 if (Rs != Rd)
4175 {
4176 inst.error = _("source1 and dest must be same register");
4177 return;
4178 }
4179
4180 switch (shift)
4181 {
4182 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
4183 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
4184 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
4185 }
4186
4187 inst.instruction |= Rd | (Rn << 3);
4188 }
4189 else
4190 {
4191 switch (shift)
4192 {
4193 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
4194 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
4195 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
4196 }
4197
4198 if (inst.reloc.exp.X_op != O_constant)
4199 {
4200 /* Value isn't known yet, create a dummy reloc and let reloc
4201 hacking fix it up */
4202
4203 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
4204 }
4205 else
4206 {
4207 unsigned shift_value = inst.reloc.exp.X_add_number;
4208
4209 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
4210 {
4211 inst.error = _("Invalid immediate for shift");
4212 return;
4213 }
4214
4215 /* Shifts of zero are handled by converting to LSL */
4216 if (shift_value == 0)
4217 inst.instruction = T_OPCODE_LSL_I;
4218
4219 /* Shifts of 32 are encoded as a shift of zero */
4220 if (shift_value == 32)
4221 shift_value = 0;
4222
4223 inst.instruction |= shift_value << 6;
4224 }
4225
4226 inst.instruction |= Rd | (Rs << 3);
4227 }
4228 end_of_line (str);
4229}
4230
4231static void
4232thumb_mov_compare (str, move)
4233 char * str;
4234 int move;
4235{
4236 int Rd, Rs = FAIL;
4237
ae5ad4ad 4238 skip_whitespace (str);
252b5132
RH
4239
4240 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4241 || skip_past_comma (&str) == FAIL)
4242 {
4243 if (! inst.error)
90ca882f 4244 inst.error = BAD_ARGS;
252b5132
RH
4245 return;
4246 }
4247
4248 if (is_immediate_prefix (*str))
4249 {
4250 str++;
4251 if (my_get_expression (&inst.reloc.exp, &str))
4252 return;
4253 }
4254 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4255 return;
4256
4257 if (Rs != FAIL)
4258 {
4259 if (Rs < 8 && Rd < 8)
4260 {
4261 if (move == THUMB_MOVE)
4262 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4263 since a MOV instruction produces unpredictable results */
4264 inst.instruction = T_OPCODE_ADD_I3;
4265 else
4266 inst.instruction = T_OPCODE_CMP_LR;
4267 inst.instruction |= Rd | (Rs << 3);
4268 }
4269 else
4270 {
4271 if (move == THUMB_MOVE)
4272 inst.instruction = T_OPCODE_MOV_HR;
4273 else
4274 inst.instruction = T_OPCODE_CMP_HR;
4275
4276 if (Rd > 7)
4277 inst.instruction |= THUMB_H1;
4278
4279 if (Rs > 7)
4280 inst.instruction |= THUMB_H2;
4281
4282 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4283 }
4284 }
4285 else
4286 {
4287 if (Rd > 7)
4288 {
4289 inst.error = _("only lo regs allowed with immediate");
4290 return;
4291 }
4292
4293 if (move == THUMB_MOVE)
4294 inst.instruction = T_OPCODE_MOV_I8;
4295 else
4296 inst.instruction = T_OPCODE_CMP_I8;
4297
4298 inst.instruction |= Rd << 8;
4299
4300 if (inst.reloc.exp.X_op != O_constant)
4301 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4302 else
4303 {
4304 unsigned value = inst.reloc.exp.X_add_number;
4305
4306 if (value > 255)
4307 {
4308 inst.error = _("invalid immediate");
4309 return;
4310 }
4311
4312 inst.instruction |= value;
4313 }
4314 }
4315
4316 end_of_line (str);
4317}
4318
4319static void
4320thumb_load_store (str, load_store, size)
4321 char * str;
4322 int load_store;
4323 int size;
4324{
4325 int Rd, Rb, Ro = FAIL;
4326
ae5ad4ad 4327 skip_whitespace (str);
252b5132
RH
4328
4329 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4330 || skip_past_comma (&str) == FAIL)
4331 {
4332 if (! inst.error)
90ca882f 4333 inst.error = BAD_ARGS;
252b5132
RH
4334 return;
4335 }
4336
4337 if (*str == '[')
4338 {
4339 str++;
4340 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4341 return;
4342
4343 if (skip_past_comma (&str) != FAIL)
4344 {
4345 if (is_immediate_prefix (*str))
4346 {
4347 str++;
4348 if (my_get_expression (&inst.reloc.exp, &str))
4349 return;
4350 }
4351 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4352 return;
4353 }
4354 else
4355 {
4356 inst.reloc.exp.X_op = O_constant;
4357 inst.reloc.exp.X_add_number = 0;
4358 }
4359
4360 if (*str != ']')
4361 {
4362 inst.error = _("expected ']'");
4363 return;
4364 }
4365 str++;
4366 }
4367 else if (*str == '=')
4368 {
4369 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
4370 str++;
4371
ae5ad4ad 4372 skip_whitespace (str);
252b5132
RH
4373
4374 if (my_get_expression (& inst.reloc.exp, & str))
4375 return;
4376
4377 end_of_line (str);
4378
4379 if ( inst.reloc.exp.X_op != O_constant
4380 && inst.reloc.exp.X_op != O_symbol)
4381 {
4382 inst.error = "Constant expression expected";
4383 return;
4384 }
4385
4386 if (inst.reloc.exp.X_op == O_constant
4387 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
4388 {
4389 /* This can be done with a mov instruction */
4390
4391 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
4392 inst.instruction |= inst.reloc.exp.X_add_number;
4393 return;
4394 }
4395
4396 /* Insert into literal pool */
4397 if (add_to_lit_pool () == FAIL)
4398 {
4399 if (!inst.error)
4400 inst.error = "literal pool insertion failed";
4401 return;
4402 }
4403
4404 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4405 inst.reloc.pc_rel = 1;
4406 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
4407 inst.reloc.exp.X_add_number += 4; /* Adjust ARM pipeline offset to Thumb */
4408
4409 return;
4410 }
4411 else
4412 {
4413 if (my_get_expression (&inst.reloc.exp, &str))
4414 return;
4415
4416 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
4417 inst.reloc.pc_rel = 1;
4418 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset */
4419 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4420 end_of_line (str);
4421 return;
4422 }
4423
4424 if (Rb == REG_PC || Rb == REG_SP)
4425 {
4426 if (size != THUMB_WORD)
4427 {
4428 inst.error = _("byte or halfword not valid for base register");
4429 return;
4430 }
4431 else if (Rb == REG_PC && load_store != THUMB_LOAD)
4432 {
4433 inst.error = _("R15 based store not allowed");
4434 return;
4435 }
4436 else if (Ro != FAIL)
4437 {
4438 inst.error = _("Invalid base register for register offset");
4439 return;
4440 }
4441
4442 if (Rb == REG_PC)
4443 inst.instruction = T_OPCODE_LDR_PC;
4444 else if (load_store == THUMB_LOAD)
4445 inst.instruction = T_OPCODE_LDR_SP;
4446 else
4447 inst.instruction = T_OPCODE_STR_SP;
4448
4449 inst.instruction |= Rd << 8;
4450 if (inst.reloc.exp.X_op == O_constant)
4451 {
4452 unsigned offset = inst.reloc.exp.X_add_number;
4453
4454 if (offset & ~0x3fc)
4455 {
4456 inst.error = _("invalid offset");
4457 return;
4458 }
4459
4460 inst.instruction |= offset >> 2;
4461 }
4462 else
4463 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4464 }
4465 else if (Rb > 7)
4466 {
4467 inst.error = _("invalid base register in load/store");
4468 return;
4469 }
4470 else if (Ro == FAIL)
4471 {
4472 /* Immediate offset */
4473 if (size == THUMB_WORD)
4474 inst.instruction = (load_store == THUMB_LOAD
4475 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
4476 else if (size == THUMB_HALFWORD)
4477 inst.instruction = (load_store == THUMB_LOAD
4478 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
4479 else
4480 inst.instruction = (load_store == THUMB_LOAD
4481 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
4482
4483 inst.instruction |= Rd | (Rb << 3);
4484
4485 if (inst.reloc.exp.X_op == O_constant)
4486 {
4487 unsigned offset = inst.reloc.exp.X_add_number;
4488
4489 if (offset & ~(0x1f << size))
4490 {
4491 inst.error = _("Invalid offset");
4492 return;
4493 }
4494 inst.instruction |= (offset >> size) << 6;
4495 }
4496 else
4497 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4498 }
4499 else
4500 {
4501 /* Register offset */
4502 if (size == THUMB_WORD)
4503 inst.instruction = (load_store == THUMB_LOAD
4504 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
4505 else if (size == THUMB_HALFWORD)
4506 inst.instruction = (load_store == THUMB_LOAD
4507 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
4508 else
4509 inst.instruction = (load_store == THUMB_LOAD
4510 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
4511
4512 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
4513 }
4514
4515 end_of_line (str);
4516}
4517
4518static void
4519do_t_nop (str)
4520 char * str;
4521{
4522 /* Do nothing */
4523 end_of_line (str);
4524 return;
4525}
4526
4527/* Handle the Format 4 instructions that do not have equivalents in other
4528 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
4529 BIC and MVN. */
4530static void
4531do_t_arit (str)
4532 char * str;
4533{
4534 int Rd, Rs, Rn;
4535
ae5ad4ad 4536 skip_whitespace (str);
252b5132 4537
92a66162
DL
4538 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4539 || skip_past_comma (&str) == FAIL
252b5132
RH
4540 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4541 {
92a66162
DL
4542 inst.error = BAD_ARGS;
4543 return;
252b5132
RH
4544 }
4545
4546 if (skip_past_comma (&str) != FAIL)
4547 {
4548 /* Three operand format not allowed for TST, CMN, NEG and MVN.
4549 (It isn't allowed for CMP either, but that isn't handled by this
4550 function.) */
4551 if (inst.instruction == T_OPCODE_TST
4552 || inst.instruction == T_OPCODE_CMN
4553 || inst.instruction == T_OPCODE_NEG
4554 || inst.instruction == T_OPCODE_MVN)
4555 {
90ca882f 4556 inst.error = BAD_ARGS;
252b5132
RH
4557 return;
4558 }
4559
4560 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4561 return;
4562
4563 if (Rs != Rd)
4564 {
4565 inst.error = _("dest and source1 one must be the same register");
4566 return;
4567 }
4568 Rs = Rn;
4569 }
4570
4571 if (inst.instruction == T_OPCODE_MUL
4572 && Rs == Rd)
4573 as_tsktsk (_("Rs and Rd must be different in MUL"));
4574
4575 inst.instruction |= Rd | (Rs << 3);
4576 end_of_line (str);
4577}
4578
4579static void
4580do_t_add (str)
4581 char * str;
4582{
4583 thumb_add_sub (str, 0);
4584}
4585
4586static void
4587do_t_asr (str)
4588 char * str;
4589{
4590 thumb_shift (str, THUMB_ASR);
4591}
4592
4593static void
4594do_t_branch9 (str)
4595 char * str;
4596{
4597 if (my_get_expression (&inst.reloc.exp, &str))
4598 return;
4599 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
4600 inst.reloc.pc_rel = 1;
4601 end_of_line (str);
4602}
4603
4604static void
4605do_t_branch12 (str)
4606 char * str;
4607{
4608 if (my_get_expression (&inst.reloc.exp, &str))
4609 return;
4610 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
4611 inst.reloc.pc_rel = 1;
4612 end_of_line (str);
4613}
4614
4615/* Find the real, Thumb encoded start of a Thumb function. */
4616
4617static symbolS *
4618find_real_start (symbolP)
4619 symbolS * symbolP;
4620{
4621 char * real_start;
4622 const char * name = S_GET_NAME (symbolP);
4623 symbolS * new_target;
4624
ae5ad4ad 4625 /* This definiton must agree with the one in gcc/config/arm/thumb.c */
252b5132
RH
4626#define STUB_NAME ".real_start_of"
4627
4628 if (name == NULL)
4629 abort();
4630
4631 /* Names that start with '.' are local labels, not function entry points.
4632 The compiler may generate BL instructions to these labels because it
4633 needs to perform a branch to a far away location. */
4634 if (name[0] == '.')
4635 return symbolP;
4636
4637 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
4638 sprintf (real_start, "%s%s", STUB_NAME, name);
4639
4640 new_target = symbol_find (real_start);
4641
4642 if (new_target == NULL)
4643 {
4644 as_warn ("Failed to find real start of function: %s\n", name);
4645 new_target = symbolP;
4646 }
4647
4648 free (real_start);
4649
4650 return new_target;
4651}
4652
4653
4654static void
4655do_t_branch23 (str)
4656 char * str;
4657{
ae5ad4ad 4658 if (my_get_expression (& inst.reloc.exp, & str))
252b5132 4659 return;
ae5ad4ad 4660
252b5132
RH
4661 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
4662 inst.reloc.pc_rel = 1;
4663 end_of_line (str);
4664
4665 /* If the destination of the branch is a defined symbol which does not have
4666 the THUMB_FUNC attribute, then we must be calling a function which has
4667 the (interfacearm) attribute. We look for the Thumb entry point to that
4668 function and change the branch to refer to that function instead. */
4669 if ( inst.reloc.exp.X_op == O_symbol
4670 && inst.reloc.exp.X_add_symbol != NULL
4671 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
4672 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
4673 inst.reloc.exp.X_add_symbol = find_real_start (inst.reloc.exp.X_add_symbol);
4674}
4675
4676static void
4677do_t_bx (str)
4678 char * str;
4679{
4680 int reg;
4681
ae5ad4ad 4682 skip_whitespace (str);
252b5132
RH
4683
4684 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4685 return;
4686
4687 /* This sets THUMB_H2 from the top bit of reg. */
4688 inst.instruction |= reg << 3;
4689
4690 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
4691 should cause the alignment to be checked once it is known. This is
4692 because BX PC only works if the instruction is word aligned. */
4693
4694 end_of_line (str);
4695}
4696
4697static void
4698do_t_compare (str)
4699 char * str;
4700{
4701 thumb_mov_compare (str, THUMB_COMPARE);
4702}
4703
4704static void
4705do_t_ldmstm (str)
4706 char * str;
4707{
4708 int Rb;
4709 long range;
4710
ae5ad4ad 4711 skip_whitespace (str);
252b5132
RH
4712
4713 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4714 return;
4715
4716 if (*str != '!')
4717 as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
4718 else
4719 str++;
4720
4721 if (skip_past_comma (&str) == FAIL
4722 || (range = reg_list (&str)) == FAIL)
4723 {
4724 if (! inst.error)
90ca882f 4725 inst.error = BAD_ARGS;
252b5132
RH
4726 return;
4727 }
4728
4729 if (inst.reloc.type != BFD_RELOC_NONE)
4730 {
4731 /* This really doesn't seem worth it. */
4732 inst.reloc.type = BFD_RELOC_NONE;
4733 inst.error = _("Expression too complex");
4734 return;
4735 }
4736
4737 if (range & ~0xff)
4738 {
4739 inst.error = _("only lo-regs valid in load/store multiple");
4740 return;
4741 }
4742
4743 inst.instruction |= (Rb << 8) | range;
4744 end_of_line (str);
4745}
4746
4747static void
4748do_t_ldr (str)
4749 char * str;
4750{
4751 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
4752}
4753
4754static void
4755do_t_ldrb (str)
4756 char * str;
4757{
4758 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
4759}
4760
4761static void
4762do_t_ldrh (str)
4763 char * str;
4764{
4765 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
4766}
4767
4768static void
4769do_t_lds (str)
4770 char * str;
4771{
4772 int Rd, Rb, Ro;
4773
ae5ad4ad 4774 skip_whitespace (str);
252b5132
RH
4775
4776 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4777 || skip_past_comma (&str) == FAIL
4778 || *str++ != '['
4779 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4780 || skip_past_comma (&str) == FAIL
4781 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4782 || *str++ != ']')
4783 {
4784 if (! inst.error)
4785 inst.error = _("Syntax: ldrs[b] Rd, [Rb, Ro]");
4786 return;
4787 }
4788
4789 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
4790 end_of_line (str);
4791}
4792
4793static void
4794do_t_lsl (str)
4795 char * str;
4796{
4797 thumb_shift (str, THUMB_LSL);
4798}
4799
4800static void
4801do_t_lsr (str)
4802 char * str;
4803{
4804 thumb_shift (str, THUMB_LSR);
4805}
4806
4807static void
4808do_t_mov (str)
4809 char * str;
4810{
4811 thumb_mov_compare (str, THUMB_MOVE);
4812}
4813
4814static void
4815do_t_push_pop (str)
4816 char * str;
4817{
4818 long range;
4819
ae5ad4ad 4820 skip_whitespace (str);
252b5132
RH
4821
4822 if ((range = reg_list (&str)) == FAIL)
4823 {
4824 if (! inst.error)
90ca882f 4825 inst.error = BAD_ARGS;
252b5132
RH
4826 return;
4827 }
4828
4829 if (inst.reloc.type != BFD_RELOC_NONE)
4830 {
4831 /* This really doesn't seem worth it. */
4832 inst.reloc.type = BFD_RELOC_NONE;
4833 inst.error = _("Expression too complex");
4834 return;
4835 }
4836
4837 if (range & ~0xff)
4838 {
4839 if ((inst.instruction == T_OPCODE_PUSH
4840 && (range & ~0xff) == 1 << REG_LR)
4841 || (inst.instruction == T_OPCODE_POP
4842 && (range & ~0xff) == 1 << REG_PC))
4843 {
4844 inst.instruction |= THUMB_PP_PC_LR;
4845 range &= 0xff;
4846 }
4847 else
4848 {
4849 inst.error = _("invalid register list to push/pop instruction");
4850 return;
4851 }
4852 }
4853
4854 inst.instruction |= range;
4855 end_of_line (str);
4856}
4857
4858static void
4859do_t_str (str)
4860 char * str;
4861{
4862 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
4863}
4864
4865static void
4866do_t_strb (str)
4867 char * str;
4868{
4869 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
4870}
4871
4872static void
4873do_t_strh (str)
4874 char * str;
4875{
4876 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
4877}
4878
4879static void
4880do_t_sub (str)
4881 char * str;
4882{
4883 thumb_add_sub (str, 1);
4884}
4885
4886static void
4887do_t_swi (str)
4888 char * str;
4889{
ae5ad4ad 4890 skip_whitespace (str);
252b5132
RH
4891
4892 if (my_get_expression (&inst.reloc.exp, &str))
4893 return;
4894
4895 inst.reloc.type = BFD_RELOC_ARM_SWI;
4896 end_of_line (str);
4897 return;
4898}
4899
4900static void
4901do_t_adr (str)
4902 char * str;
4903{
4904 /* This is a pseudo-op of the form "adr rd, label" to be converted
4905 into a relative address of the form "add rd, pc, #label-.-4" */
ae5ad4ad 4906 skip_whitespace (str);
252b5132
RH
4907
4908 if (reg_required_here (&str, 4) == FAIL /* Store Rd in temporary location inside instruction. */
4909 || skip_past_comma (&str) == FAIL
4910 || my_get_expression (&inst.reloc.exp, &str))
4911 {
4912 if (!inst.error)
90ca882f 4913 inst.error = BAD_ARGS;
252b5132
RH
4914 return;
4915 }
4916
4917 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
4918 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust */
4919 inst.reloc.pc_rel = 1;
4920 inst.instruction |= REG_PC; /* Rd is already placed into the instruction */
4921 end_of_line (str);
4922}
4923
4924static void
4925insert_reg (entry)
4926 int entry;
4927{
4928 int len = strlen (reg_table[entry].name) + 2;
4929 char * buf = (char *) xmalloc (len);
4930 char * buf2 = (char *) xmalloc (len);
4931 int i = 0;
4932
4933#ifdef REGISTER_PREFIX
4934 buf[i++] = REGISTER_PREFIX;
4935#endif
4936
4937 strcpy (buf + i, reg_table[entry].name);
4938
4939 for (i = 0; buf[i]; i++)
4940 buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i];
4941
4942 buf2[i] = '\0';
4943
4944 hash_insert (arm_reg_hsh, buf, (PTR) &reg_table[entry]);
4945 hash_insert (arm_reg_hsh, buf2, (PTR) &reg_table[entry]);
4946}
4947
4948static void
4949insert_reg_alias (str, regnum)
4950 char *str;
4951 int regnum;
4952{
4953 struct reg_entry *new =
4954 (struct reg_entry *)xmalloc (sizeof (struct reg_entry));
4955 char *name = xmalloc (strlen (str) + 1);
4956 strcpy (name, str);
4957
4958 new->name = name;
4959 new->number = regnum;
4960
4961 hash_insert (arm_reg_hsh, name, (PTR) new);
4962}
4963
4964static void
4965set_constant_flonums ()
4966{
4967 int i;
4968
4969 for (i = 0; i < NUM_FLOAT_VALS; i++)
4970 if (atof_ieee ((char *)fp_const[i], 'x', fp_values[i]) == NULL)
4971 abort ();
4972}
4973
4974void
4975md_begin ()
4976{
4977 int i;
4978
4979 if ( (arm_ops_hsh = hash_new ()) == NULL
4980 || (arm_tops_hsh = hash_new ()) == NULL
4981 || (arm_cond_hsh = hash_new ()) == NULL
4982 || (arm_shift_hsh = hash_new ()) == NULL
4983 || (arm_reg_hsh = hash_new ()) == NULL
4984 || (arm_psr_hsh = hash_new ()) == NULL)
4985 as_fatal (_("Virtual memory exhausted"));
4986
4987 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
4988 hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
4989 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
4990 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
4991 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
4992 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
4993 for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
4994 hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i));
4995 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
4996 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
4997
4998 for (i = 0; reg_table[i].name; i++)
4999 insert_reg (i);
5000
5001 set_constant_flonums ();
5002
5003#if defined OBJ_COFF || defined OBJ_ELF
5004 {
5005 unsigned int flags = 0;
5006
5007 /* Set the flags in the private structure */
5008 if (uses_apcs_26) flags |= F_APCS26;
5009 if (support_interwork) flags |= F_INTERWORK;
5010 if (uses_apcs_float) flags |= F_APCS_FLOAT;
5011 if (pic_code) flags |= F_PIC;
2f992c04 5012 if ((cpu_variant & FPU_ALL) == FPU_NONE) flags |= F_SOFT_FLOAT;
252b5132
RH
5013
5014 bfd_set_private_flags (stdoutput, flags);
5015 }
5016#endif
5017
5018 {
5019 unsigned mach;
5020
5021 /* Record the CPU type as well */
5022 switch (cpu_variant & ARM_CPU_MASK)
5023 {
5024 case ARM_2:
5025 mach = bfd_mach_arm_2;
5026 break;
5027
5028 case ARM_3: /* also ARM_250 */
5029 mach = bfd_mach_arm_2a;
5030 break;
5031
5032 default:
5033 case ARM_6 | ARM_3 | ARM_2: /* Actually no CPU type defined */
5034 mach = bfd_mach_arm_4;
5035 break;
5036
5037 case ARM_7: /* also ARM_6 */
5038 mach = bfd_mach_arm_3;
5039 break;
5040 }
5041
ae5ad4ad 5042 /* Catch special cases. */
252b5132
RH
5043 if (cpu_variant != (FPU_DEFAULT | CPU_DEFAULT))
5044 {
49a5575c
NC
5045 if (cpu_variant & (ARM_EXT_V5 & ARM_THUMB))
5046 mach = bfd_mach_arm_5T;
5047 else if (cpu_variant & ARM_EXT_V5)
5048 mach = bfd_mach_arm_5;
5049 else if (cpu_variant & ARM_THUMB)
252b5132 5050 mach = bfd_mach_arm_4T;
49a5575c 5051 else if ((cpu_variant & ARM_ARCH_V4) == ARM_ARCH_V4)
252b5132
RH
5052 mach = bfd_mach_arm_4;
5053 else if (cpu_variant & ARM_LONGMUL)
5054 mach = bfd_mach_arm_3M;
5055 }
5056
5057 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
5058 }
5059}
5060
5061/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
5062 for use in the a.out file, and stores them in the array pointed to by buf.
5063 This knows about the endian-ness of the target machine and does
5064 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
5065 2 (short) and 4 (long) Floating numbers are put out as a series of
ae5ad4ad 5066 LITTLENUMS (shorts, here at least). */
252b5132
RH
5067void
5068md_number_to_chars (buf, val, n)
5069 char * buf;
5070 valueT val;
5071 int n;
5072{
5073 if (target_big_endian)
5074 number_to_chars_bigendian (buf, val, n);
5075 else
5076 number_to_chars_littleendian (buf, val, n);
5077}
5078
5079static valueT
5080md_chars_to_number (buf, n)
5081 char * buf;
5082 int n;
5083{
5084 valueT result = 0;
5085 unsigned char * where = (unsigned char *) buf;
5086
5087 if (target_big_endian)
5088 {
5089 while (n--)
5090 {
5091 result <<= 8;
5092 result |= (*where++ & 255);
5093 }
5094 }
5095 else
5096 {
5097 while (n--)
5098 {
5099 result <<= 8;
5100 result |= (where[n] & 255);
5101 }
5102 }
5103
5104 return result;
5105}
5106
5107/* Turn a string in input_line_pointer into a floating point constant
5108 of type TYPE, and store the appropriate bytes in *litP. The number
5109 of LITTLENUMS emitted is stored in *sizeP . An error message is
5110 returned, or NULL on OK.
5111
5112 Note that fp constants aren't represent in the normal way on the ARM.
5113 In big endian mode, things are as expected. However, in little endian
5114 mode fp constants are big-endian word-wise, and little-endian byte-wise
5115 within the words. For example, (double) 1.1 in big endian mode is
5116 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
5117 the byte sequence 99 99 f1 3f 9a 99 99 99.
5118
5119 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
5120
5121char *
5122md_atof (type, litP, sizeP)
5123 char type;
5124 char * litP;
5125 int * sizeP;
5126{
5127 int prec;
5128 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5129 char *t;
5130 int i;
5131
5132 switch (type)
5133 {
5134 case 'f':
5135 case 'F':
5136 case 's':
5137 case 'S':
5138 prec = 2;
5139 break;
5140
5141 case 'd':
5142 case 'D':
5143 case 'r':
5144 case 'R':
5145 prec = 4;
5146 break;
5147
5148 case 'x':
5149 case 'X':
5150 prec = 6;
5151 break;
5152
5153 case 'p':
5154 case 'P':
5155 prec = 6;
5156 break;
5157
5158 default:
5159 *sizeP = 0;
5160 return _("Bad call to MD_ATOF()");
5161 }
5162
5163 t = atof_ieee (input_line_pointer, type, words);
5164 if (t)
5165 input_line_pointer = t;
5166 *sizeP = prec * 2;
5167
5168 if (target_big_endian)
5169 {
5170 for (i = 0; i < prec; i++)
5171 {
5172 md_number_to_chars (litP, (valueT) words[i], 2);
5173 litP += 2;
5174 }
5175 }
5176 else
5177 {
5178 /* For a 4 byte float the order of elements in `words' is 1 0. For an
5179 8 byte float the order is 1 0 3 2. */
5180 for (i = 0; i < prec; i += 2)
5181 {
5182 md_number_to_chars (litP, (valueT) words[i + 1], 2);
5183 md_number_to_chars (litP + 2, (valueT) words[i], 2);
5184 litP += 4;
5185 }
5186 }
5187
5188 return 0;
5189}
5190
661e4995 5191/* The knowledge of the PC's pipeline offset is built into the insns themselves. */
252b5132
RH
5192long
5193md_pcrel_from (fixP)
5194 fixS * fixP;
5195{
5196 if ( fixP->fx_addsy
5197 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
5198 && fixP->fx_subsy == NULL)
5199 return 0;
5200
5201 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
5202 {
5203 /* PC relative addressing on the Thumb is slightly odd
5204 as the bottom two bits of the PC are forced to zero
ae5ad4ad 5205 for the calculation. */
252b5132
RH
5206 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
5207 }
661e4995 5208
252b5132
RH
5209 return fixP->fx_where + fixP->fx_frag->fr_address;
5210}
5211
5212/* Round up a section size to the appropriate boundary. */
5213valueT
5214md_section_align (segment, size)
5215 segT segment;
5216 valueT size;
5217{
5218#ifdef OBJ_ELF
5856c19a 5219 return size;
231b5e29 5220#else
252b5132
RH
5221 /* Round all sects to multiple of 4 */
5222 return (size + 3) & ~3;
231b5e29 5223#endif
252b5132
RH
5224}
5225
5226/* Under ELF we need to default _GLOBAL_OFFSET_TABLE. Otherwise
5227 we have no need to default values of symbols. */
5228
5229/* ARGSUSED */
5230symbolS *
5231md_undefined_symbol (name)
5232 char * name;
5233{
5234#ifdef OBJ_ELF
5235 if (name[0] == '_' && name[1] == 'G'
5236 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
5237 {
5238 if (!GOT_symbol)
5239 {
5240 if (symbol_find (name))
5241 as_bad ("GOT already in the symbol table");
5242
5243 GOT_symbol = symbol_new (name, undefined_section,
5244 (valueT)0, & zero_address_frag);
5245 }
5246
5247 return GOT_symbol;
5248 }
5249#endif
5250
5251 return 0;
5252}
5253
5254/* arm_reg_parse () := if it looks like a register, return its token and
5255 advance the pointer. */
5256
5257static int
5258arm_reg_parse (ccp)
5259 register char ** ccp;
5260{
5261 char * start = * ccp;
5262 char c;
5263 char * p;
5264 struct reg_entry * reg;
5265
5266#ifdef REGISTER_PREFIX
5267 if (*start != REGISTER_PREFIX)
5268 return FAIL;
5269 p = start + 1;
5270#else
5271 p = start;
5272#ifdef OPTIONAL_REGISTER_PREFIX
5273 if (*p == OPTIONAL_REGISTER_PREFIX)
5274 p++, start++;
5275#endif
5276#endif
5277 if (!isalpha (*p) || !is_name_beginner (*p))
5278 return FAIL;
5279
5280 c = *p++;
5281 while (isalpha (c) || isdigit (c) || c == '_')
5282 c = *p++;
5283
5284 *--p = 0;
5285 reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
5286 *p = c;
5287
5288 if (reg)
5289 {
5290 *ccp = p;
5291 return reg->number;
5292 }
5293
5294 return FAIL;
5295}
5296
5297static int
5298arm_psr_parse (ccp)
5299 register char ** ccp;
5300{
5301 char * start = * ccp;
5302 char c;
5303 char * p;
5304 CONST struct asm_psr * psr;
5305
5306 p = start;
5307 c = *p++;
5308 while (isalpha (c) || c == '_')
5309 c = *p++;
5310
5311 *--p = 0;
5312 psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
5313 *p = c;
5314
5315 if (psr)
5316 {
5317 *ccp = p;
5318 return psr->number;
5319 }
5320
5321 return FAIL;
5322}
5323
5324int
5325md_apply_fix3 (fixP, val, seg)
5326 fixS * fixP;
5327 valueT * val;
5328 segT seg;
5329{
5330 offsetT value = * val;
5331 offsetT newval;
5332 unsigned int newimm;
5333 unsigned long temp;
5334 int sign;
5335 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
5336 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
5337
5338 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5339
5340 /* Note whether this will delete the relocation. */
5341#if 0 /* patch from REarnshaw to JDavis (disabled for the moment, since it doesn't work fully) */
a77f5182 5342 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
252b5132
RH
5343 && !fixP->fx_pcrel)
5344#else
5345 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
5346#endif
5347 fixP->fx_done = 1;
5348
5349 /* If this symbol is in a different section then we need to leave it for
5350 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5351 so we have to undo it's effects here. */
5352 if (fixP->fx_pcrel)
5353 {
5354 if (fixP->fx_addsy != NULL
5355 && S_IS_DEFINED (fixP->fx_addsy)
5356 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
5357 {
661e4995 5358 if (target_oabi
92a66162
DL
5359 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
5360 ))
252b5132
RH
5361 value = 0;
5362 else
5363 value += md_pcrel_from (fixP);
5364 }
5365 }
5366
ae5ad4ad 5367 fixP->fx_addnumber = value; /* Remember value for emit_reloc. */
252b5132
RH
5368
5369 switch (fixP->fx_r_type)
5370 {
5371 case BFD_RELOC_ARM_IMMEDIATE:
5372 newimm = validate_immediate (value);
5373 temp = md_chars_to_number (buf, INSN_SIZE);
5374
5375 /* If the instruction will fail, see if we can fix things up by
5376 changing the opcode. */
5377 if (newimm == (unsigned int) FAIL
5378 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
5379 {
5380 as_bad_where (fixP->fx_file, fixP->fx_line,
11450271 5381 _("invalid constant (%lx) after fixup"),
3d103319 5382 (unsigned long) value);
252b5132
RH
5383 break;
5384 }
5385
5386 newimm |= (temp & 0xfffff000);
5387 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
5388 break;
5389
49a5575c
NC
5390 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
5391 {
5392 unsigned int highpart = 0;
5393 unsigned int newinsn = 0xe1a00000; /* nop */
5394 newimm = validate_immediate (value);
5395 temp = md_chars_to_number (buf, INSN_SIZE);
5396
5397 /* If the instruction will fail, see if we can fix things up by
5398 changing the opcode. */
5399 if (newimm == (unsigned int) FAIL
5400 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
5401 {
5402 /* No ? OK - try using two ADD instructions to generate the value. */
5403 newimm = validate_immediate_twopart (value, & highpart);
5404
5405 /* Yes - then make sure that the second instruction is also an add. */
5406 if (newimm != (unsigned int) FAIL)
5407 newinsn = temp;
5408 /* Still No ? Try using a negated value. */
5409 else if (validate_immediate_twopart (- value, & highpart) != (unsigned int) FAIL)
5410 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
5411 /* Otherwise - give up. */
5412 else
5413 {
5414 as_bad_where (fixP->fx_file, fixP->fx_line,
11450271 5415 _("Unable to compute ADRL instructions for PC offset of 0x%x"), value);
49a5575c
NC
5416 break;
5417 }
5418
5419 /* Replace the first operand in the 2nd instruction (which is the PC)
5420 with the destination register. We have already added in the PC in the
5421 first instruction and we do not want to do it again. */
5422 newinsn &= ~ 0xf0000;
5423 newinsn |= ((newinsn & 0x0f000) << 4);
5424 }
5425
5426 newimm |= (temp & 0xfffff000);
5427 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
5428
5429 highpart |= (newinsn & 0xfffff000);
5430 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
5431 }
5432 break;
5433
5434 case BFD_RELOC_ARM_OFFSET_IMM:
252b5132 5435 sign = value >= 0;
276b1dc2
NC
5436
5437 if (value < 0)
5438 value = - value;
5439
5440 if (validate_offset_imm (value, 0) == FAIL)
252b5132 5441 {
50f4163f
NC
5442 as_bad_where (fixP->fx_file, fixP->fx_line,
5443 _("bad immediate value for offset (%ld)"), (long) value);
252b5132
RH
5444 break;
5445 }
252b5132
RH
5446
5447 newval = md_chars_to_number (buf, INSN_SIZE);
5448 newval &= 0xff7ff000;
5449 newval |= value | (sign ? INDEX_UP : 0);
5450 md_number_to_chars (buf, newval, INSN_SIZE);
5451 break;
5452
5453 case BFD_RELOC_ARM_OFFSET_IMM8:
5454 case BFD_RELOC_ARM_HWLITERAL:
5455 sign = value >= 0;
276b1dc2
NC
5456
5457 if (value < 0)
5458 value = - value;
5459
5460 if (validate_offset_imm (value, 1) == FAIL)
252b5132
RH
5461 {
5462 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
5463 as_bad_where (fixP->fx_file, fixP->fx_line,
11450271 5464 _("invalid literal constant: pool needs to be closer"));
252b5132 5465 else
50f4163f
NC
5466 as_bad (_("bad immediate value for half-word offset (%ld)"),
5467 (long) value);
252b5132
RH
5468 break;
5469 }
5470
252b5132
RH
5471 newval = md_chars_to_number (buf, INSN_SIZE);
5472 newval &= 0xff7ff0f0;
3d103319 5473 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
252b5132
RH
5474 md_number_to_chars (buf, newval, INSN_SIZE);
5475 break;
5476
5477 case BFD_RELOC_ARM_LITERAL:
5478 sign = value >= 0;
276b1dc2 5479
252b5132 5480 if (value < 0)
276b1dc2 5481 value = - value;
252b5132 5482
276b1dc2 5483 if (validate_offset_imm (value, 0) == FAIL)
252b5132
RH
5484 {
5485 as_bad_where (fixP->fx_file, fixP->fx_line,
11450271 5486 _("invalid literal constant: pool needs to be closer"));
252b5132
RH
5487 break;
5488 }
5489
5490 newval = md_chars_to_number (buf, INSN_SIZE);
5491 newval &= 0xff7ff000;
5492 newval |= value | (sign ? INDEX_UP : 0);
5493 md_number_to_chars (buf, newval, INSN_SIZE);
5494 break;
5495
5496 case BFD_RELOC_ARM_SHIFT_IMM:
5497 newval = md_chars_to_number (buf, INSN_SIZE);
5498 if (((unsigned long) value) > 32
5499 || (value == 32
5500 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
5501 {
5502 as_bad_where (fixP->fx_file, fixP->fx_line,
5503 _("shift expression is too large"));
5504 break;
5505 }
5506
5507 if (value == 0)
5508 newval &= ~0x60; /* Shifts of zero must be done as lsl */
5509 else if (value == 32)
5510 value = 0;
5511 newval &= 0xfffff07f;
5512 newval |= (value & 0x1f) << 7;
5513 md_number_to_chars (buf, newval , INSN_SIZE);
5514 break;
5515
5516 case BFD_RELOC_ARM_SWI:
5517 if (arm_data->thumb_mode)
5518 {
5519 if (((unsigned long) value) > 0xff)
5520 as_bad_where (fixP->fx_file, fixP->fx_line,
5521 _("Invalid swi expression"));
5522 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
5523 newval |= value;
5524 md_number_to_chars (buf, newval, THUMB_SIZE);
5525 }
5526 else
5527 {
5528 if (((unsigned long) value) > 0x00ffffff)
5529 as_bad_where (fixP->fx_file, fixP->fx_line,
5530 _("Invalid swi expression"));
5531 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
5532 newval |= value;
5533 md_number_to_chars (buf, newval , INSN_SIZE);
5534 }
5535 break;
5536
5537 case BFD_RELOC_ARM_MULTI:
5538 if (((unsigned long) value) > 0xffff)
5539 as_bad_where (fixP->fx_file, fixP->fx_line,
5540 _("Invalid expression in load/store multiple"));
5541 newval = value | md_chars_to_number (buf, INSN_SIZE);
5542 md_number_to_chars (buf, newval, INSN_SIZE);
5543 break;
5544
5545 case BFD_RELOC_ARM_PCREL_BRANCH:
5546 newval = md_chars_to_number (buf, INSN_SIZE);
661e4995 5547
252b5132 5548#ifdef OBJ_ELF
252b5132
RH
5549 if (! target_oabi)
5550 value = fixP->fx_offset;
252b5132 5551#endif
661e4995 5552 value = (value >> 2) & 0x00ffffff;
252b5132
RH
5553 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
5554 newval = value | (newval & 0xff000000);
5555 md_number_to_chars (buf, newval, INSN_SIZE);
5556 break;
5557
92a66162 5558
252b5132
RH
5559 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* conditional branch */
5560 newval = md_chars_to_number (buf, THUMB_SIZE);
5561 {
5562 addressT diff = (newval & 0xff) << 1;
5563 if (diff & 0x100)
5564 diff |= ~0xff;
5565
5566 value += diff;
5567 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
5568 as_bad_where (fixP->fx_file, fixP->fx_line,
5569 _("Branch out of range"));
5570 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
5571 }
5572 md_number_to_chars (buf, newval, THUMB_SIZE);
5573 break;
5574
5575 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* unconditional branch */
5576 newval = md_chars_to_number (buf, THUMB_SIZE);
5577 {
5578 addressT diff = (newval & 0x7ff) << 1;
5579 if (diff & 0x800)
5580 diff |= ~0x7ff;
5581
5582 value += diff;
5583 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
5584 as_bad_where (fixP->fx_file, fixP->fx_line,
5585 _("Branch out of range"));
5586 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
5587 }
5588 md_number_to_chars (buf, newval, THUMB_SIZE);
5589 break;
5590
5591 case BFD_RELOC_THUMB_PCREL_BRANCH23:
5592 {
5593 offsetT newval2;
5594 addressT diff;
5595
5596 newval = md_chars_to_number (buf, THUMB_SIZE);
5597 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
5598 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
5599 if (diff & 0x400000)
5600 diff |= ~0x3fffff;
ae5ad4ad
NC
5601#ifdef OBJ_ELF
5602 value = fixP->fx_offset;
5603#endif
252b5132
RH
5604 value += diff;
5605 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
5606 as_bad_where (fixP->fx_file, fixP->fx_line,
5607 _("Branch with link out of range"));
5608
5609 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
5610 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
5611 md_number_to_chars (buf, newval, THUMB_SIZE);
5612 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
5613 }
5614 break;
5615
5616 case BFD_RELOC_8:
5617 if (fixP->fx_done || fixP->fx_pcrel)
5618 md_number_to_chars (buf, value, 1);
5619#ifdef OBJ_ELF
5620 else if (!target_oabi)
5621 {
5622 value = fixP->fx_offset;
5623 md_number_to_chars (buf, value, 1);
5624 }
5625#endif
5626 break;
5627
5628 case BFD_RELOC_16:
5629 if (fixP->fx_done || fixP->fx_pcrel)
5630 md_number_to_chars (buf, value, 2);
5631#ifdef OBJ_ELF
5632 else if (!target_oabi)
5633 {
5634 value = fixP->fx_offset;
5635 md_number_to_chars (buf, value, 2);
5636 }
5637#endif
5638 break;
5639
5640#ifdef OBJ_ELF
5641 case BFD_RELOC_ARM_GOT32:
5642 case BFD_RELOC_ARM_GOTOFF:
5643 md_number_to_chars (buf, 0, 4);
5644 break;
5645#endif
5646
5647 case BFD_RELOC_RVA:
5648 case BFD_RELOC_32:
5649 if (fixP->fx_done || fixP->fx_pcrel)
5650 md_number_to_chars (buf, value, 4);
5651#ifdef OBJ_ELF
5652 else if (!target_oabi)
5653 {
5654 value = fixP->fx_offset;
5655 md_number_to_chars (buf, value, 4);
5656 }
5657#endif
5658 break;
5659
5660#ifdef OBJ_ELF
5661 case BFD_RELOC_ARM_PLT32:
5662 /* It appears the instruction is fully prepared at this point. */
5663 break;
5664#endif
5665
5666 case BFD_RELOC_ARM_GOTPC:
5667 md_number_to_chars (buf, value, 4);
5668 break;
5669
5670 case BFD_RELOC_ARM_CP_OFF_IMM:
5671 sign = value >= 0;
5672 if (value < -1023 || value > 1023 || (value & 3))
5673 as_bad_where (fixP->fx_file, fixP->fx_line,
5674 _("Illegal value for co-processor offset"));
5675 if (value < 0)
5676 value = -value;
5677 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
5678 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
5679 md_number_to_chars (buf, newval , INSN_SIZE);
5680 break;
5681
5682 case BFD_RELOC_ARM_THUMB_OFFSET:
5683 newval = md_chars_to_number (buf, THUMB_SIZE);
5684 /* Exactly what ranges, and where the offset is inserted depends on
5685 the type of instruction, we can establish this from the top 4 bits */
5686 switch (newval >> 12)
5687 {
5688 case 4: /* PC load */
5689 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
5690 forced to zero for these loads, so we will need to round
5691 up the offset if the instruction address is not word
5692 aligned (since the final address produced must be, and
5693 we can only describe word-aligned immediate offsets). */
5694
5695 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
5696 as_bad_where (fixP->fx_file, fixP->fx_line,
5697 _("Invalid offset, target not word aligned (0x%08X)"),
5698 (unsigned int)(fixP->fx_frag->fr_address + fixP->fx_where + value));
5699
5700 if ((value + 2) & ~0x3fe)
5701 as_bad_where (fixP->fx_file, fixP->fx_line,
50f4163f 5702 _("Invalid offset, value too big (0x%08X)"), value);
252b5132
RH
5703
5704 /* Round up, since pc will be rounded down. */
5705 newval |= (value + 2) >> 2;
5706 break;
5707
5708 case 9: /* SP load/store */
5709 if (value & ~0x3fc)
5710 as_bad_where (fixP->fx_file, fixP->fx_line,
50f4163f 5711 _("Invalid offset, value too big (0x%08X)"), value);
252b5132
RH
5712 newval |= value >> 2;
5713 break;
5714
5715 case 6: /* Word load/store */
5716 if (value & ~0x7c)
5717 as_bad_where (fixP->fx_file, fixP->fx_line,
50f4163f 5718 _("Invalid offset, value too big (0x%08X)"), value);
252b5132
RH
5719 newval |= value << 4; /* 6 - 2 */
5720 break;
5721
5722 case 7: /* Byte load/store */
5723 if (value & ~0x1f)
5724 as_bad_where (fixP->fx_file, fixP->fx_line,
50f4163f 5725 _("Invalid offset, value too big (0x%08X)"), value);
252b5132
RH
5726 newval |= value << 6;
5727 break;
5728
5729 case 8: /* Halfword load/store */
5730 if (value & ~0x3e)
5731 as_bad_where (fixP->fx_file, fixP->fx_line,
50f4163f 5732 _("Invalid offset, value too big (0x%08X)"), value);
252b5132
RH
5733 newval |= value << 5; /* 6 - 1 */
5734 break;
5735
5736 default:
5737 as_bad_where (fixP->fx_file, fixP->fx_line,
3d103319
ILT
5738 "Unable to process relocation for thumb opcode: %lx",
5739 (unsigned long) newval);
252b5132
RH
5740 break;
5741 }
5742 md_number_to_chars (buf, newval, THUMB_SIZE);
5743 break;
5744
5745 case BFD_RELOC_ARM_THUMB_ADD:
5746 /* This is a complicated relocation, since we use it for all of
5747 the following immediate relocations:
5748 3bit ADD/SUB
5749 8bit ADD/SUB
5750 9bit ADD/SUB SP word-aligned
5751 10bit ADD PC/SP word-aligned
5752
5753 The type of instruction being processed is encoded in the
5754 instruction field:
5755 0x8000 SUB
5756 0x00F0 Rd
5757 0x000F Rs
5758 */
5759 newval = md_chars_to_number (buf, THUMB_SIZE);
5760 {
5761 int rd = (newval >> 4) & 0xf;
5762 int rs = newval & 0xf;
5763 int subtract = newval & 0x8000;
5764
5765 if (rd == REG_SP)
5766 {
5767 if (value & ~0x1fc)
5768 as_bad_where (fixP->fx_file, fixP->fx_line,
5769 _("Invalid immediate for stack address calculation"));
5770 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
5771 newval |= value >> 2;
5772 }
5773 else if (rs == REG_PC || rs == REG_SP)
5774 {
5775 if (subtract ||
5776 value & ~0x3fc)
5777 as_bad_where (fixP->fx_file, fixP->fx_line,
3d103319
ILT
5778 _("Invalid immediate for address calculation (value = 0x%08lX)"),
5779 (unsigned long) value);
252b5132
RH
5780 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
5781 newval |= rd << 8;
5782 newval |= value >> 2;
5783 }
5784 else if (rs == rd)
5785 {
5786 if (value & ~0xff)
5787 as_bad_where (fixP->fx_file, fixP->fx_line,
5788 _("Invalid 8bit immediate"));
5789 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
5790 newval |= (rd << 8) | value;
5791 }
5792 else
5793 {
5794 if (value & ~0x7)
5795 as_bad_where (fixP->fx_file, fixP->fx_line,
5796 _("Invalid 3bit immediate"));
5797 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
5798 newval |= rd | (rs << 3) | (value << 6);
5799 }
5800 }
5801 md_number_to_chars (buf, newval , THUMB_SIZE);
5802 break;
5803
5804 case BFD_RELOC_ARM_THUMB_IMM:
5805 newval = md_chars_to_number (buf, THUMB_SIZE);
5806 switch (newval >> 11)
5807 {
5808 case 0x04: /* 8bit immediate MOV */
5809 case 0x05: /* 8bit immediate CMP */
5810 if (value < 0 || value > 255)
5811 as_bad_where (fixP->fx_file, fixP->fx_line,
3d103319
ILT
5812 _("Invalid immediate: %ld is too large"),
5813 (long) value);
252b5132
RH
5814 newval |= value;
5815 break;
5816
5817 default:
5818 abort ();
5819 }
5820 md_number_to_chars (buf, newval , THUMB_SIZE);
5821 break;
5822
5823 case BFD_RELOC_ARM_THUMB_SHIFT:
5824 /* 5bit shift value (0..31) */
5825 if (value < 0 || value > 31)
5826 as_bad_where (fixP->fx_file, fixP->fx_line,
3d103319 5827 _("Illegal Thumb shift value: %ld"), (long) value);
252b5132
RH
5828 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
5829 newval |= value << 6;
5830 md_number_to_chars (buf, newval , THUMB_SIZE);
5831 break;
5832
5833 case BFD_RELOC_VTABLE_INHERIT:
5834 case BFD_RELOC_VTABLE_ENTRY:
5835 fixP->fx_done = 0;
5836 return 1;
5837
5838 case BFD_RELOC_NONE:
5839 default:
5840 as_bad_where (fixP->fx_file, fixP->fx_line,
11450271 5841 _("Bad relocation fixup type (%d)"), fixP->fx_r_type);
252b5132
RH
5842 }
5843
5844 return 1;
5845}
5846
5847/* Translate internal representation of relocation info to BFD target
5848 format. */
5849arelent *
5850tc_gen_reloc (section, fixp)
5851 asection * section;
5852 fixS * fixp;
5853{
5854 arelent * reloc;
5855 bfd_reloc_code_real_type code;
5856
5857 reloc = (arelent *) xmalloc (sizeof (arelent));
5858
174419c1
ILT
5859 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
5860 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
252b5132
RH
5861 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5862
5863 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
5864#ifndef OBJ_ELF
5865 if (fixp->fx_pcrel == 0)
5866 reloc->addend = fixp->fx_offset;
5867 else
5868 reloc->addend = fixp->fx_offset = reloc->address;
5869#else /* OBJ_ELF */
5870 reloc->addend = fixp->fx_offset;
5871#endif
5872
5873 switch (fixp->fx_r_type)
5874 {
5875 case BFD_RELOC_8:
5876 if (fixp->fx_pcrel)
5877 {
5878 code = BFD_RELOC_8_PCREL;
5879 break;
5880 }
5881
5882 case BFD_RELOC_16:
5883 if (fixp->fx_pcrel)
5884 {
5885 code = BFD_RELOC_16_PCREL;
5886 break;
5887 }
5888
5889 case BFD_RELOC_32:
5890 if (fixp->fx_pcrel)
5891 {
5892 code = BFD_RELOC_32_PCREL;
5893 break;
5894 }
5895
5896 case BFD_RELOC_ARM_PCREL_BRANCH:
5897 case BFD_RELOC_RVA:
5898 case BFD_RELOC_THUMB_PCREL_BRANCH9:
5899 case BFD_RELOC_THUMB_PCREL_BRANCH12:
5900 case BFD_RELOC_THUMB_PCREL_BRANCH23:
5901 case BFD_RELOC_VTABLE_ENTRY:
5902 case BFD_RELOC_VTABLE_INHERIT:
5903 code = fixp->fx_r_type;
5904 break;
5905
5906 case BFD_RELOC_ARM_LITERAL:
5907 case BFD_RELOC_ARM_HWLITERAL:
5908 /* If this is called then the a literal has been referenced across
2f992c04 5909 a section boundary - possibly due to an implicit dump */
252b5132 5910 as_bad_where (fixp->fx_file, fixp->fx_line,
2f992c04 5911 _("Literal referenced across section boundary (Implicit dump?)"));
252b5132
RH
5912 return NULL;
5913
252b5132
RH
5914#ifdef OBJ_ELF
5915 case BFD_RELOC_ARM_GOT32:
5916 case BFD_RELOC_ARM_GOTOFF:
5917 case BFD_RELOC_ARM_PLT32:
5918 code = fixp->fx_r_type;
5919 break;
5920#endif
5921
5922 case BFD_RELOC_ARM_IMMEDIATE:
5923 as_bad_where (fixp->fx_file, fixp->fx_line,
5924 _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
5925 fixp->fx_r_type);
5926 return NULL;
5927
49a5575c
NC
5928 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
5929 as_bad_where (fixp->fx_file, fixp->fx_line,
5930 _("ADRL used for a symbol not defined in the same file"),
5931 fixp->fx_r_type);
5932 return NULL;
5933
252b5132
RH
5934 case BFD_RELOC_ARM_OFFSET_IMM:
5935 as_bad_where (fixp->fx_file, fixp->fx_line,
5936 _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
5937 fixp->fx_r_type);
5938 return NULL;
5939
5940 default:
5941 {
5942 char * type;
5943 switch (fixp->fx_r_type)
5944 {
5945 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
5946 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
5947 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
5948 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
5949 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
5950 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
5951 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
5952 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
5953 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
5954 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
5955 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
ae5ad4ad 5956 default: type = _("<unknown>"); break;
252b5132
RH
5957 }
5958 as_bad_where (fixp->fx_file, fixp->fx_line,
5959 _("Can not represent %s relocation in this object file format (%d)"),
5960 type, fixp->fx_pcrel);
5961 return NULL;
5962 }
5963 }
5964
5965#ifdef OBJ_ELF
5966 if (code == BFD_RELOC_32_PCREL
5967 && GOT_symbol
5968 && fixp->fx_addsy == GOT_symbol)
a8aed0fb
UD
5969 {
5970 code = BFD_RELOC_ARM_GOTPC;
5971 reloc->addend = fixp->fx_offset = reloc->address;
5972 }
252b5132
RH
5973#endif
5974
5975 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
5976
5977 if (reloc->howto == NULL)
5978 {
5979 as_bad_where (fixp->fx_file, fixp->fx_line,
5980 _("Can not represent %s relocation in this object file format"),
5981 bfd_get_reloc_code_name (code));
5982 return NULL;
5983 }
5984
c8d259f7
CM
5985 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
5986 vtable entry to be used in the relocation's section offset. */
5987 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5988 reloc->address = fixp->fx_offset;
5989
252b5132
RH
5990 return reloc;
5991}
5992
5993int
5994md_estimate_size_before_relax (fragP, segtype)
5995 fragS * fragP;
5996 segT segtype;
5997{
5998 as_fatal (_("md_estimate_size_before_relax\n"));
5999 return 1;
6000}
6001
6002static void
49a5575c 6003output_inst PARAMS ((void))
252b5132
RH
6004{
6005 char * to = NULL;
6006
6007 if (inst.error)
6008 {
6009 as_bad (inst.error);
6010 return;
6011 }
6012
6013 to = frag_more (inst.size);
ae5ad4ad 6014
252b5132
RH
6015 if (thumb_mode && (inst.size > THUMB_SIZE))
6016 {
6017 assert (inst.size == (2 * THUMB_SIZE));
6018 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
49a5575c
NC
6019 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
6020 }
6021 else if (inst.size > INSN_SIZE)
6022 {
6023 assert (inst.size == (2 * INSN_SIZE));
6024 md_number_to_chars (to, inst.instruction, INSN_SIZE);
6025 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
252b5132
RH
6026 }
6027 else
6028 md_number_to_chars (to, inst.instruction, inst.size);
6029
6030 if (inst.reloc.type != BFD_RELOC_NONE)
6031 fix_new_arm (frag_now, to - frag_now->fr_literal,
6032 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
6033 inst.reloc.type);
6034
6035 return;
6036}
6037
6038void
6039md_assemble (str)
6040 char * str;
6041{
6042 char c;
6043 char * p;
6044 char * q;
6045 char * start;
6046
6047 /* Align the instruction.
6048 This may not be the right thing to do but ... */
6049 /* arm_align (2, 0); */
6050 listing_prev_line (); /* Defined in listing.h */
6051
6052 /* Align the previous label if needed. */
6053 if (last_label_seen != NULL)
6054 {
174419c1 6055 symbol_set_frag (last_label_seen, frag_now);
252b5132
RH
6056 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
6057 S_SET_SEGMENT (last_label_seen, now_seg);
6058 }
6059
6060 memset (&inst, '\0', sizeof (inst));
6061 inst.reloc.type = BFD_RELOC_NONE;
6062
ae5ad4ad 6063 skip_whitespace (str);
49a5575c 6064
252b5132
RH
6065 /* Scan up to the end of the op-code, which must end in white space or
6066 end of string. */
6067 for (start = p = str; *p != '\0'; p++)
6068 if (*p == ' ')
6069 break;
6070
6071 if (p == str)
6072 {
6073 as_bad (_("No operator -- statement `%s'\n"), str);
6074 return;
6075 }
6076
6077 if (thumb_mode)
6078 {
49a5575c 6079 CONST struct thumb_opcode * opcode;
252b5132
RH
6080
6081 c = *p;
6082 *p = '\0';
6083 opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
6084 *p = c;
49a5575c 6085
252b5132
RH
6086 if (opcode)
6087 {
92a66162 6088 /* Check that this instruction is supported for this CPU. */
a64bcdd8 6089 if (thumb_mode == 1 && (opcode->variants & cpu_variant) == 0)
92a66162
DL
6090 {
6091 as_bad (_("selected processor does not support this opcode"));
6092 return;
6093 }
6094
252b5132
RH
6095 inst.instruction = opcode->value;
6096 inst.size = opcode->size;
6097 (*opcode->parms)(p);
49a5575c 6098 output_inst ();
252b5132
RH
6099 return;
6100 }
6101 }
6102 else
6103 {
49a5575c 6104 CONST struct asm_opcode * opcode;
92a66162 6105 unsigned long cond_code;
252b5132
RH
6106
6107 inst.size = INSN_SIZE;
6108 /* p now points to the end of the opcode, probably white space, but we
6109 have to break the opcode up in case it contains condionals and flags;
6110 keep trying with progressively smaller basic instructions until one
ae5ad4ad 6111 matches, or we run out of opcode. */
252b5132
RH
6112 q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
6113 for (; q != str; q--)
6114 {
6115 c = *q;
6116 *q = '\0';
6117 opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
6118 *q = c;
49a5575c 6119
252b5132
RH
6120 if (opcode && opcode->template)
6121 {
6122 unsigned long flag_bits = 0;
49a5575c 6123 char * r;
252b5132 6124
ae5ad4ad 6125 /* Check that this instruction is supported for this CPU. */
252b5132
RH
6126 if ((opcode->variants & cpu_variant) == 0)
6127 goto try_shorter;
6128
6129 inst.instruction = opcode->value;
ae5ad4ad 6130 if (q == p) /* Just a simple opcode. */
252b5132 6131 {
92a66162
DL
6132 if (opcode->comp_suffix)
6133 {
6134 if (*opcode->comp_suffix != '\0')
858f4ff6 6135 as_bad (_("Opcode `%s' must have suffix from list: <%s>"),
92a66162
DL
6136 str, opcode->comp_suffix);
6137 else
6138 /* Not a conditional instruction. */
6139 (*opcode->parms)(q, 0);
6140 }
252b5132
RH
6141 else
6142 {
92a66162 6143 /* A conditional instruction with default condition. */
252b5132
RH
6144 inst.instruction |= COND_ALWAYS;
6145 (*opcode->parms)(q, 0);
6146 }
49a5575c 6147 output_inst ();
252b5132
RH
6148 return;
6149 }
6150
92a66162 6151 /* Not just a simple opcode. Check if extra is a conditional. */
252b5132
RH
6152 r = q;
6153 if (p - r >= 2)
6154 {
6155 CONST struct asm_cond *cond;
6156 char d = *(r + 2);
6157
6158 *(r + 2) = '\0';
6159 cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
6160 *(r + 2) = d;
6161 if (cond)
6162 {
6163 if (cond->value == 0xf0000000)
6164 as_tsktsk (
6165_("Warning: Use of the 'nv' conditional is deprecated\n"));
6166
92a66162 6167 cond_code = cond->value;
252b5132
RH
6168 r += 2;
6169 }
6170 else
92a66162 6171 cond_code = COND_ALWAYS;
252b5132
RH
6172 }
6173 else
92a66162
DL
6174 cond_code = COND_ALWAYS;
6175
92a66162
DL
6176 /* Apply the conditional, or complain it's not allowed. */
6177 if (opcode->comp_suffix && *opcode->comp_suffix == '\0')
6178 {
6179 /* Instruction isn't conditional */
6180 if (cond_code != COND_ALWAYS)
6181 {
6182 as_bad (_("Opcode `%s' is unconditional\n"), str);
6183 return;
6184 }
6185 }
6186 else
6187 /* Instruction is conditional: set the condition into it. */
6188 inst.instruction |= cond_code;
6189
252b5132 6190
ae5ad4ad
NC
6191 /* If there is a compulsory suffix, it should come here, before
6192 any optional flags. */
92a66162 6193 if (opcode->comp_suffix && *opcode->comp_suffix != '\0')
252b5132
RH
6194 {
6195 CONST char *s = opcode->comp_suffix;
6196
6197 while (*s)
6198 {
6199 inst.suffix++;
6200 if (*r == *s)
6201 break;
6202 s++;
6203 }
6204
6205 if (*s == '\0')
6206 {
6207 as_bad (_("Opcode `%s' must have suffix from <%s>\n"), str,
6208 opcode->comp_suffix);
6209 return;
6210 }
6211
6212 r++;
6213 }
6214
6215 /* The remainder, if any should now be flags for the instruction;
6216 Scan these checking each one found with the opcode. */
6217 if (r != p)
6218 {
6219 char d;
6220 CONST struct asm_flg *flag = opcode->flags;
6221
6222 if (flag)
6223 {
6224 int flagno;
6225
6226 d = *p;
6227 *p = '\0';
6228
6229 for (flagno = 0; flag[flagno].template; flagno++)
6230 {
6231 if (streq (r, flag[flagno].template))
6232 {
6233 flag_bits |= flag[flagno].set_bits;
6234 break;
6235 }
6236 }
6237
6238 *p = d;
6239 if (! flag[flagno].template)
6240 goto try_shorter;
6241 }
6242 else
6243 goto try_shorter;
6244 }
6245
6246 (*opcode->parms) (p, flag_bits);
49a5575c 6247 output_inst ();
252b5132
RH
6248 return;
6249 }
6250
6251 try_shorter:
6252 ;
6253 }
6254 }
6255
6256 /* It wasn't an instruction, but it might be a register alias of the form
ae5ad4ad 6257 alias .req reg */
252b5132 6258 q = p;
ae5ad4ad 6259 skip_whitespace (q);
252b5132
RH
6260
6261 c = *p;
6262 *p = '\0';
6263
6264 if (*q && !strncmp (q, ".req ", 4))
6265 {
6266 int reg;
6267 char * copy_of_str = str;
6268 char * r;
6269
6270 q += 4;
ae5ad4ad 6271 skip_whitespace (q);
252b5132
RH
6272
6273 for (r = q; *r != '\0'; r++)
6274 if (*r == ' ')
6275 break;
6276
6277 if (r != q)
6278 {
6279 int regnum;
6280 char d = *r;
6281
6282 *r = '\0';
6283 regnum = arm_reg_parse (& q);
6284 *r = d;
6285
6286 reg = arm_reg_parse (& str);
6287
6288 if (reg == FAIL)
6289 {
6290 if (regnum != FAIL)
11450271 6291 insert_reg_alias (str, regnum);
252b5132 6292 else
92a66162 6293 as_warn (_("register '%s' does not exist\n"), q);
252b5132
RH
6294 }
6295 else if (regnum != FAIL)
6296 {
6297 if (reg != regnum)
6298 as_warn (_("ignoring redefinition of register alias '%s'"), copy_of_str );
6299
ae5ad4ad 6300 /* Do not warn about redefinitions to the same alias. */
252b5132
RH
6301 }
6302 else
6303 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
6304 copy_of_str, q);
6305 }
6306 else
6307 as_warn (_("ignoring incomplete .req pseuso op"));
6308
6309 *p = c;
6310 return;
6311 }
6312
6313 *p = c;
6314 as_bad (_("bad instruction `%s'"), start);
6315}
6316
6317/*
6318 * md_parse_option
6319 * Invocation line includes a switch not recognized by the base assembler.
6320 * See if it's a processor-specific option. These are:
6321 * Cpu variants, the arm part is optional:
6322 * -m[arm]1 Currently not supported.
6323 * -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
6324 * -m[arm]3 Arm 3 processor
6325 * -m[arm]6[xx], Arm 6 processors
6326 * -m[arm]7[xx][t][[d]m] Arm 7 processors
49a5575c
NC
6327 * -m[arm]8[10] Arm 8 processors
6328 * -m[arm]9[20][tdmi] Arm 9 processors
c1d3c45e 6329 * -mstrongarm[110[0]] StrongARM processors
92a66162 6330 * -m[arm]v[2345] Arm architectures
252b5132
RH
6331 * -mall All (except the ARM1)
6332 * FP variants:
6333 * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
6334 * -mfpe-old (No float load/store multiples)
6335 * -mno-fpu Disable all floating point instructions
6336 * Run-time endian selection:
6337 * -EB big endian cpu
6338 * -EL little endian cpu
6339 * ARM Procedure Calling Standard:
6340 * -mapcs-32 32 bit APCS
6341 * -mapcs-26 26 bit APCS
6342 * -mapcs-float Pass floats in float regs
6343 * -mapcs-reentrant Position independent code
6344 * -mthumb-interwork Code supports Arm/Thumb interworking
6345 * -moabi Old ELF ABI
6346 */
6347
6348CONST char * md_shortopts = "m:k";
6349struct option md_longopts[] =
6350{
6351#ifdef ARM_BI_ENDIAN
6352#define OPTION_EB (OPTION_MD_BASE + 0)
6353 {"EB", no_argument, NULL, OPTION_EB},
6354#define OPTION_EL (OPTION_MD_BASE + 1)
6355 {"EL", no_argument, NULL, OPTION_EL},
6356#ifdef OBJ_ELF
6357#define OPTION_OABI (OPTION_MD_BASE +2)
6358 {"oabi", no_argument, NULL, OPTION_OABI},
6359#endif
6360#endif
6361 {NULL, no_argument, NULL, 0}
6362};
6363size_t md_longopts_size = sizeof (md_longopts);
6364
6365int
6366md_parse_option (c, arg)
6367 int c;
6368 char * arg;
6369{
6370 char * str = arg;
6371
6372 switch (c)
6373 {
6374#ifdef ARM_BI_ENDIAN
6375 case OPTION_EB:
6376 target_big_endian = 1;
6377 break;
6378 case OPTION_EL:
6379 target_big_endian = 0;
6380 break;
6381#endif
6382
6383 case 'm':
6384 switch (*str)
6385 {
6386 case 'f':
6387 if (streq (str, "fpa10"))
6388 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10;
6389 else if (streq (str, "fpa11"))
6390 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11;
6391 else if (streq (str, "fpe-old"))
6392 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE;
6393 else
6394 goto bad;
6395 break;
6396
6397 case 'n':
6398 if (streq (str, "no-fpu"))
6399 cpu_variant &= ~FPU_ALL;
6400 break;
6401
6402#ifdef OBJ_ELF
6403 case 'o':
6404 if (streq (str, "oabi"))
6405 target_oabi = true;
6406 break;
6407#endif
6408
6409 case 't':
6410 /* Limit assembler to generating only Thumb instructions: */
6411 if (streq (str, "thumb"))
6412 {
6413 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB;
6414 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
6415 thumb_mode = 1;
6416 }
6417 else if (streq (str, "thumb-interwork"))
6418 {
858f4ff6
NC
6419 if ((cpu_variant & ARM_THUMB) == 0)
6420 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T;
252b5132
RH
6421#if defined OBJ_COFF || defined OBJ_ELF
6422 support_interwork = true;
6423#endif
6424 }
6425 else
6426 goto bad;
6427 break;
6428
6429 default:
6430 if (streq (str, "all"))
6431 {
6432 cpu_variant = ARM_ALL | FPU_ALL;
6433 return 1;
6434 }
6435#if defined OBJ_COFF || defined OBJ_ELF
6436 if (! strncmp (str, "apcs-", 5))
6437 {
6438 /* GCC passes on all command line options starting "-mapcs-..."
6439 to us, so we must parse them here. */
6440
6441 str += 5;
6442
6443 if (streq (str, "32"))
6444 {
6445 uses_apcs_26 = false;
6446 return 1;
6447 }
6448 else if (streq (str, "26"))
6449 {
6450 uses_apcs_26 = true;
6451 return 1;
6452 }
6453 else if (streq (str, "frame"))
6454 {
6455 /* Stack frames are being generated - does not affect
6456 linkage of code. */
6457 return 1;
6458 }
6459 else if (streq (str, "stack-check"))
6460 {
6461 /* Stack checking is being performed - does not affect
6462 linkage, but does require that the functions
6463 __rt_stkovf_split_small and __rt_stkovf_split_big be
6464 present in the final link. */
6465
6466 return 1;
6467 }
6468 else if (streq (str, "float"))
6469 {
6470 /* Floating point arguments are being passed in the floating
6471 point registers. This does affect linking, since this
6472 version of the APCS is incompatible with the version that
6473 passes floating points in the integer registers. */
6474
6475 uses_apcs_float = true;
6476 return 1;
6477 }
6478 else if (streq (str, "reentrant"))
6479 {
6480 /* Reentrant code has been generated. This does affect
6481 linking, since there is no point in linking reentrant/
6482 position independent code with absolute position code. */
6483 pic_code = true;
6484 return 1;
6485 }
6486
6487 as_bad (_("Unrecognised APCS switch -m%s"), arg);
6488 return 0;
6489 }
6490#endif
6491 /* Strip off optional "arm" */
6492 if (! strncmp (str, "arm", 3))
6493 str += 3;
6494
6495 switch (*str)
6496 {
6497 case '1':
6498 if (streq (str, "1"))
6499 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
6500 else
6501 goto bad;
6502 break;
6503
6504 case '2':
6505 if (streq (str, "2"))
6506 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
6507 else if (streq (str, "250"))
6508 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
6509 else
6510 goto bad;
6511 break;
6512
6513 case '3':
6514 if (streq (str, "3"))
6515 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
6516 else
6517 goto bad;
6518 break;
6519
6520 case '6':
6521 switch (strtol (str, NULL, 10))
6522 {
6523 case 6:
6524 case 60:
6525 case 600:
6526 case 610:
6527 case 620:
6528 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
6529 break;
6530 default:
6531 goto bad;
6532 }
6533 break;
6534
6535 case '7':
6536 switch (strtol (str, & str, 10)) /* Eat the processor name */
6537 {
6538 case 7:
6539 case 70:
6540 case 700:
6541 case 710:
b4d0b2b3 6542 case 720:
252b5132
RH
6543 case 7100:
6544 case 7500:
6545 break;
6546 default:
6547 goto bad;
6548 }
6549 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
6550 for (; *str; str++)
6551 {
6552 switch (* str)
6553 {
6554 case 't':
49a5575c 6555 cpu_variant |= (ARM_THUMB | ARM_ARCH_V4);
252b5132
RH
6556 break;
6557
6558 case 'm':
6559 cpu_variant |= ARM_LONGMUL;
6560 break;
6561
6562 case 'f': /* fe => fp enabled cpu. */
6563 if (str[1] == 'e')
6564 ++ str;
6565 else
6566 goto bad;
6567
6568 case 'c': /* Left over from 710c processor name. */
6569 case 'd': /* Debug */
6570 case 'i': /* Embedded ICE */
6571 /* Included for completeness in ARM processor naming. */
6572 break;
6573
6574 default:
6575 goto bad;
6576 }
6577 }
6578 break;
6579
6580 case '8':
6581 if (streq (str, "8") || streq (str, "810"))
49a5575c 6582 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_8 | ARM_ARCH_V4 | ARM_LONGMUL;
252b5132
RH
6583 else
6584 goto bad;
6585 break;
6586
6587 case '9':
6588 if (streq (str, "9"))
49a5575c 6589 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V4 | ARM_LONGMUL | ARM_THUMB;
c1d3c45e 6590 else if (streq (str, "920"))
49a5575c 6591 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V4 | ARM_LONGMUL;
c1d3c45e 6592 else if (streq (str, "920t"))
49a5575c 6593 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V4 | ARM_LONGMUL | ARM_THUMB;
252b5132 6594 else if (streq (str, "9tdmi"))
49a5575c 6595 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V4 | ARM_LONGMUL | ARM_THUMB;
252b5132
RH
6596 else
6597 goto bad;
6598 break;
92a66162 6599
252b5132
RH
6600
6601 case 's':
6602 if (streq (str, "strongarm")
6603 || streq (str, "strongarm110")
6604 || streq (str, "strongarm1100"))
49a5575c 6605 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_8 | ARM_ARCH_V4 | ARM_LONGMUL;
252b5132
RH
6606 else
6607 goto bad;
6608 break;
6609
6610 case 'v':
6611 /* Select variant based on architecture rather than processor */
6612 switch (*++str)
6613 {
6614 case '2':
6615 switch (*++str)
6616 {
6617 case 'a': cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3; break;
6618 case 0: cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2; break;
6619 default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
6620 }
6621 break;
6622
6623 case '3':
6624 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
6625
6626 switch (*++str)
6627 {
6628 case 'm': cpu_variant |= ARM_LONGMUL; break;
6629 case 0: break;
6630 default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
6631 }
6632 break;
6633
6634 case '4':
49a5575c
NC
6635 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4;
6636
6637 switch (*++str)
6638 {
6639 case 't': cpu_variant |= ARM_THUMB; break;
6640 case 0: break;
6641 default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
6642 }
6643 break;
92a66162 6644
49a5575c
NC
6645 case '5':
6646 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V5;
252b5132
RH
6647 switch (*++str)
6648 {
6649 case 't': cpu_variant |= ARM_THUMB; break;
92a66162 6650 case 'e': cpu_variant |= ARM_EXT_V5E; break;
252b5132
RH
6651 case 0: break;
6652 default: as_bad (_("Invalid architecture variant -m%s"), arg); break;
6653 }
6654 break;
6655
6656 default:
6657 as_bad (_("Invalid architecture variant -m%s"), arg);
6658 break;
6659 }
6660 break;
6661
6662 default:
6663 bad:
6664 as_bad (_("Invalid processor variant -m%s"), arg);
6665 return 0;
6666 }
6667 }
6668 break;
6669
325188ec 6670#if defined OBJ_ELF || defined OBJ_COFF
252b5132
RH
6671 case 'k':
6672 pic_code = 1;
6673 break;
325188ec 6674#endif
252b5132
RH
6675
6676 default:
6677 return 0;
6678 }
6679
6680 return 1;
6681}
6682
6683void
6684md_show_usage (fp)
6685 FILE * fp;
6686{
6687 fprintf (fp,
6688_("\
6689 ARM Specific Assembler Options:\n\
6690 -m[arm][<processor name>] select processor variant\n\
858f4ff6 6691 -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
252b5132
RH
6692 -mthumb only allow Thumb instructions\n\
6693 -mthumb-interwork mark the assembled code as supporting interworking\n\
6694 -mall allow any instruction\n\
6695 -mfpa10, -mfpa11 select floating point architecture\n\
6696 -mfpe-old don't allow floating-point multiple instructions\n\
6697 -mno-fpu don't allow any floating-point instructions.\n"));
6698 fprintf (fp,
6699_("\
6700 -k generate PIC code.\n"));
6701#if defined OBJ_COFF || defined OBJ_ELF
6702 fprintf (fp,
6703_("\
6704 -mapcs-32, -mapcs-26 specify which ARM Procedure Calling Standard to use\n"));
6705 fprintf (fp,
6706_("\
6707 -mapcs-float floating point args are passed in FP regs\n"));
6708 fprintf (fp,
6709_("\
6710 -mapcs-reentrant the code is position independent/reentrant\n"));
6711 #endif
6712#ifdef OBJ_ELF
6713 fprintf (fp,
6714_("\
6715 -moabi support the old ELF ABI\n"));
6716#endif
6717#ifdef ARM_BI_ENDIAN
6718 fprintf (fp,
6719_("\
6720 -EB assemble code for a big endian cpu\n\
6721 -EL assemble code for a little endian cpu\n"));
6722#endif
6723}
6724
6725/* We need to be able to fix up arbitrary expressions in some statements.
6726 This is so that we can handle symbols that are an arbitrary distance from
6727 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
6728 which returns part of an address in a form which will be valid for
6729 a data instruction. We do this by pushing the expression into a symbol
6730 in the expr_section, and creating a fix for that. */
6731
6732static void
6733fix_new_arm (frag, where, size, exp, pc_rel, reloc)
6734 fragS * frag;
6735 int where;
6736 short int size;
6737 expressionS * exp;
6738 int pc_rel;
6739 int reloc;
6740{
6741 fixS * new_fix;
6742 arm_fix_data * arm_data;
6743
6744 switch (exp->X_op)
6745 {
6746 case O_constant:
6747 case O_symbol:
6748 case O_add:
6749 case O_subtract:
6750 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
6751 break;
6752
6753 default:
6754 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
6755 pc_rel, reloc);
6756 break;
6757 }
6758
6759 /* Mark whether the fix is to a THUMB instruction, or an ARM instruction */
6760 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
6761 new_fix->tc_fix_data = (PTR) arm_data;
6762 arm_data->thumb_mode = thumb_mode;
6763
6764 return;
6765}
6766
6767
2f992c04 6768/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
252b5132
RH
6769void
6770cons_fix_new_arm (frag, where, size, exp)
6771 fragS * frag;
6772 int where;
6773 int size;
6774 expressionS * exp;
6775{
6776 bfd_reloc_code_real_type type;
6777 int pcrel = 0;
6778
6779 /* Pick a reloc ...
6780 *
6781 * @@ Should look at CPU word size.
6782 */
6783 switch (size)
6784 {
6785 case 2:
6786 type = BFD_RELOC_16;
6787 break;
6788 case 4:
6789 default:
6790 type = BFD_RELOC_32;
6791 break;
6792 case 8:
6793 type = BFD_RELOC_64;
6794 break;
6795 }
6796
252b5132
RH
6797 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
6798}
6799
6800/* A good place to do this, although this was probably not intended
ae5ad4ad
NC
6801 for this kind of use. We need to dump the literal pool before
6802 references are made to a null symbol pointer. */
252b5132
RH
6803void
6804arm_cleanup ()
6805{
ae5ad4ad
NC
6806 if (current_poolP == NULL)
6807 return;
6808
6809 subseg_set (text_section, 0); /* Put it at the end of text section. */
6810 s_ltorg (0);
6811 listing_prev_line ();
252b5132
RH
6812}
6813
6814void
6815arm_start_line_hook ()
6816{
6817 last_label_seen = NULL;
6818}
6819
6820void
6821arm_frob_label (sym)
6822 symbolS * sym;
6823{
6824 last_label_seen = sym;
6825
6826 ARM_SET_THUMB (sym, thumb_mode);
6827
6828#if defined OBJ_COFF || defined OBJ_ELF
6829 ARM_SET_INTERWORK (sym, support_interwork);
6830#endif
6831
6832 if (label_is_thumb_function_name)
6833 {
6834 /* When the address of a Thumb function is taken the bottom
6835 bit of that address should be set. This will allow
6836 interworking between Arm and Thumb functions to work
6837 correctly. */
6838
6839 THUMB_SET_FUNC (sym, 1);
6840
6841 label_is_thumb_function_name = false;
6842 }
6843}
6844
6845/* Adjust the symbol table. This marks Thumb symbols as distinct from
6846 ARM ones. */
6847
6848void
6849arm_adjust_symtab ()
6850{
6851#ifdef OBJ_COFF
6852 symbolS * sym;
6853
6854 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
6855 {
6856 if (ARM_IS_THUMB (sym))
6857 {
6858 if (THUMB_IS_FUNC (sym))
6859 {
6860 /* Mark the symbol as a Thumb function. */
6861 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
6862 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
6863 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
6864
6865 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
6866 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
6867 else
6868 as_bad (_("%s: unexpected function type: %d"),
6869 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
6870 }
6871 else switch (S_GET_STORAGE_CLASS (sym))
6872 {
6873 case C_EXT:
6874 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
6875 break;
6876 case C_STAT:
6877 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
6878 break;
6879 case C_LABEL:
6880 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
6881 break;
6882 default: /* do nothing */
6883 break;
6884 }
6885 }
6886
6887 if (ARM_IS_INTERWORK (sym))
155f0fe7 6888 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
252b5132
RH
6889 }
6890#endif
6891#ifdef OBJ_ELF
6892 symbolS * sym;
6893 elf_symbol_type * elf_sym;
6894 char bind;
6895
6896 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
6897 {
6898 if (ARM_IS_THUMB (sym))
6899 {
2f0ca46a
NC
6900 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
6901 bind = ELF_ST_BIND (elf_sym);
6902
6903 /* If it's a .thumb_func, declare it as so, else tag label as .code 16. */
252b5132 6904 if (THUMB_IS_FUNC (sym))
2f0ca46a
NC
6905 elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_TFUNC);
6906 else
6907 elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_16BIT);
252b5132
RH
6908 }
6909 }
6910#endif
6911}
6912
6913int
6914arm_data_in_code ()
6915{
6916 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
6917 {
6918 *input_line_pointer = '/';
6919 input_line_pointer += 5;
6920 *input_line_pointer = 0;
6921 return 1;
6922 }
6923
6924 return 0;
6925}
6926
6927char *
6928arm_canonicalize_symbol_name (name)
6929 char * name;
6930{
6931 int len;
6932
6933 if (thumb_mode && (len = strlen (name)) > 5
6934 && streq (name + len - 5, "/data"))
ae5ad4ad 6935 *(name + len - 5) = 0;
252b5132
RH
6936
6937 return name;
6938}
6939
6940boolean
6941arm_validate_fix (fixP)
6942 fixS * fixP;
6943{
6944 /* If the destination of the branch is a defined symbol which does not have
6945 the THUMB_FUNC attribute, then we must be calling a function which has
6946 the (interfacearm) attribute. We look for the Thumb entry point to that
6947 function and change the branch to refer to that function instead. */
6948 if ( fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
6949 && fixP->fx_addsy != NULL
6950 && S_IS_DEFINED (fixP->fx_addsy)
6951 && ! THUMB_IS_FUNC (fixP->fx_addsy))
6952 {
6953 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
6954 return true;
6955 }
6956
6957 return false;
6958}
6959
6960#ifdef OBJ_ELF
6961/* Relocations against Thumb function names must be left unadjusted,
6962 so that the linker can use this information to correctly set the
6963 bottom bit of their addresses. The MIPS version of this function
6964 also prevents relocations that are mips-16 specific, but I do not
6965 know why it does this.
6966
6967 FIXME:
6968 There is one other problem that ought to be addressed here, but
6969 which currently is not: Taking the address of a label (rather
6970 than a function) and then later jumping to that address. Such
6971 addresses also ought to have their bottom bit set (assuming that
6972 they reside in Thumb code), but at the moment they will not. */
6973
6974boolean
6975arm_fix_adjustable (fixP)
6976 fixS * fixP;
6977{
252b5132
RH
6978 if (fixP->fx_addsy == NULL)
6979 return 1;
6980
6981 /* Prevent all adjustments to global symbols. */
6982 if (S_IS_EXTERN (fixP->fx_addsy))
6983 return 0;
6984
6985 if (S_IS_WEAK (fixP->fx_addsy))
6986 return 0;
6987
6988 if (THUMB_IS_FUNC (fixP->fx_addsy)
6989 && fixP->fx_subsy == NULL)
6990 return 0;
6991
6992 /* We need the symbol name for the VTABLE entries */
6993 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6994 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6995 return 0;
6996
6997 return 1;
6998}
6999
7000const char *
7001elf32_arm_target_format ()
7002{
7003 if (target_big_endian)
7004 if (target_oabi)
7005 return "elf32-bigarm-oabi";
7006 else
7007 return "elf32-bigarm";
7008 else
7009 if (target_oabi)
7010 return "elf32-littlearm-oabi";
7011 else
7012 return "elf32-littlearm";
7013}
7014
7015void
7016armelf_frob_symbol (symp, puntp)
7017 symbolS * symp;
7018 int * puntp;
7019{
7020 elf_frob_symbol (symp, puntp);
7021}
7022
7023int
7024arm_force_relocation (fixp)
7025 struct fix * fixp;
7026{
7027 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
7028 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
ae5ad4ad
NC
7029 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
7030 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
252b5132
RH
7031 return 1;
7032
7033 return 0;
7034}
7035
7036static bfd_reloc_code_real_type
7037arm_parse_reloc ()
7038{
7039 char id[16];
7040 char * ip;
7041 int i;
7042 static struct
7043 {
7044 char * str;
7045 int len;
7046 bfd_reloc_code_real_type reloc;
7047 }
7048 reloc_map[] =
7049 {
7050#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
7051 MAP ("(got)", BFD_RELOC_ARM_GOT32),
7052 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
7053 /* ScottB: Jan 30, 1998 */
7054 /* Added support for parsing "var(PLT)" branch instructions */
7055 /* generated by GCC for PLT relocs */
7056 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
29c4c6b5 7057 { NULL, 0, BFD_RELOC_UNUSED }
252b5132
RH
7058#undef MAP
7059 };
7060
7061 for (i = 0, ip = input_line_pointer;
7062 i < sizeof (id) && (isalnum (*ip) || ispunct (*ip));
7063 i++, ip++)
7064 id[i] = tolower (*ip);
7065
7066 for (i = 0; reloc_map[i].str; i++)
7067 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
7068 break;
7069
7070 input_line_pointer += reloc_map[i].len;
7071
7072 return reloc_map[i].reloc;
7073}
7074
7075static void
7076s_arm_elf_cons (nbytes)
7077 int nbytes;
7078{
7079 expressionS exp;
7080
7081#ifdef md_flush_pending_output
7082 md_flush_pending_output ();
7083#endif
7084
7085 if (is_it_end_of_statement ())
7086 {
7087 demand_empty_rest_of_line ();
7088 return;
7089 }
7090
7091#ifdef md_cons_align
7092 md_cons_align (nbytes);
7093#endif
7094
7095 do
7096 {
7097 bfd_reloc_code_real_type reloc;
7098
7099 expression (& exp);
7100
7101 if (exp.X_op == O_symbol
7102 && * input_line_pointer == '('
7103 && (reloc = arm_parse_reloc()) != BFD_RELOC_UNUSED)
7104 {
7105 reloc_howto_type * howto = bfd_reloc_type_lookup (stdoutput, reloc);
7106 int size = bfd_get_reloc_size (howto);
7107
7108 if (size > nbytes)
7109 as_bad ("%s relocations do not fit in %d bytes", howto->name, nbytes);
7110 else
7111 {
7112 register char * p = frag_more ((int) nbytes);
7113 int offset = nbytes - size;
7114
7115 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
7116 & exp, 0, reloc);
7117 }
7118 }
7119 else
7120 emit_expr (& exp, (unsigned int) nbytes);
7121 }
7122 while (*input_line_pointer++ == ',');
7123
7124 input_line_pointer--; /* Put terminator back into stream. */
7125 demand_empty_rest_of_line ();
7126}
7127
7128#endif /* OBJ_ELF */
This page took 0.32695 seconds and 4 git commands to generate.