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