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