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