1 /* tc-arm.c -- Assemble for the ARM
2 Copyright (C) 1994, 95, 96, 1997 Free Software Foundation, Inc.
3 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4 Modified by David Taylor (dtaylor@armltd.co.uk)
6 This file is part of GAS, the GNU Assembler.
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)
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.
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
35 /* ??? This is currently unused. */
37 #define internalError() \
38 as_fatal ("ARM Internal Error, line %d, %s", __LINE__, __FILE__)
40 #define internalError() as_fatal ("ARM Internal Error")
43 /* Types of processor to assemble for. */
44 #define ARM_1 0x00000001
45 #define ARM_2 0x00000002
46 #define ARM_3 0x00000004
48 #define ARM_6 0x00000008
49 #define ARM_7 ARM_6 /* same core instruction set */
50 #define ARM_CPU_MASK 0x0000000f
52 /* The following bitmasks control CPU extensions (ARM7 onwards): */
53 #define ARM_LONGMUL 0x00000010 /* allow long multiplies */
54 #define ARM_HALFWORD 0x00000020 /* allow half word loads */
55 #define ARM_THUMB 0x00000040 /* allow BX instruction */
57 #define ARM_ARCHv4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD)
59 /* Some useful combinations: */
60 #define ARM_ANY 0x00ffffff
61 #define ARM_2UP 0x00fffffe
62 #define ARM_ALL ARM_2UP /* Not arm1 only */
63 #define ARM_3UP 0x00fffffc
64 #define ARM_6UP 0x00fffff8 /* Includes ARM7 */
66 #define FPU_CORE 0x80000000
67 #define FPU_FPA10 0x40000000
68 #define FPU_FPA11 0x40000000
71 /* Some useful combinations */
72 #define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */
73 #define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */
78 #define CPU_DEFAULT (ARM_ARCHv4 | ARM_THUMB)
80 #define CPU_DEFAULT ARM_ALL
85 #define FPU_DEFAULT FPU_ALL
88 static unsigned long cpu_variant
= CPU_DEFAULT
| FPU_DEFAULT
;
91 /* Flags stored in private area of BFD COFF structure */
92 static boolean uses_apcs_26
= false;
93 static boolean support_interwork
= false;
94 static boolean uses_apcs_float
= false;
95 static boolean pic_code
= false;
98 /* This array holds the chars that always start a comment. If the
99 pre-processor is disabled, these aren't very useful */
100 CONST
char comment_chars
[] = "@";
102 /* This array holds the chars that only start a comment at the beginning of
103 a line. If the line seems to have the form '# 123 filename'
104 .line and .file directives will appear in the pre-processed output */
105 /* Note that input_file.c hand checks for '#' at the beginning of the
106 first line of the input file. This is because the compiler outputs
107 #NO_APP at the beginning of its output. */
108 /* Also note that comments like this one will always work. */
109 CONST
char line_comment_chars
[] = "#";
111 CONST
char line_separator_chars
[] = "";
113 /* Chars that can be used to separate mant from exp in floating point nums */
114 CONST
char EXP_CHARS
[] = "eE";
116 /* Chars that mean this number is a floating point constant */
120 CONST
char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
122 CONST
int md_reloc_size
= 8; /* Size of relocation record */
124 static int thumb_mode
= 0; /* non-zero if assembling thumb instructions */
126 typedef struct arm_fix
134 unsigned long instruction
;
139 bfd_reloc_code_real_type type
;
149 CONST
char *template;
153 static CONST
struct asm_shift shift
[] =
169 #define NO_SHIFT_RESTRICT 1
170 #define SHIFT_RESTRICT 0
172 #define NUM_FLOAT_VALS 8
174 CONST
char *fp_const
[] =
176 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
179 /* Number of littlenums required to hold an extended precision number */
180 #define MAX_LITTLENUMS 6
182 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
192 #define CP_T_X 0x00008000
193 #define CP_T_Y 0x00400000
194 #define CP_T_Pre 0x01000000
195 #define CP_T_UD 0x00800000
196 #define CP_T_WB 0x00200000
198 #define CONDS_BIT (0x00100000)
199 #define LOAD_BIT (0x00100000)
200 #define TRANS_BIT (0x00200000)
204 CONST
char *template;
208 /* This is to save a hash look-up in the common case */
209 #define COND_ALWAYS 0xe0000000
211 static CONST
struct asm_cond conds
[] =
215 {"cs", 0x20000000}, {"hs", 0x20000000},
216 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
231 /* Warning: If the top bit of the set_bits is set, then the standard
232 instruction bitmask is ignored, and the new bitmask is taken from
236 CONST
char *template; /* Basic flag string */
237 unsigned long set_bits
; /* Bits to set */
240 static CONST
struct asm_flg s_flag
[] =
246 static CONST
struct asm_flg ldr_flags
[] =
250 {"bt", 0x00400000 | TRANS_BIT
},
257 static CONST
struct asm_flg str_flags
[] =
261 {"bt", 0x00400000 | TRANS_BIT
},
266 static CONST
struct asm_flg byte_flag
[] =
272 static CONST
struct asm_flg cmp_flags
[] =
279 static CONST
struct asm_flg ldm_flags
[] =
292 static CONST
struct asm_flg stm_flags
[] =
305 static CONST
struct asm_flg lfm_flags
[] =
312 static CONST
struct asm_flg sfm_flags
[] =
319 static CONST
struct asm_flg round_flags
[] =
327 /* The implementation of the FIX instruction is broken on some assemblers,
328 in that it accepts a precision specifier as well as a rounding specifier,
329 despite the fact that this is meaningless. To be more compatible, we
330 accept it as well, though of course it does not set any bits. */
331 static CONST
struct asm_flg fix_flags
[] =
348 static CONST
struct asm_flg except_flag
[] =
354 static CONST
struct asm_flg cplong_flag
[] =
362 CONST
char *template;
363 unsigned long number
;
366 #define PSR_ALL 0x00010000
368 static CONST
struct asm_psr psrs
[] =
381 /* Functions called by parser */
382 /* ARM instructions */
383 static void do_arit
PARAMS ((char *operands
, unsigned long flags
));
384 static void do_cmp
PARAMS ((char *operands
, unsigned long flags
));
385 static void do_mov
PARAMS ((char *operands
, unsigned long flags
));
386 static void do_ldst
PARAMS ((char *operands
, unsigned long flags
));
387 static void do_ldmstm
PARAMS ((char *operands
, unsigned long flags
));
388 static void do_branch
PARAMS ((char *operands
, unsigned long flags
));
389 static void do_swi
PARAMS ((char *operands
, unsigned long flags
));
390 /* Pseudo Op codes */
391 static void do_adr
PARAMS ((char *operands
, unsigned long flags
));
392 static void do_nop
PARAMS ((char *operands
, unsigned long flags
));
394 static void do_mul
PARAMS ((char *operands
, unsigned long flags
));
395 static void do_mla
PARAMS ((char *operands
, unsigned long flags
));
397 static void do_swap
PARAMS ((char *operands
, unsigned long flags
));
399 static void do_msr
PARAMS ((char *operands
, unsigned long flags
));
400 static void do_mrs
PARAMS ((char *operands
, unsigned long flags
));
402 static void do_mull
PARAMS ((char *operands
, unsigned long flags
));
404 static void do_bx
PARAMS ((char *operands
, unsigned long flags
));
406 /* Coprocessor Instructions */
407 static void do_cdp
PARAMS ((char *operands
, unsigned long flags
));
408 static void do_lstc
PARAMS ((char *operands
, unsigned long flags
));
409 static void do_co_reg
PARAMS ((char *operands
, unsigned long flags
));
410 static void do_fp_ctrl
PARAMS ((char *operands
, unsigned long flags
));
411 static void do_fp_ldst
PARAMS ((char *operands
, unsigned long flags
));
412 static void do_fp_ldmstm
PARAMS ((char *operands
, unsigned long flags
));
413 static void do_fp_dyadic
PARAMS ((char *operands
, unsigned long flags
));
414 static void do_fp_monadic
PARAMS ((char *operands
, unsigned long flags
));
415 static void do_fp_cmp
PARAMS ((char *operands
, unsigned long flags
));
416 static void do_fp_from_reg
PARAMS ((char *operands
, unsigned long flags
));
417 static void do_fp_to_reg
PARAMS ((char *operands
, unsigned long flags
));
419 static void fix_new_arm
PARAMS ((fragS
*frag
, int where
,
420 short int size
, expressionS
*exp
,
421 int pc_rel
, int reloc
));
422 static int arm_reg_parse
PARAMS ((char **ccp
));
423 static int arm_psr_parse
PARAMS ((char **ccp
));
424 static void symbol_locate
PARAMS ((symbolS
*, CONST
char *, segT
,
426 static int add_to_lit_pool
PARAMS ((void));
427 static unsigned validate_immediate
PARAMS ((unsigned));
428 static int validate_offset_imm
PARAMS ((int, int));
429 static void opcode_select
PARAMS ((int));
430 static void end_of_line
PARAMS ((char *));
431 static int reg_required_here
PARAMS ((char **, int));
432 static int psr_required_here
PARAMS ((char **, int));
433 static int psrf_required_here
PARAMS ((char **, int));
434 static int co_proc_number
PARAMS ((char **));
435 static int cp_opc_expr
PARAMS ((char **, int, int));
436 static int cp_reg_required_here
PARAMS ((char **, int));
437 static int fp_reg_required_here
PARAMS ((char **, int));
438 static int cp_address_offset
PARAMS ((char **));
439 static int cp_address_required_here
PARAMS ((char **));
440 static int my_get_float_expression
PARAMS ((char **));
441 static int skip_past_comma
PARAMS ((char **));
442 static int walk_no_bignums
PARAMS ((symbolS
*));
443 static int negate_data_op
PARAMS ((unsigned long *,
445 static int data_op2
PARAMS ((char **));
446 static int fp_op2
PARAMS ((char **));
447 static long reg_list
PARAMS ((char **));
448 static void thumb_load_store
PARAMS ((char *, int, int));
449 static int decode_shift
PARAMS ((char **, int));
450 static int ldst_extend
PARAMS ((char **, int));
451 static void thumb_add_sub
PARAMS ((char *, int));
452 static void insert_reg
PARAMS ((int));
453 static void thumb_shift
PARAMS ((char *, int));
454 static void thumb_mov_compare
PARAMS ((char *, int));
455 static void set_constant_flonums
PARAMS ((void));
456 static valueT md_chars_to_number
PARAMS ((char *, int));
457 static void insert_reg_alias
PARAMS ((char *, int));
458 static void output_inst
PARAMS ((char *));
460 /* ARM instructions take 4bytes in the object file, Thumb instructions
464 /* LONGEST_INST is the longest basic instruction name without conditions or
466 * ARM7M has 4 of length 5
469 #define LONGEST_INST 5
473 CONST
char *template; /* Basic string to match */
474 unsigned long value
; /* Basic instruction code */
475 CONST
char *comp_suffix
; /* Compulsory suffix that must follow conds */
476 CONST
struct asm_flg
*flags
; /* Bits to toggle if flag 'n' set */
477 unsigned long variants
; /* Which CPU variants this exists for */
478 /* Function to call to parse args */
479 void (*parms
) PARAMS ((char *, unsigned long));
482 static CONST
struct asm_opcode insns
[] =
484 /* ARM Instructions */
485 {"and", 0x00000000, NULL
, s_flag
, ARM_ANY
, do_arit
},
486 {"eor", 0x00200000, NULL
, s_flag
, ARM_ANY
, do_arit
},
487 {"sub", 0x00400000, NULL
, s_flag
, ARM_ANY
, do_arit
},
488 {"rsb", 0x00600000, NULL
, s_flag
, ARM_ANY
, do_arit
},
489 {"add", 0x00800000, NULL
, s_flag
, ARM_ANY
, do_arit
},
490 {"adc", 0x00a00000, NULL
, s_flag
, ARM_ANY
, do_arit
},
491 {"sbc", 0x00c00000, NULL
, s_flag
, ARM_ANY
, do_arit
},
492 {"rsc", 0x00e00000, NULL
, s_flag
, ARM_ANY
, do_arit
},
493 {"orr", 0x01800000, NULL
, s_flag
, ARM_ANY
, do_arit
},
494 {"bic", 0x01c00000, NULL
, s_flag
, ARM_ANY
, do_arit
},
495 {"tst", 0x01000000, NULL
, cmp_flags
, ARM_ANY
, do_cmp
},
496 {"teq", 0x01200000, NULL
, cmp_flags
, ARM_ANY
, do_cmp
},
497 {"cmp", 0x01400000, NULL
, cmp_flags
, ARM_ANY
, do_cmp
},
498 {"cmn", 0x01600000, NULL
, cmp_flags
, ARM_ANY
, do_cmp
},
499 {"mov", 0x01a00000, NULL
, s_flag
, ARM_ANY
, do_mov
},
500 {"mvn", 0x01e00000, NULL
, s_flag
, ARM_ANY
, do_mov
},
501 {"str", 0x04000000, NULL
, str_flags
, ARM_ANY
, do_ldst
},
502 {"ldr", 0x04100000, NULL
, ldr_flags
, ARM_ANY
, do_ldst
},
503 {"stm", 0x08000000, NULL
, stm_flags
, ARM_ANY
, do_ldmstm
},
504 {"ldm", 0x08100000, NULL
, ldm_flags
, ARM_ANY
, do_ldmstm
},
505 {"swi", 0x0f000000, NULL
, NULL
, ARM_ANY
, do_swi
},
506 {"bl", 0x0bfffffe, NULL
, NULL
, ARM_ANY
, do_branch
},
507 {"b", 0x0afffffe, NULL
, NULL
, ARM_ANY
, do_branch
},
510 {"adr", 0x028f0000, NULL
, NULL
, ARM_ANY
, do_adr
},
511 {"nop", 0x01a00000, NULL
, NULL
, ARM_ANY
, do_nop
},
513 /* ARM 2 multiplies */
514 {"mul", 0x00000090, NULL
, s_flag
, ARM_2UP
, do_mul
},
515 {"mla", 0x00200090, NULL
, s_flag
, ARM_2UP
, do_mla
},
517 /* ARM 3 - swp instructions */
518 {"swp", 0x01000090, NULL
, byte_flag
, ARM_3UP
, do_swap
},
520 /* ARM 6 Coprocessor instructions */
521 {"mrs", 0x010f0000, NULL
, NULL
, ARM_6UP
, do_mrs
},
522 {"msr", 0x0128f000, NULL
, NULL
, ARM_6UP
, do_msr
},
524 /* ARM 7M long multiplies - need signed/unsigned flags! */
525 {"smull", 0x00c00090, NULL
, s_flag
, ARM_LONGMUL
, do_mull
},
526 {"umull", 0x00800090, NULL
, s_flag
, ARM_LONGMUL
, do_mull
},
527 {"smlal", 0x00e00090, NULL
, s_flag
, ARM_LONGMUL
, do_mull
},
528 {"umlal", 0x00a00090, NULL
, s_flag
, ARM_LONGMUL
, do_mull
},
530 /* ARM THUMB interworking */
531 {"bx", 0x012fff10, NULL
, NULL
, ARM_THUMB
, do_bx
},
533 /* Floating point instructions */
534 {"wfs", 0x0e200110, NULL
, NULL
, FPU_ALL
, do_fp_ctrl
},
535 {"rfs", 0x0e300110, NULL
, NULL
, FPU_ALL
, do_fp_ctrl
},
536 {"wfc", 0x0e400110, NULL
, NULL
, FPU_ALL
, do_fp_ctrl
},
537 {"rfc", 0x0e500110, NULL
, NULL
, FPU_ALL
, do_fp_ctrl
},
538 {"ldf", 0x0c100100, "sdep", NULL
, FPU_ALL
, do_fp_ldst
},
539 {"stf", 0x0c000100, "sdep", NULL
, FPU_ALL
, do_fp_ldst
},
540 {"lfm", 0x0c100200, NULL
, lfm_flags
, FPU_MEMMULTI
, do_fp_ldmstm
},
541 {"sfm", 0x0c000200, NULL
, sfm_flags
, FPU_MEMMULTI
, do_fp_ldmstm
},
542 {"mvf", 0x0e008100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
543 {"mnf", 0x0e108100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
544 {"abs", 0x0e208100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
545 {"rnd", 0x0e308100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
546 {"sqt", 0x0e408100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
547 {"log", 0x0e508100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
548 {"lgn", 0x0e608100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
549 {"exp", 0x0e708100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
550 {"sin", 0x0e808100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
551 {"cos", 0x0e908100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
552 {"tan", 0x0ea08100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
553 {"asn", 0x0eb08100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
554 {"acs", 0x0ec08100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
555 {"atn", 0x0ed08100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
556 {"urd", 0x0ee08100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
557 {"nrm", 0x0ef08100, "sde", round_flags
, FPU_ALL
, do_fp_monadic
},
558 {"adf", 0x0e000100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
559 {"suf", 0x0e200100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
560 {"rsf", 0x0e300100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
561 {"muf", 0x0e100100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
562 {"dvf", 0x0e400100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
563 {"rdf", 0x0e500100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
564 {"pow", 0x0e600100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
565 {"rpw", 0x0e700100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
566 {"rmf", 0x0e800100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
567 {"fml", 0x0e900100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
568 {"fdv", 0x0ea00100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
569 {"frd", 0x0eb00100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
570 {"pol", 0x0ec00100, "sde", round_flags
, FPU_ALL
, do_fp_dyadic
},
571 {"cmf", 0x0e90f110, NULL
, except_flag
, FPU_ALL
, do_fp_cmp
},
572 {"cnf", 0x0eb0f110, NULL
, except_flag
, FPU_ALL
, do_fp_cmp
},
573 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
574 be an optional suffix, but part of the instruction. To be compatible,
576 {"cmfe", 0x0ed0f110, NULL
, NULL
, FPU_ALL
, do_fp_cmp
},
577 {"cnfe", 0x0ef0f110, NULL
, NULL
, FPU_ALL
, do_fp_cmp
},
578 {"flt", 0x0e000110, "sde", round_flags
, FPU_ALL
, do_fp_from_reg
},
579 {"fix", 0x0e100110, NULL
, fix_flags
, FPU_ALL
, do_fp_to_reg
},
581 /* Generic copressor instructions */
582 {"cdp", 0x0e000000, NULL
, NULL
, ARM_2UP
, do_cdp
},
583 {"ldc", 0x0c100000, NULL
, cplong_flag
, ARM_2UP
, do_lstc
},
584 {"stc", 0x0c000000, NULL
, cplong_flag
, ARM_2UP
, do_lstc
},
585 {"mcr", 0x0e000010, NULL
, NULL
, ARM_2UP
, do_co_reg
},
586 {"mrc", 0x0e100010, NULL
, NULL
, ARM_2UP
, do_co_reg
},
589 /* defines for various bits that we will want to toggle */
591 #define INST_IMMEDIATE 0x02000000
592 #define OFFSET_REG 0x02000000
593 #define HWOFFSET_IMM 0x00400000
594 #define SHIFT_BY_REG 0x00000010
595 #define PRE_INDEX 0x01000000
596 #define INDEX_UP 0x00800000
597 #define WRITE_BACK 0x00200000
598 #define MULTI_SET_PSR 0x00400000
600 #define LITERAL_MASK 0xf000f000
601 #define COND_MASK 0xf0000000
602 #define OPCODE_MASK 0xfe1fffff
603 #define DATA_OP_SHIFT 21
605 /* Codes to distinguish the arithmetic instructions */
617 #define OPCODE_CMP 10
618 #define OPCODE_CMN 11
619 #define OPCODE_ORR 12
620 #define OPCODE_MOV 13
621 #define OPCODE_BIC 14
622 #define OPCODE_MVN 15
624 static void do_t_nop
PARAMS ((char *operands
));
625 static void do_t_arit
PARAMS ((char *operands
));
626 static void do_t_add
PARAMS ((char *operands
));
627 static void do_t_asr
PARAMS ((char *operands
));
628 static void do_t_branch9
PARAMS ((char *operands
));
629 static void do_t_branch12
PARAMS ((char *operands
));
630 static void do_t_branch23
PARAMS ((char *operands
));
631 static void do_t_bx
PARAMS ((char *operands
));
632 static void do_t_compare
PARAMS ((char *operands
));
633 static void do_t_ldmstm
PARAMS ((char *operands
));
634 static void do_t_ldr
PARAMS ((char *operands
));
635 static void do_t_ldrb
PARAMS ((char *operands
));
636 static void do_t_ldrh
PARAMS ((char *operands
));
637 static void do_t_lds
PARAMS ((char *operands
));
638 static void do_t_lsl
PARAMS ((char *operands
));
639 static void do_t_lsr
PARAMS ((char *operands
));
640 static void do_t_mov
PARAMS ((char *operands
));
641 static void do_t_push_pop
PARAMS ((char *operands
));
642 static void do_t_str
PARAMS ((char *operands
));
643 static void do_t_strb
PARAMS ((char *operands
));
644 static void do_t_strh
PARAMS ((char *operands
));
645 static void do_t_sub
PARAMS ((char *operands
));
646 static void do_t_swi
PARAMS ((char *operands
));
647 static void do_t_adr
PARAMS ((char *operands
));
649 #define T_OPCODE_MUL 0x4340
650 #define T_OPCODE_TST 0x4200
651 #define T_OPCODE_CMN 0x42c0
652 #define T_OPCODE_NEG 0x4240
653 #define T_OPCODE_MVN 0x43c0
655 #define T_OPCODE_ADD_R3 0x1800
656 #define T_OPCODE_SUB_R3 0x1a00
657 #define T_OPCODE_ADD_HI 0x4400
658 #define T_OPCODE_ADD_ST 0xb000
659 #define T_OPCODE_SUB_ST 0xb080
660 #define T_OPCODE_ADD_SP 0xa800
661 #define T_OPCODE_ADD_PC 0xa000
662 #define T_OPCODE_ADD_I8 0x3000
663 #define T_OPCODE_SUB_I8 0x3800
664 #define T_OPCODE_ADD_I3 0x1c00
665 #define T_OPCODE_SUB_I3 0x1e00
667 #define T_OPCODE_ASR_R 0x4100
668 #define T_OPCODE_LSL_R 0x4080
669 #define T_OPCODE_LSR_R 0x40c0
670 #define T_OPCODE_ASR_I 0x1000
671 #define T_OPCODE_LSL_I 0x0000
672 #define T_OPCODE_LSR_I 0x0800
674 #define T_OPCODE_MOV_I8 0x2000
675 #define T_OPCODE_CMP_I8 0x2800
676 #define T_OPCODE_CMP_LR 0x4280
677 #define T_OPCODE_MOV_HR 0x4600
678 #define T_OPCODE_CMP_HR 0x4500
680 #define T_OPCODE_LDR_PC 0x4800
681 #define T_OPCODE_LDR_SP 0x9800
682 #define T_OPCODE_STR_SP 0x9000
683 #define T_OPCODE_LDR_IW 0x6800
684 #define T_OPCODE_STR_IW 0x6000
685 #define T_OPCODE_LDR_IH 0x8800
686 #define T_OPCODE_STR_IH 0x8000
687 #define T_OPCODE_LDR_IB 0x7800
688 #define T_OPCODE_STR_IB 0x7000
689 #define T_OPCODE_LDR_RW 0x5800
690 #define T_OPCODE_STR_RW 0x5000
691 #define T_OPCODE_LDR_RH 0x5a00
692 #define T_OPCODE_STR_RH 0x5200
693 #define T_OPCODE_LDR_RB 0x5c00
694 #define T_OPCODE_STR_RB 0x5400
696 #define T_OPCODE_PUSH 0xb400
697 #define T_OPCODE_POP 0xbc00
699 #define T_OPCODE_BRANCH 0xe7fe
701 static int thumb_reg
PARAMS ((char **str
, int hi_lo
));
703 #define THUMB_SIZE 2 /* Size of thumb instruction */
704 #define THUMB_REG_LO 0x1
705 #define THUMB_REG_HI 0x2
706 #define THUMB_REG_ANY 0x3
708 #define THUMB_H1 0x0080
709 #define THUMB_H2 0x0040
716 #define THUMB_COMPARE 1
719 #define THUMB_STORE 1
721 #define THUMB_PP_PC_LR 0x0100
723 /* These three are used for immediate shifts, do not alter */
725 #define THUMB_HALFWORD 1
730 CONST
char *template; /* Basic string to match */
731 unsigned long value
; /* Basic instruction code */
733 /* Function to call to parse args */
734 void (*parms
) PARAMS ((char *));
737 static CONST
struct thumb_opcode tinsns
[] =
739 {"adc", 0x4140, 2, do_t_arit
},
740 {"add", 0x0000, 2, do_t_add
},
741 {"and", 0x4000, 2, do_t_arit
},
742 {"asr", 0x0000, 2, do_t_asr
},
743 {"b", T_OPCODE_BRANCH
, 2, do_t_branch12
},
744 {"beq", 0xd0fe, 2, do_t_branch9
},
745 {"bne", 0xd1fe, 2, do_t_branch9
},
746 {"bcs", 0xd2fe, 2, do_t_branch9
},
747 {"bhs", 0xd2fe, 2, do_t_branch9
},
748 {"bcc", 0xd3fe, 2, do_t_branch9
},
749 {"bul", 0xd3fe, 2, do_t_branch9
},
750 {"blo", 0xd3fe, 2, do_t_branch9
},
751 {"bmi", 0xd4fe, 2, do_t_branch9
},
752 {"bpl", 0xd5fe, 2, do_t_branch9
},
753 {"bvs", 0xd6fe, 2, do_t_branch9
},
754 {"bvc", 0xd7fe, 2, do_t_branch9
},
755 {"bhi", 0xd8fe, 2, do_t_branch9
},
756 {"bls", 0xd9fe, 2, do_t_branch9
},
757 {"bge", 0xdafe, 2, do_t_branch9
},
758 {"blt", 0xdbfe, 2, do_t_branch9
},
759 {"bgt", 0xdcfe, 2, do_t_branch9
},
760 {"ble", 0xddfe, 2, do_t_branch9
},
761 {"bic", 0x4380, 2, do_t_arit
},
762 {"bl", 0xf7fffffe, 4, do_t_branch23
},
763 {"bx", 0x4700, 2, do_t_bx
},
764 {"cmn", T_OPCODE_CMN
, 2, do_t_arit
},
765 {"cmp", 0x0000, 2, do_t_compare
},
766 {"eor", 0x4040, 2, do_t_arit
},
767 {"ldmia", 0xc800, 2, do_t_ldmstm
},
768 {"ldr", 0x0000, 2, do_t_ldr
},
769 {"ldrb", 0x0000, 2, do_t_ldrb
},
770 {"ldrh", 0x0000, 2, do_t_ldrh
},
771 {"ldrsb", 0x5600, 2, do_t_lds
},
772 {"ldrsh", 0x5e00, 2, do_t_lds
},
773 {"ldsb", 0x5600, 2, do_t_lds
},
774 {"ldsh", 0x5e00, 2, do_t_lds
},
775 {"lsl", 0x0000, 2, do_t_lsl
},
776 {"lsr", 0x0000, 2, do_t_lsr
},
777 {"mov", 0x0000, 2, do_t_mov
},
778 {"mul", T_OPCODE_MUL
, 2, do_t_arit
},
779 {"mvn", T_OPCODE_MVN
, 2, do_t_arit
},
780 {"neg", T_OPCODE_NEG
, 2, do_t_arit
},
781 {"orr", 0x4300, 2, do_t_arit
},
782 {"pop", 0xbc00, 2, do_t_push_pop
},
783 {"push", 0xb400, 2, do_t_push_pop
},
784 {"ror", 0x41c0, 2, do_t_arit
},
785 {"sbc", 0x4180, 2, do_t_arit
},
786 {"stmia", 0xc000, 2, do_t_ldmstm
},
787 {"str", 0x0000, 2, do_t_str
},
788 {"strb", 0x0000, 2, do_t_strb
},
789 {"strh", 0x0000, 2, do_t_strh
},
790 {"swi", 0xdf00, 2, do_t_swi
},
791 {"sub", 0x0000, 2, do_t_sub
},
792 {"tst", T_OPCODE_TST
, 2, do_t_arit
},
794 {"adr", 0x0000, 2, do_t_adr
},
795 {"nop", 0x46C0, 2, do_t_nop
}, /* mov r8,r8 */
804 #define int_register(reg) ((reg) >= 0 && (reg) <= 15)
805 #define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
806 #define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
812 /* These are the standard names; Users can add aliases with .req */
813 static CONST
struct reg_entry reg_table
[] =
815 /* Processor Register Numbers */
816 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
817 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
818 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
819 {"r12", 12}, {"r13", REG_SP
},{"r14", REG_LR
},{"r15", REG_PC
},
820 /* APCS conventions */
821 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
822 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
823 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
824 {"fp", 11}, {"ip", 12}, {"sp", REG_SP
},{"lr", REG_LR
},{"pc", REG_PC
},
826 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
827 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
828 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
829 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
830 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
831 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
832 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
833 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
834 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
835 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
839 static CONST
char *bad_args
= "Bad arguments to instruction";
840 static CONST
char *bad_pc
= "r15 not allowed here";
842 static struct hash_control
*arm_ops_hsh
= NULL
;
843 static struct hash_control
*arm_tops_hsh
= NULL
;
844 static struct hash_control
*arm_cond_hsh
= NULL
;
845 static struct hash_control
*arm_shift_hsh
= NULL
;
846 static struct hash_control
*arm_reg_hsh
= NULL
;
847 static struct hash_control
*arm_psr_hsh
= NULL
;
849 /* This table describes all the machine specific pseudo-ops the assembler
850 has to support. The fields are:
851 pseudo-op name without dot
852 function to call to execute this pseudo-op
853 Integer arg to pass to the function
856 static void s_req
PARAMS ((int));
857 static void s_align
PARAMS ((int));
858 static void s_bss
PARAMS ((int));
859 static void s_even
PARAMS ((int));
860 static void s_ltorg
PARAMS ((int));
861 static void s_arm
PARAMS ((int));
862 static void s_thumb
PARAMS ((int));
863 static void s_code
PARAMS ((int));
864 static void s_force_thumb
PARAMS ((int));
865 static void s_thumb_func
PARAMS ((int));
867 static int my_get_expression
PARAMS ((expressionS
*, char **));
869 CONST pseudo_typeS md_pseudo_table
[] =
871 {"req", s_req
, 0}, /* Never called becasue '.req' does not start line */
873 {"align", s_align
, 0},
875 {"thumb", s_thumb
, 0},
877 {"force_thumb", s_force_thumb
, 0},
878 {"thumb_func", s_thumb_func
, 0},
880 {"ltorg", s_ltorg
, 0},
881 {"pool", s_ltorg
, 0},
883 {"extend", float_cons
, 'x'},
884 {"ldouble", float_cons
, 'x'},
885 {"packed", float_cons
, 'p'},
889 /* Stuff needed to resolve the label ambiguity
899 symbolS
* last_label_seen
;
900 static int label_is_thumb_function_name
= false;
904 #define MAX_LITERAL_POOL_SIZE 1024
906 typedef struct literalS
908 struct expressionS exp
;
912 literalT literals
[MAX_LITERAL_POOL_SIZE
];
913 int next_literal_pool_place
= 0; /* Next free entry in the pool */
914 int lit_pool_num
= 1; /* Next literal pool number */
915 symbolS
*current_poolP
= NULL
;
916 symbolS
*symbol_make_empty
PARAMS ((void));
923 if (current_poolP
== NULL
)
924 current_poolP
= symbol_make_empty();
926 /* Check if this literal value is already in the pool: */
927 while (lit_count
< next_literal_pool_place
)
929 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
930 && inst
.reloc
.exp
.X_op
== O_constant
931 && literals
[lit_count
].exp
.X_add_number
== inst
.reloc
.exp
.X_add_number
932 && literals
[lit_count
].exp
.X_unsigned
== inst
.reloc
.exp
.X_unsigned
)
937 if (lit_count
== next_literal_pool_place
) /* new entry */
939 if (next_literal_pool_place
> MAX_LITERAL_POOL_SIZE
)
941 inst
.error
= "Literal Pool Overflow";
945 literals
[next_literal_pool_place
].exp
= inst
.reloc
.exp
;
946 lit_count
= next_literal_pool_place
++;
949 inst
.reloc
.exp
.X_op
= O_symbol
;
950 inst
.reloc
.exp
.X_add_number
= (lit_count
)*4-8;
951 inst
.reloc
.exp
.X_add_symbol
= current_poolP
;
956 /* Can't use symbol_new here, so have to create a symbol and then at
957 a later date assign it a value. Thats what these functions do */
959 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
961 CONST
char *name
; /* It is copied, the caller can modify */
962 segT segment
; /* Segment identifier (SEG_<something>) */
963 valueT valu
; /* Symbol value */
964 fragS
*frag
; /* Associated fragment */
966 unsigned int name_length
;
967 char *preserved_copy_of_name
;
969 name_length
= strlen (name
) + 1; /* +1 for \0 */
970 obstack_grow (¬es
, name
, name_length
);
971 preserved_copy_of_name
= obstack_finish (¬es
);
972 #ifdef STRIP_UNDERSCORE
973 if (preserved_copy_of_name
[0] == '_')
974 preserved_copy_of_name
++;
977 #ifdef tc_canonicalize_symbol_name
978 preserved_copy_of_name
=
979 tc_canonicalize_symbol_name (preserved_copy_of_name
);
982 S_SET_NAME (symbolP
, preserved_copy_of_name
);
984 S_SET_SEGMENT (symbolP
, segment
);
985 S_SET_VALUE (symbolP
, valu
);
986 symbol_clear_list_pointers(symbolP
);
988 symbolP
->sy_frag
= frag
;
991 * Link to end of symbol chain.
994 extern int symbol_table_frozen
;
995 if (symbol_table_frozen
)
999 symbol_append (symbolP
, symbol_lastP
, &symbol_rootP
, &symbol_lastP
);
1001 obj_symbol_new_hook (symbolP
);
1003 #ifdef tc_symbol_new_hook
1004 tc_symbol_new_hook (symbolP
);
1008 verify_symbol_chain(symbol_rootP
, symbol_lastP
);
1009 #endif /* DEBUG_SYMS */
1013 symbol_make_empty ()
1017 symbolP
= (symbolS
*) obstack_alloc (¬es
, sizeof (symbolS
));
1019 /* symbol must be born in some fixed state. This seems as good as any. */
1020 memset (symbolP
, 0, sizeof (symbolS
));
1022 symbolP
->bsym
= bfd_make_empty_symbol (stdoutput
);
1023 assert (symbolP
->bsym
!= 0);
1024 symbolP
->bsym
->udata
.p
= (PTR
) symbolP
;
1029 /* Check that an immediate is valid, and if so, convert it to the right format. */
1032 validate_immediate (val
)
1038 #define rotate_left(v, n) (v << n | v >> (32 - n))
1040 for (i
= 0; i
< 32; i
+= 2)
1041 if ((a
= rotate_left (val
, i
)) <= 0xff)
1042 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const] */
1047 validate_offset_imm (val
, hwse
)
1051 if ((hwse
&& (val
< -255 || val
> 255))
1052 || (val
< -4095 || val
> 4095))
1062 as_bad ("Invalid syntax for .req directive.");
1069 /* We don't support putting frags in the BSS segment, we fake it by
1070 marking in_bss, then looking at s_skip for clues?.. */
1071 subseg_set (bss_section
, 0);
1072 demand_empty_rest_of_line ();
1079 if (!need_pass_2
) /* Never make frag if expect extra pass. */
1080 frag_align (1, 0, 0);
1081 record_alignment (now_seg
, 1);
1082 demand_empty_rest_of_line ();
1092 if (current_poolP
== NULL
)
1096 as_tsktsk ("Nothing to put in the pool\n");
1100 /* Align pool as you have word accesses */
1101 /* Only make a frag if we have to ... */
1103 frag_align (2, 0, 0);
1105 record_alignment (now_seg
, 2);
1108 as_tsktsk ("Inserting implicit pool at change of section");
1110 sprintf (sym_name
, "$$lit_\002%x", lit_pool_num
++);
1112 symbol_locate (current_poolP
, sym_name
, now_seg
,
1113 (valueT
) frag_now_fix (), frag_now
);
1114 symbol_table_insert (current_poolP
);
1116 ARM_SET_THUMB (current_poolP
, thumb_mode
);
1118 ARM_SET_INTERWORK (current_poolP
, support_interwork
);
1121 while (lit_count
< next_literal_pool_place
)
1122 /* First output the expression in the instruction to the pool */
1123 emit_expr (&(literals
[lit_count
++].exp
), 4); /* .word */
1125 next_literal_pool_place
= 0;
1126 current_poolP
= NULL
;
1129 #if 0 /* not used */
1131 arm_align (power
, fill
)
1135 /* Only make a frag if we HAVE to ... */
1136 if (power
&& !need_pass_2
)
1137 frag_align (power
, fill
, 0);
1139 record_alignment (now_seg
, power
);
1144 s_align (unused
) /* Same as s_align_ptwo but align 0 => align 2 */
1148 register long temp_fill
;
1149 long max_alignment
= 15;
1151 temp
= get_absolute_expression ();
1152 if (temp
> max_alignment
)
1153 as_bad ("Alignment too large: %d. assumed.", temp
= max_alignment
);
1156 as_bad ("Alignment negative. 0 assumed.");
1160 if (*input_line_pointer
== ',')
1162 input_line_pointer
++;
1163 temp_fill
= get_absolute_expression ();
1171 /* Only make a frag if we HAVE to. . . */
1172 if (temp
&& !need_pass_2
)
1173 frag_align (temp
, (int) temp_fill
, 0);
1174 demand_empty_rest_of_line ();
1176 record_alignment (now_seg
, temp
);
1180 s_force_thumb (ignore
)
1183 /* If we are not already in thumb mode go into it, EVEN if
1184 the target processor does not support thumb instructions.
1185 This is used by gcc/config/arm/lib1funcs.asm for example
1186 to compile interworking support functions even if the
1187 target processor should not support interworking. */
1193 record_alignment (now_seg
, 1);
1196 demand_empty_rest_of_line ();
1200 s_thumb_func (ignore
)
1203 /* The following label is the name/address of the start of a Thumb function.
1204 We need to know this for the interworking support. */
1206 label_is_thumb_function_name
= true;
1208 demand_empty_rest_of_line();
1212 opcode_select (width
)
1220 if (! (cpu_variant
& ARM_THUMB
))
1221 as_bad ("selected processor does not support THUMB opcodes");
1223 /* No need to force the alignment, since we will have been
1224 coming from ARM mode, which is word-aligned. */
1225 record_alignment (now_seg
, 1);
1232 if ((cpu_variant
& ARM_ANY
) == ARM_THUMB
)
1233 as_bad ("selected processor does not support ARM opcodes");
1236 frag_align (2, 0, 0);
1237 record_alignment (now_seg
, 1);
1242 as_bad ("invalid instruction size selected (%d)", width
);
1251 demand_empty_rest_of_line ();
1259 demand_empty_rest_of_line ();
1268 temp
= get_absolute_expression ();
1273 opcode_select(temp
);
1277 as_bad ("invalid operand to .code directive (%d) (expecting 16 or 32)", temp
);
1289 inst
.error
= "Garbage following instruction";
1293 skip_past_comma (str
)
1299 while ((c
= *p
) == ' ' || c
== ',')
1302 if (c
== ',' && comma
++)
1310 return comma
? SUCCESS
: FAIL
;
1313 /* A standard register must be given at this point. Shift is the place to
1314 put it in the instruction. */
1317 reg_required_here (str
, shift
)
1324 if ((reg
= arm_reg_parse (str
)) != FAIL
&& int_register (reg
))
1326 inst
.instruction
|= reg
<< shift
;
1330 /* In the few cases where we might be able to accept something else
1331 this error can be overridden */
1332 inst
.error
= "Register expected";
1334 /* Restore the start point, we may have got a reg of the wrong class. */
1340 psr_required_here (str
, shift
)
1347 if ((psr
= arm_psr_parse (str
)) != FAIL
&& psr
< 2)
1350 inst
.instruction
|= 1 << shift
; /* Should be bit 22 */
1354 /* In the few cases where we might be able to accept something else
1355 this error can be overridden */
1356 inst
.error
= "<psr> expected";
1358 /* Restore the start point. */
1364 psrf_required_here (str
, shift
)
1371 if ((psrf
= arm_psr_parse (str
)) != FAIL
&& psrf
> 1)
1373 if (psrf
== 1 || psrf
== 3)
1374 inst
.instruction
|= 1 << shift
; /* Should be bit 22 */
1378 /* In the few cases where we might be able to accept something else
1379 this error can be overridden */
1380 inst
.error
= "<psrf> expected";
1382 /* Restore the start point. */
1388 co_proc_number (str
)
1391 int processor
, pchar
;
1393 while (**str
== ' ')
1396 /* The data sheet seems to imply that just a number on its own is valid
1397 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
1399 if (**str
== 'p' || **str
== 'P')
1403 if (pchar
>= '0' && pchar
<= '9')
1405 processor
= pchar
- '0';
1406 if (**str
>= '0' && **str
<= '9')
1408 processor
= processor
* 10 + *(*str
)++ - '0';
1411 inst
.error
= "Illegal co-processor number";
1418 inst
.error
= "Bad or missing co-processor number";
1422 inst
.instruction
|= processor
<< 8;
1427 cp_opc_expr (str
, where
, length
)
1434 while (**str
== ' ')
1437 memset (&expr
, '\0', sizeof (expr
));
1439 if (my_get_expression (&expr
, str
))
1441 if (expr
.X_op
!= O_constant
)
1443 inst
.error
= "bad or missing expression";
1447 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
1449 inst
.error
= "immediate co-processor expression too large";
1453 inst
.instruction
|= expr
.X_add_number
<< where
;
1458 cp_reg_required_here (str
, where
)
1465 if ((reg
= arm_reg_parse (str
)) != FAIL
&& cp_register (reg
))
1468 inst
.instruction
|= reg
<< where
;
1472 /* In the few cases where we might be able to accept something else
1473 this error can be overridden */
1474 inst
.error
= "Co-processor register expected";
1476 /* Restore the start point */
1482 fp_reg_required_here (str
, where
)
1489 if ((reg
= arm_reg_parse (str
)) != FAIL
&& fp_register (reg
))
1492 inst
.instruction
|= reg
<< where
;
1496 /* In the few cases where we might be able to accept something else
1497 this error can be overridden */
1498 inst
.error
= "Floating point register expected";
1500 /* Restore the start point */
1506 cp_address_offset (str
)
1511 while (**str
== ' ')
1516 inst
.error
= "immediate expression expected";
1521 if (my_get_expression (&inst
.reloc
.exp
, str
))
1523 if (inst
.reloc
.exp
.X_op
== O_constant
)
1525 offset
= inst
.reloc
.exp
.X_add_number
;
1528 inst
.error
= "co-processor address must be word aligned";
1532 if (offset
> 1023 || offset
< -1023)
1534 inst
.error
= "offset too large";
1539 inst
.instruction
|= INDEX_UP
;
1543 inst
.instruction
|= offset
>> 2;
1546 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
1552 cp_address_required_here (str
)
1567 if ((reg
= reg_required_here (&p
, 16)) == FAIL
)
1569 inst
.error
= "Register required";
1579 if (skip_past_comma (&p
) == SUCCESS
)
1582 write_back
= WRITE_BACK
;
1585 inst
.error
= "pc may not be used in post-increment";
1589 if (cp_address_offset (&p
) == FAIL
)
1593 pre_inc
= PRE_INDEX
| INDEX_UP
;
1597 /* '['Rn, #expr']'[!] */
1599 if (skip_past_comma (&p
) == FAIL
)
1601 inst
.error
= "pre-indexed expression expected";
1605 pre_inc
= PRE_INDEX
;
1606 if (cp_address_offset (&p
) == FAIL
)
1614 inst
.error
= "missing ]";
1625 inst
.error
= "pc may not be used with write-back";
1630 write_back
= WRITE_BACK
;
1636 if (my_get_expression (&inst
.reloc
.exp
, &p
))
1639 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
1640 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust */
1641 inst
.reloc
.pc_rel
= 1;
1642 inst
.instruction
|= (REG_PC
<< 16);
1643 pre_inc
= PRE_INDEX
;
1646 inst
.instruction
|= write_back
| pre_inc
;
1654 unsigned long flags
;
1656 /* Do nothing really */
1657 inst
.instruction
|= flags
; /* This is pointless */
1665 unsigned long flags
;
1667 /* Only one syntax */
1671 if (reg_required_here (&str
, 12) == FAIL
)
1673 inst
.error
= bad_args
;
1677 if (skip_past_comma (&str
) == FAIL
1678 || psr_required_here (&str
, 22) == FAIL
)
1680 inst
.error
= "<psr> expected";
1684 inst
.instruction
|= flags
;
1692 unsigned long flags
;
1695 /* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression" */
1700 if ((psr
= psr_required_here (&str
, 22)) != FAIL
)
1702 inst
.instruction
|= PSR_ALL
;
1703 /* Sytax should be "<psr>, Rm" */
1704 if (skip_past_comma (&str
) == FAIL
1705 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
1707 inst
.error
= bad_args
;
1711 else if ((psrf
= psrf_required_here (&str
, 22)) != FAIL
)
1712 /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
1714 if (skip_past_comma (&str
) == FAIL
)
1716 inst
.error
= bad_args
;
1719 if ((reg
= reg_required_here (&str
, 0)) != FAIL
)
1721 /* Immediate expression */
1722 else if (*(str
++) == '#')
1725 if (my_get_expression (&inst
.reloc
.exp
, &str
))
1727 inst
.error
= "Register or shift expression expected";
1731 if (inst
.reloc
.exp
.X_add_symbol
)
1733 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
1734 inst
.reloc
.pc_rel
= 0;
1738 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
1741 inst
.error
= "Invalid constant";
1745 inst
.instruction
|= value
;
1748 flags
|= INST_IMMEDIATE
;
1752 inst
.error
= "Error: the other";
1758 inst
.error
= bad_args
;
1763 inst
.instruction
|= flags
;
1768 /* Long Multiply Parser
1769 UMULL RdLo, RdHi, Rm, Rs
1770 SMULL RdLo, RdHi, Rm, Rs
1771 UMLAL RdLo, RdHi, Rm, Rs
1772 SMLAL RdLo, RdHi, Rm, Rs
1775 do_mull (str
, flags
)
1777 unsigned long flags
;
1779 int rdlo
, rdhi
, rm
, rs
;
1781 /* only one format "rdlo, rdhi, rm, rs" */
1785 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
1787 inst
.error
= bad_args
;
1791 if (skip_past_comma (&str
) == FAIL
1792 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
1794 inst
.error
= bad_args
;
1798 if (skip_past_comma (&str
) == FAIL
1799 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
1801 inst
.error
= bad_args
;
1805 /* rdhi, rdlo and rm must all be different */
1806 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
1807 as_tsktsk ("rdhi, rdlo and rm must all be different");
1809 if (skip_past_comma (&str
) == FAIL
1810 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
1812 inst
.error
= bad_args
;
1816 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
1818 inst
.error
= bad_pc
;
1822 inst
.instruction
|= flags
;
1830 unsigned long flags
;
1834 /* only one format "rd, rm, rs" */
1838 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
1840 inst
.error
= bad_args
;
1846 inst
.error
= bad_pc
;
1850 if (skip_past_comma (&str
) == FAIL
1851 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
1853 inst
.error
= bad_args
;
1859 inst
.error
= bad_pc
;
1864 as_tsktsk ("rd and rm should be different in mul");
1866 if (skip_past_comma (&str
) == FAIL
1867 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
1869 inst
.error
= bad_args
;
1875 inst
.error
= bad_pc
;
1879 inst
.instruction
|= flags
;
1887 unsigned long flags
;
1891 /* only one format "rd, rm, rs, rn" */
1895 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
1897 inst
.error
= bad_args
;
1903 inst
.error
= bad_pc
;
1907 if (skip_past_comma (&str
) == FAIL
1908 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
1910 inst
.error
= bad_args
;
1916 inst
.error
= bad_pc
;
1921 as_tsktsk ("rd and rm should be different in mla");
1923 if (skip_past_comma (&str
) == FAIL
1924 || (rd
= reg_required_here (&str
, 8)) == FAIL
1925 || skip_past_comma (&str
) == FAIL
1926 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
1928 inst
.error
= bad_args
;
1932 if (rd
== REG_PC
|| rm
== REG_PC
)
1934 inst
.error
= bad_pc
;
1938 inst
.instruction
|= flags
;
1943 /* Returns the index into fp_values of a floating point number, or -1 if
1944 not in the table. */
1946 my_get_float_expression (str
)
1949 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1954 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
1955 /* Look for a raw floating point number */
1956 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
1957 && (is_end_of_line
[(int)(*save_in
)] || *save_in
== '\0'))
1959 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
1961 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
1963 if (words
[j
] != fp_values
[i
][j
])
1967 if (j
== MAX_LITTLENUMS
)
1975 /* Try and parse a more complex expression, this will probably fail
1976 unless the code uses a floating point prefix (eg "0f") */
1977 save_in
= input_line_pointer
;
1978 input_line_pointer
= *str
;
1979 if (expression (&exp
) == absolute_section
1980 && exp
.X_op
== O_big
1981 && exp
.X_add_number
< 0)
1983 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
1985 if (gen_to_words (words
, 5, (long)15) == 0)
1987 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
1989 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
1991 if (words
[j
] != fp_values
[i
][j
])
1995 if (j
== MAX_LITTLENUMS
)
1997 *str
= input_line_pointer
;
1998 input_line_pointer
= save_in
;
2005 *str
= input_line_pointer
;
2006 input_line_pointer
= save_in
;
2010 /* Return true if anything in the expression is a bignum */
2012 walk_no_bignums (sp
)
2015 if (sp
->sy_value
.X_op
== O_big
)
2018 if (sp
->sy_value
.X_add_symbol
)
2020 return (walk_no_bignums (sp
->sy_value
.X_add_symbol
)
2021 || (sp
->sy_value
.X_op_symbol
2022 && walk_no_bignums (sp
->sy_value
.X_op_symbol
)));
2029 my_get_expression (ep
, str
)
2036 save_in
= input_line_pointer
;
2037 input_line_pointer
= *str
;
2038 seg
= expression (ep
);
2041 if (seg
!= absolute_section
2042 && seg
!= text_section
2043 && seg
!= data_section
2044 && seg
!= bss_section
2045 && seg
!= undefined_section
)
2047 inst
.error
= "bad_segment";
2048 *str
= input_line_pointer
;
2049 input_line_pointer
= save_in
;
2054 /* Get rid of any bignums now, so that we don't generate an error for which
2055 we can't establish a line number later on. Big numbers are never valid
2056 in instructions, which is where this routine is always called. */
2057 if (ep
->X_op
== O_big
2058 || (ep
->X_add_symbol
2059 && (walk_no_bignums (ep
->X_add_symbol
)
2061 && walk_no_bignums (ep
->X_op_symbol
)))))
2063 inst
.error
= "Invalid constant";
2064 *str
= input_line_pointer
;
2065 input_line_pointer
= save_in
;
2069 *str
= input_line_pointer
;
2070 input_line_pointer
= save_in
;
2074 /* unrestrict should be one if <shift> <register> is permitted for this
2078 decode_shift (str
, unrestrict
)
2082 struct asm_shift
*shft
;
2086 while (**str
== ' ')
2089 for (p
= *str
; isalpha (*p
); p
++)
2094 inst
.error
= "Shift expression expected";
2100 shft
= (struct asm_shift
*) hash_find (arm_shift_hsh
, *str
);
2104 if (!strncmp (*str
, "rrx", 3)
2105 || !strncmp (*str
, "RRX", 3))
2108 inst
.instruction
|= shft
->value
;
2115 if (unrestrict
&& reg_required_here (&p
, 8) != FAIL
)
2117 inst
.instruction
|= shft
->value
| SHIFT_BY_REG
;
2125 if (my_get_expression (&inst
.reloc
.exp
, &p
))
2128 /* Validate some simple #expressions */
2129 if (inst
.reloc
.exp
.X_op
== O_constant
)
2131 unsigned num
= inst
.reloc
.exp
.X_add_number
;
2133 /* Reject operations greater than 32, or lsl #32 */
2134 if (num
> 32 || (num
== 32 && shft
->value
== 0))
2136 inst
.error
= "Invalid immediate shift";
2140 /* Shifts of zero should be converted to lsl (which is zero)*/
2147 /* Shifts of 32 are encoded as 0, for those shifts that
2152 inst
.instruction
|= (num
<< 7) | shft
->value
;
2157 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
2158 inst
.reloc
.pc_rel
= 0;
2159 inst
.instruction
|= shft
->value
;
2165 inst
.error
= unrestrict
? "shift requires register or #expression"
2166 : "shift requires #expression";
2172 inst
.error
= "Shift expression expected";
2176 /* Do those data_ops which can take a negative immediate constant */
2177 /* by altering the instuction. A bit of a hack really */
2181 by inverting the second operand, and
2184 by negating the second operand.
2187 negate_data_op (instruction
, value
)
2188 unsigned long *instruction
;
2189 unsigned long value
;
2192 unsigned long negated
, inverted
;
2194 negated
= validate_immediate (-value
);
2195 inverted
= validate_immediate (~value
);
2197 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
2201 case OPCODE_SUB
: /* ADD <-> SUB */
2202 new_inst
= OPCODE_ADD
;
2207 new_inst
= OPCODE_SUB
;
2211 case OPCODE_CMP
: /* CMP <-> CMN */
2212 new_inst
= OPCODE_CMN
;
2217 new_inst
= OPCODE_CMP
;
2221 /* Now Inverted ops */
2222 case OPCODE_MOV
: /* MOV <-> MVN */
2223 new_inst
= OPCODE_MVN
;
2228 new_inst
= OPCODE_MOV
;
2232 case OPCODE_AND
: /* AND <-> BIC */
2233 new_inst
= OPCODE_BIC
;
2238 new_inst
= OPCODE_AND
;
2242 case OPCODE_ADC
: /* ADC <-> SBC */
2243 new_inst
= OPCODE_SBC
;
2248 new_inst
= OPCODE_ADC
;
2252 /* We cannot do anything */
2260 *instruction
&= OPCODE_MASK
;
2261 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
2272 while (**str
== ' ')
2275 if (reg_required_here (str
, 0) != FAIL
)
2277 if (skip_past_comma (str
) == SUCCESS
)
2279 /* Shift operation on register */
2280 return decode_shift (str
, NO_SHIFT_RESTRICT
);
2286 /* Immediate expression */
2287 if (*((*str
)++) == '#')
2290 if (my_get_expression (&inst
.reloc
.exp
, str
))
2293 if (inst
.reloc
.exp
.X_add_symbol
)
2295 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2296 inst
.reloc
.pc_rel
= 0;
2300 if (skip_past_comma (str
) == SUCCESS
)
2302 /* #x, y -- ie explicit rotation by Y */
2303 if (my_get_expression (&expr
, str
))
2306 if (expr
.X_op
!= O_constant
)
2308 inst
.error
= "Constant expression expected";
2312 /* Rotate must be a multiple of 2 */
2313 if (((unsigned) expr
.X_add_number
) > 30
2314 || (expr
.X_add_number
& 1) != 0
2315 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
2317 inst
.error
= "Invalid constant";
2320 inst
.instruction
|= INST_IMMEDIATE
;
2321 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
2322 inst
.instruction
|= expr
.X_add_number
<< 7;
2326 /* Implicit rotation, select a suitable one */
2327 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
2331 /* Can't be done, perhaps the code reads something like
2332 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be ok */
2333 if ((value
= negate_data_op (&inst
.instruction
,
2334 inst
.reloc
.exp
.X_add_number
))
2337 inst
.error
= "Invalid constant";
2342 inst
.instruction
|= value
;
2345 inst
.instruction
|= INST_IMMEDIATE
;
2349 inst
.error
= "Register or shift expression expected";
2358 while (**str
== ' ')
2361 if (fp_reg_required_here (str
, 0) != FAIL
)
2365 /* Immediate expression */
2366 if (*((*str
)++) == '#')
2371 while (**str
== ' ')
2374 /* First try and match exact strings, this is to guarantee that
2375 some formats will work even for cross assembly */
2377 for (i
= 0; fp_const
[i
]; i
++)
2379 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
2383 *str
+= strlen (fp_const
[i
]);
2384 if (is_end_of_line
[(int)**str
] || **str
== '\0')
2386 inst
.instruction
|= i
+ 8;
2393 /* Just because we didn't get a match doesn't mean that the
2394 constant isn't valid, just that it is in a format that we
2395 don't automatically recognize. Try parsing it with
2396 the standard expression routines. */
2397 if ((i
= my_get_float_expression (str
)) >= 0)
2399 inst
.instruction
|= i
+ 8;
2403 inst
.error
= "Invalid floating point immediate expression";
2406 inst
.error
= "Floating point register or immediate expression expected";
2412 do_arit (str
, flags
)
2414 unsigned long flags
;
2419 if (reg_required_here (&str
, 12) == FAIL
2420 || skip_past_comma (&str
) == FAIL
2421 || reg_required_here (&str
, 16) == FAIL
2422 || skip_past_comma (&str
) == FAIL
2423 || data_op2 (&str
) == FAIL
)
2426 inst
.error
= bad_args
;
2430 inst
.instruction
|= flags
;
2438 unsigned long flags
;
2440 /* This is a pseudo-op of the form "adr rd, label" to be converted
2441 into a relative address of the form "add rd, pc, #label-.-8" */
2446 if (reg_required_here (&str
, 12) == FAIL
2447 || skip_past_comma (&str
) == FAIL
2448 || my_get_expression (&inst
.reloc
.exp
, &str
))
2451 inst
.error
= bad_args
;
2454 /* Frag hacking will turn this into a sub instruction if the offset turns
2455 out to be negative. */
2456 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
2457 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
2458 inst
.reloc
.pc_rel
= 1;
2459 inst
.instruction
|= flags
;
2467 unsigned long flags
;
2472 if (reg_required_here (&str
, 16) == FAIL
)
2475 inst
.error
= bad_args
;
2479 if (skip_past_comma (&str
) == FAIL
2480 || data_op2 (&str
) == FAIL
)
2483 inst
.error
= bad_args
;
2487 inst
.instruction
|= flags
;
2488 if ((flags
& 0x0000f000) == 0)
2489 inst
.instruction
|= CONDS_BIT
;
2498 unsigned long flags
;
2503 if (reg_required_here (&str
, 12) == FAIL
)
2506 inst
.error
= bad_args
;
2510 if (skip_past_comma (&str
) == FAIL
2511 || data_op2 (&str
) == FAIL
)
2514 inst
.error
= bad_args
;
2518 inst
.instruction
|= flags
;
2524 ldst_extend (str
, hwse
)
2534 if (my_get_expression (&inst
.reloc
.exp
, str
))
2537 if (inst
.reloc
.exp
.X_op
== O_constant
)
2539 int value
= inst
.reloc
.exp
.X_add_number
;
2541 if ((hwse
&& (value
< -255 || value
> 255))
2542 || (value
< -4095 || value
> 4095))
2544 inst
.error
= "address offset too large";
2554 /* Halfword and signextension instructions have the
2555 immediate value split across bits 11..8 and bits 3..0 */
2557 inst
.instruction
|= add
| HWOFFSET_IMM
| (value
>> 4) << 8 | value
& 0xF;
2559 inst
.instruction
|= add
| value
;
2565 inst
.instruction
|= HWOFFSET_IMM
;
2566 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2569 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
2570 inst
.reloc
.pc_rel
= 0;
2575 add
= 0; /* and fall through */
2577 (*str
)++; /* and fall through */
2579 if (reg_required_here (str
, 0) == FAIL
)
2581 inst
.error
= "Register expected";
2586 inst
.instruction
|= add
;
2589 inst
.instruction
|= add
| OFFSET_REG
;
2590 if (skip_past_comma (str
) == SUCCESS
)
2591 return decode_shift (str
, SHIFT_RESTRICT
);
2599 do_ldst (str
, flags
)
2601 unsigned long flags
;
2608 /* This is not ideal, but it is the simplest way of dealing with the
2609 ARM7T halfword instructions (since they use a different
2610 encoding, but the same mnemonic): */
2611 if (halfword
= ((flags
& 0x80000000) != 0))
2613 /* This is actually a load/store of a halfword, or a
2614 signed-extension load */
2615 if ((cpu_variant
& ARM_HALFWORD
) == 0)
2618 = "Processor does not support halfwords or signed bytes";
2622 inst
.instruction
= (inst
.instruction
& COND_MASK
)
2623 | (flags
& ~COND_MASK
);
2631 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
2634 inst
.error
= bad_args
;
2638 if (skip_past_comma (&str
) == FAIL
)
2640 inst
.error
= "Address expected";
2652 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
2654 inst
.error
= "Register required";
2658 conflict_reg
= (((conflict_reg
== reg
)
2659 && (inst
.instruction
& LOAD_BIT
))
2668 if (skip_past_comma (&str
) == SUCCESS
)
2670 /* [Rn],... (post inc) */
2671 if (ldst_extend (&str
, halfword
) == FAIL
)
2674 as_warn ("destination register same as write-back base\n");
2680 inst
.instruction
|= HWOFFSET_IMM
;
2688 as_warn ("destination register same as write-back base\n");
2690 inst
.instruction
|= WRITE_BACK
;
2694 if (! (flags
& TRANS_BIT
))
2701 if (skip_past_comma (&str
) == FAIL
)
2703 inst
.error
= "pre-indexed expression expected";
2708 if (ldst_extend (&str
, halfword
) == FAIL
)
2716 inst
.error
= "missing ]";
2726 as_tsktsk ("destination register same as write-back base\n");
2728 inst
.instruction
|= WRITE_BACK
;
2732 else if (*str
== '=')
2734 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
2740 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2743 if (inst
.reloc
.exp
.X_op
!= O_constant
2744 && inst
.reloc
.exp
.X_op
!= O_symbol
)
2746 inst
.error
= "Constant expression expected";
2750 if (inst
.reloc
.exp
.X_op
== O_constant
2751 && (value
= validate_immediate(inst
.reloc
.exp
.X_add_number
)) != FAIL
)
2753 /* This can be done with a mov instruction */
2754 inst
.instruction
&= LITERAL_MASK
;
2755 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
2756 inst
.instruction
|= (flags
& COND_MASK
) | (value
& 0xfff);
2762 /* Insert into literal pool */
2763 if (add_to_lit_pool () == FAIL
)
2766 inst
.error
= "literal pool insertion failed";
2770 /* Change the instruction exp to point to the pool */
2773 inst
.instruction
|= HWOFFSET_IMM
;
2774 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
2777 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
2778 inst
.reloc
.pc_rel
= 1;
2779 inst
.instruction
|= (REG_PC
<< 16);
2785 if (my_get_expression (&inst
.reloc
.exp
, &str
))
2790 inst
.instruction
|= HWOFFSET_IMM
;
2791 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
2794 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
2795 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust */
2796 inst
.reloc
.pc_rel
= 1;
2797 inst
.instruction
|= (REG_PC
<< 16);
2801 if (pre_inc
&& (flags
& TRANS_BIT
))
2802 inst
.error
= "Pre-increment instruction with translate";
2804 inst
.instruction
|= flags
| (pre_inc
? PRE_INDEX
: 0);
2817 /* We come back here if we get ranges concatenated by '+' or '|' */
2835 if ((reg
= arm_reg_parse (&str
)) == FAIL
|| !int_register (reg
))
2837 inst
.error
= "Register expected";
2847 inst
.error
= "Bad range in register list";
2851 for (i
= cur_reg
+ 1; i
< reg
; i
++)
2853 if (range
& (1 << i
))
2855 ("Warning: Duplicated register (r%d) in register list",
2863 if (range
& (1 << reg
))
2864 as_tsktsk ("Warning: Duplicated register (r%d) in register list",
2866 else if (reg
<= cur_reg
)
2867 as_tsktsk ("Warning: Register range not in ascending order");
2871 } while (skip_past_comma (&str
) != FAIL
2872 || (in_range
= 1, *str
++ == '-'));
2879 inst
.error
= "Missing `}'";
2887 if (my_get_expression (&expr
, &str
))
2890 if (expr
.X_op
== O_constant
)
2892 if (expr
.X_add_number
2893 != (expr
.X_add_number
& 0x0000ffff))
2895 inst
.error
= "invalid register mask";
2899 if ((range
& expr
.X_add_number
) != 0)
2901 int regno
= range
& expr
.X_add_number
;
2904 regno
= (1 << regno
) - 1;
2906 ("Warning: Duplicated register (r%d) in register list",
2910 range
|= expr
.X_add_number
;
2914 if (inst
.reloc
.type
!= 0)
2916 inst
.error
= "expression too complex";
2920 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
2921 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
2922 inst
.reloc
.pc_rel
= 0;
2929 if (*str
== '|' || *str
== '+')
2934 } while (another_range
);
2941 do_ldmstm (str
, flags
)
2943 unsigned long flags
;
2951 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
2954 inst
.error
= bad_args
;
2958 if (base_reg
== REG_PC
)
2960 inst
.error
= "r15 not allowed as base register";
2968 flags
|= WRITE_BACK
;
2972 if (skip_past_comma (&str
) == FAIL
2973 || (range
= reg_list (&str
)) == FAIL
)
2976 inst
.error
= bad_args
;
2983 flags
|= MULTI_SET_PSR
;
2986 inst
.instruction
|= flags
| range
;
2994 unsigned long flags
;
2996 /* Allow optional leading '#'. */
3002 if (my_get_expression (&inst
.reloc
.exp
, &str
))
3005 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
3006 inst
.reloc
.pc_rel
= 0;
3007 inst
.instruction
|= flags
;
3013 do_swap (str
, flags
)
3015 unsigned long flags
;
3022 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
3027 inst
.error
= "r15 not allowed in swap";
3031 if (skip_past_comma (&str
) == FAIL
3032 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
3035 inst
.error
= bad_args
;
3041 inst
.error
= "r15 not allowed in swap";
3045 if (skip_past_comma (&str
) == FAIL
3048 inst
.error
= bad_args
;
3055 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
3060 inst
.error
= bad_pc
;
3069 inst
.error
= "missing ]";
3073 inst
.instruction
|= flags
;
3079 do_branch (str
, flags
)
3081 unsigned long flags
;
3083 if (my_get_expression (&inst
.reloc
.exp
, &str
))
3085 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
3086 inst
.reloc
.pc_rel
= 1;
3094 unsigned long flags
;
3101 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3105 as_tsktsk ("Use of r15 in bx has undefined behaviour");
3114 unsigned long flags
;
3116 /* Co-processor data operation.
3117 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
3121 if (co_proc_number (&str
) == FAIL
)
3124 inst
.error
= bad_args
;
3128 if (skip_past_comma (&str
) == FAIL
3129 || cp_opc_expr (&str
, 20,4) == FAIL
)
3132 inst
.error
= bad_args
;
3136 if (skip_past_comma (&str
) == FAIL
3137 || cp_reg_required_here (&str
, 12) == FAIL
)
3140 inst
.error
= bad_args
;
3144 if (skip_past_comma (&str
) == FAIL
3145 || cp_reg_required_here (&str
, 16) == FAIL
)
3148 inst
.error
= bad_args
;
3152 if (skip_past_comma (&str
) == FAIL
3153 || cp_reg_required_here (&str
, 0) == FAIL
)
3156 inst
.error
= bad_args
;
3160 if (skip_past_comma (&str
) == SUCCESS
)
3162 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
3165 inst
.error
= bad_args
;
3175 do_lstc (str
, flags
)
3177 unsigned long flags
;
3179 /* Co-processor register load/store.
3180 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
3185 if (co_proc_number (&str
) == FAIL
)
3188 inst
.error
= bad_args
;
3192 if (skip_past_comma (&str
) == FAIL
3193 || cp_reg_required_here (&str
, 12) == FAIL
)
3196 inst
.error
= bad_args
;
3200 if (skip_past_comma (&str
) == FAIL
3201 || cp_address_required_here (&str
) == FAIL
)
3204 inst
.error
= bad_args
;
3208 inst
.instruction
|= flags
;
3214 do_co_reg (str
, flags
)
3216 unsigned long flags
;
3218 /* Co-processor register transfer.
3219 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
3224 if (co_proc_number (&str
) == FAIL
)
3227 inst
.error
= bad_args
;
3231 if (skip_past_comma (&str
) == FAIL
3232 || cp_opc_expr (&str
, 21, 3) == FAIL
)
3235 inst
.error
= bad_args
;
3239 if (skip_past_comma (&str
) == FAIL
3240 || reg_required_here (&str
, 12) == FAIL
)
3243 inst
.error
= bad_args
;
3247 if (skip_past_comma (&str
) == FAIL
3248 || cp_reg_required_here (&str
, 16) == FAIL
)
3251 inst
.error
= bad_args
;
3255 if (skip_past_comma (&str
) == FAIL
3256 || cp_reg_required_here (&str
, 0) == FAIL
)
3259 inst
.error
= bad_args
;
3263 if (skip_past_comma (&str
) == SUCCESS
)
3265 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
3268 inst
.error
= bad_args
;
3278 do_fp_ctrl (str
, flags
)
3280 unsigned long flags
;
3282 /* FP control registers.
3283 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
3288 if (reg_required_here (&str
, 12) == FAIL
)
3291 inst
.error
= bad_args
;
3300 do_fp_ldst (str
, flags
)
3302 unsigned long flags
;
3307 switch (inst
.suffix
)
3312 inst
.instruction
|= CP_T_X
;
3315 inst
.instruction
|= CP_T_Y
;
3318 inst
.instruction
|= CP_T_X
| CP_T_Y
;
3324 if (fp_reg_required_here (&str
, 12) == FAIL
)
3327 inst
.error
= bad_args
;
3331 if (skip_past_comma (&str
) == FAIL
3332 || cp_address_required_here (&str
) == FAIL
)
3335 inst
.error
= bad_args
;
3343 do_fp_ldmstm (str
, flags
)
3345 unsigned long flags
;
3352 if (fp_reg_required_here (&str
, 12) == FAIL
)
3355 inst
.error
= bad_args
;
3359 /* Get Number of registers to transfer */
3360 if (skip_past_comma (&str
) == FAIL
3361 || my_get_expression (&inst
.reloc
.exp
, &str
))
3364 inst
.error
= "constant expression expected";
3368 if (inst
.reloc
.exp
.X_op
!= O_constant
)
3370 inst
.error
= "Constant value required for number of registers";
3374 num_regs
= inst
.reloc
.exp
.X_add_number
;
3376 if (num_regs
< 1 || num_regs
> 4)
3378 inst
.error
= "number of registers must be in the range [1:4]";
3385 inst
.instruction
|= CP_T_X
;
3388 inst
.instruction
|= CP_T_Y
;
3391 inst
.instruction
|= CP_T_Y
| CP_T_X
;
3405 /* The instruction specified "ea" or "fd", so we can only accept
3406 [Rn]{!}. The instruction does not really support stacking or
3407 unstacking, so we have to emulate these by setting appropriate
3408 bits and offsets. */
3409 if (skip_past_comma (&str
) == FAIL
3413 inst
.error
= bad_args
;
3421 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
3423 inst
.error
= "Register required";
3432 inst
.error
= bad_args
;
3443 inst
.error
= "R15 not allowed as base register with write-back";
3450 if (flags
& CP_T_Pre
)
3453 offset
= 3 * num_regs
;
3459 /* Post-increment */
3463 offset
= 3 * num_regs
;
3467 /* No write-back, so convert this into a standard pre-increment
3468 instruction -- aesthetically more pleasing. */
3469 flags
= CP_T_Pre
| CP_T_UD
;
3474 inst
.instruction
|= flags
| offset
;
3476 else if (skip_past_comma (&str
) == FAIL
3477 || cp_address_required_here (&str
) == FAIL
)
3480 inst
.error
= bad_args
;
3488 do_fp_dyadic (str
, flags
)
3490 unsigned long flags
;
3495 switch (inst
.suffix
)
3500 inst
.instruction
|= 0x00000080;
3503 inst
.instruction
|= 0x00080000;
3509 if (fp_reg_required_here (&str
, 12) == FAIL
)
3512 inst
.error
= bad_args
;
3516 if (skip_past_comma (&str
) == FAIL
3517 || fp_reg_required_here (&str
, 16) == FAIL
)
3520 inst
.error
= bad_args
;
3524 if (skip_past_comma (&str
) == FAIL
3525 || fp_op2 (&str
) == FAIL
)
3528 inst
.error
= bad_args
;
3532 inst
.instruction
|= flags
;
3538 do_fp_monadic (str
, flags
)
3540 unsigned long flags
;
3545 switch (inst
.suffix
)
3550 inst
.instruction
|= 0x00000080;
3553 inst
.instruction
|= 0x00080000;
3559 if (fp_reg_required_here (&str
, 12) == FAIL
)
3562 inst
.error
= bad_args
;
3566 if (skip_past_comma (&str
) == FAIL
3567 || fp_op2 (&str
) == FAIL
)
3570 inst
.error
= bad_args
;
3574 inst
.instruction
|= flags
;
3580 do_fp_cmp (str
, flags
)
3582 unsigned long flags
;
3587 if (fp_reg_required_here (&str
, 16) == FAIL
)
3590 inst
.error
= bad_args
;
3594 if (skip_past_comma (&str
) == FAIL
3595 || fp_op2 (&str
) == FAIL
)
3598 inst
.error
= bad_args
;
3602 inst
.instruction
|= flags
;
3608 do_fp_from_reg (str
, flags
)
3610 unsigned long flags
;
3615 switch (inst
.suffix
)
3620 inst
.instruction
|= 0x00000080;
3623 inst
.instruction
|= 0x00080000;
3629 if (fp_reg_required_here (&str
, 16) == FAIL
)
3632 inst
.error
= bad_args
;
3636 if (skip_past_comma (&str
) == FAIL
3637 || reg_required_here (&str
, 12) == FAIL
)
3640 inst
.error
= bad_args
;
3644 inst
.instruction
|= flags
;
3650 do_fp_to_reg (str
, flags
)
3652 unsigned long flags
;
3657 if (reg_required_here (&str
, 12) == FAIL
)
3660 inst
.error
= bad_args
;
3664 if (skip_past_comma (&str
) == FAIL
3665 || fp_reg_required_here (&str
, 0) == FAIL
)
3668 inst
.error
= bad_args
;
3672 inst
.instruction
|= flags
;
3677 /* Thumb specific routines */
3679 /* Parse and validate that a register is of the right form, this saves
3680 repeated checking of this information in many similar cases.
3681 Unlike the 32-bit case we do not insert the register into the opcode
3682 here, since the position is often unknown until the full instruction
3685 thumb_reg (strp
, hi_lo
)
3691 if ((reg
= arm_reg_parse (strp
)) == FAIL
|| ! int_register (reg
))
3693 inst
.error
= "Register expected";
3702 inst
.error
= "lo register required";
3710 inst
.error
= "hi register required";
3722 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
3725 thumb_add_sub (str
, subtract
)
3729 int Rd
, Rs
, Rn
= FAIL
;
3734 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
3735 || skip_past_comma (&str
) == FAIL
)
3738 inst
.error
= bad_args
;
3746 if (my_get_expression (&inst
.reloc
.exp
, &str
))
3751 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
3754 if (skip_past_comma (&str
) == FAIL
)
3756 /* Two operand format, shuffle the registers and pretend there
3761 else if (*str
== '#')
3764 if (my_get_expression (&inst
.reloc
.exp
, &str
))
3767 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
3771 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
3772 for the latter case, EXPR contains the immediate that was found. */
3775 /* All register format. */
3776 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
3780 inst
.error
= "dest and source1 must be the same register";
3784 /* Can't do this for SUB */
3787 inst
.error
= "subtract valid only on lo regs";
3791 inst
.instruction
= (T_OPCODE_ADD_HI
3792 | (Rd
> 7 ? THUMB_H1
: 0)
3793 | (Rn
> 7 ? THUMB_H2
: 0));
3794 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
3798 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
3799 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
3804 /* Immediate expression, now things start to get nasty. */
3806 /* First deal with HI regs, only very restricted cases allowed:
3807 Adjusting SP, and using PC or SP to get an address. */
3808 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
3809 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
3811 inst
.error
= "invalid Hi register with immediate";
3815 if (inst
.reloc
.exp
.X_op
!= O_constant
)
3817 /* Value isn't known yet, all we can do is store all the fragments
3818 we know about in the instruction and let the reloc hacking
3820 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
3821 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
3825 int offset
= inst
.reloc
.exp
.X_add_number
;
3835 /* Quick check, in case offset is MIN_INT */
3838 inst
.error
= "immediate value out of range";
3847 if (offset
& ~0x1fc)
3849 inst
.error
= "invalid immediate value for stack adjust";
3852 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
3853 inst
.instruction
|= offset
>> 2;
3855 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
3858 || (offset
& ~0x3fc))
3860 inst
.error
= "invalid immediate for address calculation";
3863 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
3865 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
3871 inst
.error
= "immediate value out of range";
3874 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
3875 inst
.instruction
|= (Rd
<< 8) | offset
;
3881 inst
.error
= "immediate value out of range";
3884 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
3885 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
3893 thumb_shift (str
, shift
)
3897 int Rd
, Rs
, Rn
= FAIL
;
3902 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
3903 || skip_past_comma (&str
) == FAIL
)
3906 inst
.error
= bad_args
;
3912 /* Two operand immediate format, set Rs to Rd. */
3915 if (my_get_expression (&inst
.reloc
.exp
, &str
))
3920 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
3923 if (skip_past_comma (&str
) == FAIL
)
3925 /* Two operand format, shuffle the registers and pretend there
3930 else if (*str
== '#')
3933 if (my_get_expression (&inst
.reloc
.exp
, &str
))
3936 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
3940 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
3941 for the latter case, EXPR contains the immediate that was found. */
3947 inst
.error
= "source1 and dest must be same register";
3953 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
3954 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
3955 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
3958 inst
.instruction
|= Rd
| (Rn
<< 3);
3964 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
3965 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
3966 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
3969 if (inst
.reloc
.exp
.X_op
!= O_constant
)
3971 /* Value isn't known yet, create a dummy reloc and let reloc
3972 hacking fix it up */
3974 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
3978 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
3980 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
3982 inst
.error
= "Invalid immediate for shift";
3986 /* Shifts of zero are handled by converting to LSL */
3987 if (shift_value
== 0)
3988 inst
.instruction
= T_OPCODE_LSL_I
;
3990 /* Shifts of 32 are encoded as a shift of zero */
3991 if (shift_value
== 32)
3994 inst
.instruction
|= shift_value
<< 6;
3997 inst
.instruction
|= Rd
| (Rs
<< 3);
4003 thumb_mov_compare (str
, move
)
4012 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
4013 || skip_past_comma (&str
) == FAIL
)
4016 inst
.error
= bad_args
;
4023 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4026 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4031 if (Rs
< 8 && Rd
< 8)
4033 if (move
== THUMB_MOVE
)
4034 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4035 since a MOV instruction produces unpredictable results */
4036 inst
.instruction
= T_OPCODE_ADD_I3
;
4038 inst
.instruction
= T_OPCODE_CMP_LR
;
4039 inst
.instruction
|= Rd
| (Rs
<< 3);
4043 if (move
== THUMB_MOVE
)
4044 inst
.instruction
= T_OPCODE_MOV_HR
;
4046 inst
.instruction
= T_OPCODE_CMP_HR
;
4049 inst
.instruction
|= THUMB_H1
;
4052 inst
.instruction
|= THUMB_H2
;
4054 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
4061 inst
.error
= "only lo regs allowed with immediate";
4065 if (move
== THUMB_MOVE
)
4066 inst
.instruction
= T_OPCODE_MOV_I8
;
4068 inst
.instruction
= T_OPCODE_CMP_I8
;
4070 inst
.instruction
|= Rd
<< 8;
4072 if (inst
.reloc
.exp
.X_op
!= O_constant
)
4073 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
4076 unsigned value
= inst
.reloc
.exp
.X_add_number
;
4080 inst
.error
= "invalid immediate";
4084 inst
.instruction
|= value
;
4092 thumb_load_store (str
, load_store
, size
)
4097 int Rd
, Rb
, Ro
= FAIL
;
4102 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
4103 || skip_past_comma (&str
) == FAIL
)
4106 inst
.error
= bad_args
;
4113 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4116 if (skip_past_comma (&str
) != FAIL
)
4121 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4124 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
4129 inst
.reloc
.exp
.X_op
= O_constant
;
4130 inst
.reloc
.exp
.X_add_number
= 0;
4135 inst
.error
= "expected ']'";
4140 else if (*str
== '=')
4142 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
4148 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4153 if ( inst
.reloc
.exp
.X_op
!= O_constant
4154 && inst
.reloc
.exp
.X_op
!= O_symbol
)
4156 inst
.error
= "Constant expression expected";
4160 if (inst
.reloc
.exp
.X_op
== O_constant
4161 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
4163 /* This can be done with a mov instruction */
4165 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
4166 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
4170 /* Insert into literal pool */
4171 if (add_to_lit_pool () == FAIL
)
4174 inst
.error
= "literal pool insertion failed";
4178 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
4179 inst
.reloc
.pc_rel
= 1;
4180 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
4181 inst
.reloc
.exp
.X_add_number
+= 4; /* Adjust ARM pipeline offset to Thumb */
4187 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4190 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
4191 inst
.reloc
.pc_rel
= 1;
4192 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset */
4193 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
4198 if (Rb
== REG_PC
|| Rb
== REG_SP
)
4200 if (size
!= THUMB_WORD
)
4202 inst
.error
= "byte or halfword not valid for base register";
4205 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
4207 inst
.error
= "R15 based store not allowed";
4210 else if (Ro
!= FAIL
)
4212 inst
.error
= "Invalid base register for register offset";
4217 inst
.instruction
= T_OPCODE_LDR_PC
;
4218 else if (load_store
== THUMB_LOAD
)
4219 inst
.instruction
= T_OPCODE_LDR_SP
;
4221 inst
.instruction
= T_OPCODE_STR_SP
;
4223 inst
.instruction
|= Rd
<< 8;
4224 if (inst
.reloc
.exp
.X_op
== O_constant
)
4226 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
4228 if (offset
& ~0x3fc)
4230 inst
.error
= "invalid offset";
4234 inst
.instruction
|= offset
>> 2;
4237 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
4241 inst
.error
= "invalid base register in load/store";
4244 else if (Ro
== FAIL
)
4246 /* Immediate offset */
4247 if (size
== THUMB_WORD
)
4248 inst
.instruction
= (load_store
== THUMB_LOAD
4249 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
4250 else if (size
== THUMB_HALFWORD
)
4251 inst
.instruction
= (load_store
== THUMB_LOAD
4252 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
4254 inst
.instruction
= (load_store
== THUMB_LOAD
4255 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
4257 inst
.instruction
|= Rd
| (Rb
<< 3);
4259 if (inst
.reloc
.exp
.X_op
== O_constant
)
4261 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
4263 if (offset
& ~(0x1f << size
))
4265 inst
.error
= "Invalid offset";
4268 inst
.instruction
|= (offset
>> size
) << 6;
4271 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
4275 /* Register offset */
4276 if (size
== THUMB_WORD
)
4277 inst
.instruction
= (load_store
== THUMB_LOAD
4278 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
4279 else if (size
== THUMB_HALFWORD
)
4280 inst
.instruction
= (load_store
== THUMB_LOAD
4281 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
4283 inst
.instruction
= (load_store
== THUMB_LOAD
4284 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
4286 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
4301 /* Handle the Format 4 instructions that do not have equivalents in other
4302 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
4313 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
4316 if (skip_past_comma (&str
) == FAIL
4317 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
4320 inst
.error
= bad_args
;
4324 if (skip_past_comma (&str
) != FAIL
)
4326 /* Three operand format not allowed for TST, CMN, NEG and MVN.
4327 (It isn't allowed for CMP either, but that isn't handled by this
4329 if (inst
.instruction
== T_OPCODE_TST
4330 || inst
.instruction
== T_OPCODE_CMN
4331 || inst
.instruction
== T_OPCODE_NEG
4332 || inst
.instruction
== T_OPCODE_MVN
)
4334 inst
.error
= bad_args
;
4338 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
4343 inst
.error
= "dest and source1 one must be the same register";
4349 if (inst
.instruction
== T_OPCODE_MUL
4351 as_tsktsk ("Rs and Rd must be different in MUL");
4353 inst
.instruction
|= Rd
| (Rs
<< 3);
4361 thumb_add_sub (str
, 0);
4368 thumb_shift (str
, THUMB_ASR
);
4375 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4377 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
4378 inst
.reloc
.pc_rel
= 1;
4386 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4388 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
4389 inst
.reloc
.pc_rel
= 1;
4393 /* Find the real, Thumb encoded start of a Thumb function. */
4396 find_real_start (symbolP
)
4400 const char * name
= S_GET_NAME (symbolP
);
4401 symbolS
* new_target
;
4403 /* This definitonmust agree with the one in gcc/config/arm/thumb.c */
4404 #define STUB_NAME ".real_start_of"
4406 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
4407 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
4409 new_target
= symbol_find (real_start
);
4411 if (new_target
== NULL
)
4424 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4426 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
4427 inst
.reloc
.pc_rel
= 1;
4430 /* If the destination of the branch is a defined symbol which does not have
4431 the THUMB_FUNC attribute, then we must be calling a function which has
4432 the (interfacearm) attribute. We look for the Thumb entry point to that
4433 function and change the branch to refer to that function instead. */
4434 if ( inst
.reloc
.exp
.X_op
== O_symbol
4435 && inst
.reloc
.exp
.X_add_symbol
!= NULL
4436 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
4437 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
4438 inst
.reloc
.exp
.X_add_symbol
= find_real_start (inst
.reloc
.exp
.X_add_symbol
);
4450 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
4453 /* This sets THUMB_H2 from the top bit of reg. */
4454 inst
.instruction
|= reg
<< 3;
4456 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
4457 should cause the alignment to be checked once it is known. This is
4458 because BX PC only works if the instruction is word aligned. */
4467 thumb_mov_compare (str
, THUMB_COMPARE
);
4480 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
4484 as_warn ("Inserted missing '!': load/store multiple always writes back base register");
4488 if (skip_past_comma (&str
) == FAIL
4489 || (range
= reg_list (&str
)) == FAIL
)
4492 inst
.error
= bad_args
;
4496 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
4498 /* This really doesn't seem worth it. */
4499 inst
.reloc
.type
= BFD_RELOC_NONE
;
4500 inst
.error
= "Expression too complex";
4506 inst
.error
= "only lo-regs valid in load/store multiple";
4510 inst
.instruction
|= (Rb
<< 8) | range
;
4518 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
4525 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
4532 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
4544 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
4545 || skip_past_comma (&str
) == FAIL
4547 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
4548 || skip_past_comma (&str
) == FAIL
4549 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
4553 inst
.error
= "Syntax: ldrs[b] Rd, [Rb, Ro]";
4557 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
4565 thumb_shift (str
, THUMB_LSL
);
4572 thumb_shift (str
, THUMB_LSR
);
4579 thumb_mov_compare (str
, THUMB_MOVE
);
4591 if ((range
= reg_list (&str
)) == FAIL
)
4594 inst
.error
= bad_args
;
4598 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
4600 /* This really doesn't seem worth it. */
4601 inst
.reloc
.type
= BFD_RELOC_NONE
;
4602 inst
.error
= "Expression too complex";
4608 if ((inst
.instruction
== T_OPCODE_PUSH
4609 && (range
& ~0xff) == 1 << REG_LR
)
4610 || (inst
.instruction
== T_OPCODE_POP
4611 && (range
& ~0xff) == 1 << REG_PC
))
4613 inst
.instruction
|= THUMB_PP_PC_LR
;
4618 inst
.error
= "invalid register list to push/pop instruction";
4623 inst
.instruction
|= range
;
4631 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
4638 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
4645 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
4652 thumb_add_sub (str
, 1);
4662 if (my_get_expression (&inst
.reloc
.exp
, &str
))
4665 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
4674 /* This is a pseudo-op of the form "adr rd, label" to be converted
4675 into a relative address of the form "add rd, pc, #label-.-4" */
4679 if (reg_required_here (&str
, 4) == FAIL
/* Store Rd in temporary location inside instruction. */
4680 || skip_past_comma (&str
) == FAIL
4681 || my_get_expression (&inst
.reloc
.exp
, &str
))
4684 inst
.error
= bad_args
;
4688 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
4689 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust */
4690 inst
.reloc
.pc_rel
= 1;
4691 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction */
4699 int len
= strlen (reg_table
[entry
].name
) + 2;
4700 char *buf
= (char *) xmalloc (len
);
4701 char *buf2
= (char *) xmalloc (len
);
4704 #ifdef REGISTER_PREFIX
4705 buf
[i
++] = REGISTER_PREFIX
;
4708 strcpy (buf
+ i
, reg_table
[entry
].name
);
4710 for (i
= 0; buf
[i
]; i
++)
4711 buf2
[i
] = islower (buf
[i
]) ? toupper (buf
[i
]) : buf
[i
];
4715 hash_insert (arm_reg_hsh
, buf
, (PTR
) ®_table
[entry
]);
4716 hash_insert (arm_reg_hsh
, buf2
, (PTR
) ®_table
[entry
]);
4720 insert_reg_alias (str
, regnum
)
4724 struct reg_entry
*new =
4725 (struct reg_entry
*)xmalloc (sizeof (struct reg_entry
));
4726 char *name
= xmalloc (strlen (str
) + 1);
4730 new->number
= regnum
;
4732 hash_insert (arm_reg_hsh
, name
, (PTR
) new);
4736 set_constant_flonums ()
4740 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4741 if (atof_ieee ((char *)fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
4750 if ((arm_ops_hsh
= hash_new ()) == NULL
4751 || (arm_tops_hsh
= hash_new ()) == NULL
4752 || (arm_cond_hsh
= hash_new ()) == NULL
4753 || (arm_shift_hsh
= hash_new ()) == NULL
4754 || (arm_reg_hsh
= hash_new ()) == NULL
4755 || (arm_psr_hsh
= hash_new ()) == NULL
)
4756 as_fatal ("Virtual memory exhausted");
4758 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
4759 hash_insert (arm_ops_hsh
, insns
[i
].template, (PTR
) (insns
+ i
));
4760 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
4761 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
4762 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
4763 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
4764 for (i
= 0; i
< sizeof (shift
) / sizeof (struct asm_shift
); i
++)
4765 hash_insert (arm_shift_hsh
, shift
[i
].template, (PTR
) (shift
+ i
));
4766 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
4767 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
4769 for (i
= 0; reg_table
[i
].name
; i
++)
4772 set_constant_flonums ();
4776 unsigned int flags
= 0;
4778 /* Set the flags in the private structure */
4779 if (uses_apcs_26
) flags
|= F_APCS26
;
4780 if (support_interwork
) flags
|= F_INTERWORK
;
4781 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
4782 if (pic_code
) flags
|= F_PIC
;
4784 bfd_set_private_flags (stdoutput
, flags
);
4791 /* Record the CPU type as well */
4792 switch (cpu_variant
& ARM_CPU_MASK
)
4795 mach
= bfd_mach_arm_2
;
4798 case ARM_3
: /* also ARM_250 */
4799 mach
= bfd_mach_arm_2a
;
4803 case ARM_6
| ARM_3
| ARM_2
: /* Actually no CPU type defined */
4804 mach
= bfd_mach_arm_4
;
4807 case ARM_7
: /* also ARM_6 */
4808 mach
= bfd_mach_arm_3
;
4812 /* Catch special cases */
4813 if (cpu_variant
!= (FPU_DEFAULT
| CPU_DEFAULT
))
4815 if (cpu_variant
& ARM_THUMB
)
4816 mach
= bfd_mach_arm_4T
;
4817 else if ((cpu_variant
& ARM_ARCHv4
) == ARM_ARCHv4
)
4818 mach
= bfd_mach_arm_4
;
4819 else if (cpu_variant
& ARM_LONGMUL
)
4820 mach
= bfd_mach_arm_3M
;
4823 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
4827 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4828 for use in the a.out file, and stores them in the array pointed to by buf.
4829 This knows about the endian-ness of the target machine and does
4830 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
4831 2 (short) and 4 (long) Floating numbers are put out as a series of
4832 LITTLENUMS (shorts, here at least)
4835 md_number_to_chars (buf
, val
, n
)
4840 if (target_big_endian
)
4841 number_to_chars_bigendian (buf
, val
, n
);
4843 number_to_chars_littleendian (buf
, val
, n
);
4847 md_chars_to_number (buf
, n
)
4852 unsigned char *where
= (unsigned char *) buf
;
4854 if (target_big_endian
)
4859 result
|= (*where
++ & 255);
4867 result
|= (where
[n
] & 255);
4874 /* Turn a string in input_line_pointer into a floating point constant
4875 of type TYPE, and store the appropriate bytes in *litP. The number
4876 of LITTLENUMS emitted is stored in *sizeP . An error message is
4877 returned, or NULL on OK.
4879 Note that fp constants aren't represent in the normal way on the ARM.
4880 In big endian mode, things are as expected. However, in little endian
4881 mode fp constants are big-endian word-wise, and little-endian byte-wise
4882 within the words. For example, (double) 1.1 in big endian mode is
4883 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
4884 the byte sequence 99 99 f1 3f 9a 99 99 99.
4886 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
4889 md_atof (type
, litP
, sizeP
)
4895 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
4927 return "Bad call to MD_ATOF()";
4930 t
= atof_ieee (input_line_pointer
, type
, words
);
4932 input_line_pointer
= t
;
4935 if (target_big_endian
)
4937 for (i
= 0; i
< prec
; i
++)
4939 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
4945 /* For a 4 byte float the order of elements in `words' is 1 0. For an
4946 8 byte float the order is 1 0 3 2. */
4947 for (i
= 0; i
< prec
; i
+= 2)
4949 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
4950 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
4958 /* We have already put the pipeline compensation in the instruction */
4961 md_pcrel_from (fixP
)
4965 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
4966 && fixP
->fx_subsy
== NULL
)
4967 return 0; /* HACK */
4969 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
4971 /* PC relative addressing on the Thumb is slightly odd
4972 as the bottom two bits of the PC are forced to zero
4973 for the calculation */
4974 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
4977 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
4980 /* Round up a section size to the appropriate boundary. */
4982 md_section_align (segment
, size
)
4986 /* Round all sects to multiple of 4 */
4987 return (size
+ 3) & ~3;
4990 /* We have no need to default values of symbols. */
4994 md_undefined_symbol (name
)
5000 /* arm_reg_parse () := if it looks like a register, return its token and
5001 advance the pointer. */
5005 register char **ccp
;
5010 struct reg_entry
*reg
;
5012 #ifdef REGISTER_PREFIX
5013 if (*start
!= REGISTER_PREFIX
)
5018 #ifdef OPTIONAL_REGISTER_PREFIX
5019 if (*p
== OPTIONAL_REGISTER_PREFIX
)
5023 if (!isalpha (*p
) || !is_name_beginner (*p
))
5027 while (isalpha (c
) || isdigit (c
) || c
== '_')
5031 reg
= (struct reg_entry
*) hash_find (arm_reg_hsh
, start
);
5045 register char **ccp
;
5049 CONST
struct asm_psr
*psr
;
5053 while (isalpha (c
) || c
== '_')
5057 psr
= (CONST
struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
5070 md_apply_fix3 (fixP
, val
, seg
)
5075 offsetT value
= *val
;
5077 unsigned int newimm
;
5080 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
5081 arm_fix_data
*arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
5083 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
5085 /* Note whether this will delete the relocation. */
5086 #if 0 /* patch from REarnshaw to JDavis (disabled for the moment, since it doesn't work fully) */
5087 if ((fixP
->fx_addsy
== 0 || fixP
->fx_addsy
->sy_value
.X_op
== O_constant
)
5090 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
5094 /* If this symbol is in a different section then we need to leave it for
5095 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5096 so we have to undo it's effects here. */
5099 if (fixP
->fx_addsy
!= NULL
5100 && S_IS_DEFINED (fixP
->fx_addsy
)
5101 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
5103 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
)
5106 value
+= md_pcrel_from (fixP
);
5110 fixP
->fx_addnumber
= value
; /* Remember value for emit_reloc */
5112 switch (fixP
->fx_r_type
)
5114 case BFD_RELOC_ARM_IMMEDIATE
:
5115 newimm
= validate_immediate (value
);
5116 temp
= md_chars_to_number (buf
, INSN_SIZE
);
5118 /* If the instruction will fail, see if we can fix things up by
5119 changing the opcode. */
5120 if (newimm
== (unsigned int) FAIL
5121 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
5123 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5124 "invalid constant after fixup\n");
5128 newimm
|= (temp
& 0xfffff000);
5129 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
5132 case BFD_RELOC_ARM_OFFSET_IMM
:
5134 if ((value
= validate_offset_imm (value
, 0)) == FAIL
)
5136 as_bad ("bad immediate value for offset (%d)", val
);
5142 newval
= md_chars_to_number (buf
, INSN_SIZE
);
5143 newval
&= 0xff7ff000;
5144 newval
|= value
| (sign
? INDEX_UP
: 0);
5145 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5148 case BFD_RELOC_ARM_OFFSET_IMM8
:
5149 case BFD_RELOC_ARM_HWLITERAL
:
5151 if ((value
= validate_offset_imm (value
, 1)) == FAIL
)
5153 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
5154 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5155 "invalid literal constant: pool needs to be closer\n");
5157 as_bad ("bad immediate value for offset (%d)", value
);
5164 newval
= md_chars_to_number (buf
, INSN_SIZE
);
5165 newval
&= 0xff7ff0f0;
5166 newval
|= ((value
>> 4) << 8) | value
& 0xf | (sign
? INDEX_UP
: 0);
5167 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5170 case BFD_RELOC_ARM_LITERAL
:
5175 if ((value
= validate_offset_imm (value
, 0)) == FAIL
)
5177 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5178 "invalid literal constant: pool needs to be closer\n");
5182 newval
= md_chars_to_number (buf
, INSN_SIZE
);
5183 newval
&= 0xff7ff000;
5184 newval
|= value
| (sign
? INDEX_UP
: 0);
5185 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5188 case BFD_RELOC_ARM_SHIFT_IMM
:
5189 newval
= md_chars_to_number (buf
, INSN_SIZE
);
5190 if (((unsigned long) value
) > 32
5192 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
5194 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5195 "shift expression is too large");
5200 newval
&= ~0x60; /* Shifts of zero must be done as lsl */
5201 else if (value
== 32)
5203 newval
&= 0xfffff07f;
5204 newval
|= (value
& 0x1f) << 7;
5205 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5208 case BFD_RELOC_ARM_SWI
:
5209 if (arm_data
->thumb_mode
)
5211 if (((unsigned long) value
) > 0xff)
5212 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5213 "Invalid swi expression");
5214 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
5216 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5220 if (((unsigned long) value
) > 0x00ffffff)
5221 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5222 "Invalid swi expression");
5223 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
5225 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5229 case BFD_RELOC_ARM_MULTI
:
5230 if (((unsigned long) value
) > 0xffff)
5231 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5232 "Invalid expression in load/store multiple");
5233 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
5234 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5237 case BFD_RELOC_ARM_PCREL_BRANCH
:
5238 value
= (value
>> 2) & 0x00ffffff;
5239 newval
= md_chars_to_number (buf
, INSN_SIZE
);
5240 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
5241 newval
= value
| (newval
& 0xff000000);
5242 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5245 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* conditional branch */
5246 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
5248 addressT diff
= (newval
& 0xff) << 1;
5253 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
5254 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5255 "Branch out of range");
5256 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
5258 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5261 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* unconditional branch */
5262 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
5264 addressT diff
= (newval
& 0x7ff) << 1;
5269 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
5270 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5271 "Branch out of range");
5272 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
5274 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5277 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
5282 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
5283 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
5284 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
5285 if (diff
& 0x400000)
5288 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
5289 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5290 "Branch with link out of range");
5292 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
5293 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
5294 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5295 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
5300 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
5301 md_number_to_chars (buf
, value
, 1);
5305 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
5306 md_number_to_chars (buf
, value
, 2);
5311 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
5312 md_number_to_chars (buf
, value
, 4);
5315 case BFD_RELOC_ARM_CP_OFF_IMM
:
5317 if (value
< -1023 || value
> 1023 || (value
& 3))
5318 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5319 "Illegal value for co-processor offset");
5322 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
5323 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
5324 md_number_to_chars (buf
, newval
, INSN_SIZE
);
5327 case BFD_RELOC_ARM_THUMB_OFFSET
:
5328 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
5329 /* Exactly what ranges, and where the offset is inserted depends on
5330 the type of instruction, we can establish this from the top 4 bits */
5331 switch (newval
>> 12)
5333 case 4: /* PC load */
5334 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
5335 forced to zero for these loads, so we will need to round
5336 up the offset if the instruction address is not word
5337 aligned (since the final address produced must be, and
5338 we can only describe word-aligned immediate offsets). */
5340 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
5341 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5342 "Invalid offset, target not word aligned (0x%08X)",
5343 (unsigned int)(fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
));
5345 if ((value
+ 2) & ~0x3fe)
5346 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5349 /* Round up, since pc will be rounded down. */
5350 newval
|= (value
+ 2) >> 2;
5353 case 9: /* SP load/store */
5355 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5357 newval
|= value
>> 2;
5360 case 6: /* Word load/store */
5362 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5364 newval
|= value
<< 4; /* 6 - 2 */
5367 case 7: /* Byte load/store */
5369 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5371 newval
|= value
<< 6;
5374 case 8: /* Halfword load/store */
5376 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5378 newval
|= value
<< 5; /* 6 - 1 */
5382 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5383 "Unable to process relocation for thumb opcode: %x", newval
);
5386 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5389 case BFD_RELOC_ARM_THUMB_ADD
:
5390 /* This is a complicated relocation, since we use it for all of
5391 the following immediate relocations:
5394 9bit ADD/SUB SP word-aligned
5395 10bit ADD PC/SP word-aligned
5397 The type of instruction being processed is encoded in the
5403 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
5405 int rd
= (newval
>> 4) & 0xf;
5406 int rs
= newval
& 0xf;
5407 int subtract
= newval
& 0x8000;
5412 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5413 "Invalid immediate for stack address calculation");
5414 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
5415 newval
|= value
>> 2;
5417 else if (rs
== REG_PC
|| rs
== REG_SP
)
5421 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5422 "Invalid immediate for address calculation (value = 0x%08X)", value
);
5423 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
5425 newval
|= value
>> 2;
5430 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5431 "Invalid 8bit immediate");
5432 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
5433 newval
|= (rd
<< 8) | value
;
5438 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5439 "Invalid 3bit immediate");
5440 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
5441 newval
|= rd
| (rs
<< 3) | (value
<< 6);
5444 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5447 case BFD_RELOC_ARM_THUMB_IMM
:
5448 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
5449 switch (newval
>> 11)
5451 case 0x04: /* 8bit immediate MOV */
5452 case 0x05: /* 8bit immediate CMP */
5453 if (value
< 0 || value
> 255)
5454 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5455 "Invalid immediate: %d is too large", value
);
5462 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5465 case BFD_RELOC_ARM_THUMB_SHIFT
:
5466 /* 5bit shift value (0..31) */
5467 if (value
< 0 || value
> 31)
5468 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5469 "Illegal Thumb shift value: %d", value
);
5470 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
5471 newval
|= value
<< 6;
5472 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
5475 case BFD_RELOC_NONE
:
5477 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5478 "Bad relocation fixup type (%d)\n", fixP
->fx_r_type
);
5484 /* Translate internal representation of relocation info to BFD target
5487 tc_gen_reloc (section
, fixp
)
5492 bfd_reloc_code_real_type code
;
5494 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
5496 reloc
->sym_ptr_ptr
= &fixp
->fx_addsy
->bsym
;
5497 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
5499 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
5500 if (fixp
->fx_pcrel
== 0)
5501 reloc
->addend
= fixp
->fx_offset
;
5503 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
5505 switch (fixp
->fx_r_type
)
5510 code
= BFD_RELOC_8_PCREL
;
5517 code
= BFD_RELOC_16_PCREL
;
5524 code
= BFD_RELOC_32_PCREL
;
5528 case BFD_RELOC_ARM_PCREL_BRANCH
:
5530 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
5531 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
5532 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
5533 code
= fixp
->fx_r_type
;
5536 case BFD_RELOC_ARM_LITERAL
:
5537 case BFD_RELOC_ARM_HWLITERAL
:
5538 /* If this is called then the a literal has been referenced across
5539 a section boundry - possibly due to an implicit dump */
5540 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
5541 "Literal referenced across section boundry (Implicit dump?)");
5547 switch (fixp
->fx_r_type
)
5549 case BFD_RELOC_ARM_IMMEDIATE
: type
= "IMMEDIATE"; break;
5550 case BFD_RELOC_ARM_OFFSET_IMM
: type
= "OFFSET_IMM"; break;
5551 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
5552 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
5553 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
5554 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
5555 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
5556 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
5557 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
5558 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
5559 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
5560 default: type
= "<unknown>"; break;
5562 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
5563 "Can not represent %s relocation in this object file format (%d)",
5564 type
, fixp
->fx_pcrel
);
5569 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
5571 if (reloc
->howto
== NULL
)
5573 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
5574 "Can not represent %s relocation in this object file format",
5575 bfd_get_reloc_code_name (code
));
5582 CONST
int md_short_jump_size
= 4;
5583 CONST
int md_long_jump_size
= 4;
5585 /* These should never be called on the arm */
5587 md_create_long_jump (ptr
, from_addr
, to_addr
, frag
, to_symbol
)
5589 addressT from_addr
, to_addr
;
5593 as_fatal ("md_create_long_jump\n");
5597 md_create_short_jump (ptr
, from_addr
, to_addr
, frag
, to_symbol
)
5599 addressT from_addr
, to_addr
;
5603 as_fatal ("md_create_short_jump\n");
5607 md_estimate_size_before_relax (fragP
, segtype
)
5611 as_fatal ("md_estimate_size_before_relax\n");
5623 as_bad (inst
.error
);
5627 to
= frag_more (inst
.size
);
5628 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
5630 assert (inst
.size
== (2 * THUMB_SIZE
));
5631 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
5632 md_number_to_chars (to
+ 2, inst
.instruction
, THUMB_SIZE
);
5635 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
5637 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
5638 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
5639 inst
.size
, &inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
5650 char *p
, *q
, *start
;
5652 /* Align the instruction */
5653 /* this may not be the right thing to do but ... */
5654 /* arm_align (2, 0); */
5655 listing_prev_line (); /* Defined in listing.h */
5657 /* Align the previous label if needed */
5658 if (last_label_seen
!= NULL
)
5660 last_label_seen
->sy_frag
= frag_now
;
5661 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
5662 S_SET_SEGMENT (last_label_seen
, now_seg
);
5665 memset (&inst
, '\0', sizeof (inst
));
5666 inst
.reloc
.type
= BFD_RELOC_NONE
;
5669 str
++; /* Skip leading white space */
5671 /* scan up to the end of the op-code, which must end in white space or
5673 for (start
= p
= str
; *p
!= '\0'; p
++)
5679 as_bad ("No operator -- statement `%s'\n", str
);
5685 CONST
struct thumb_opcode
*opcode
;
5689 opcode
= (CONST
struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
5693 inst
.instruction
= opcode
->value
;
5694 inst
.size
= opcode
->size
;
5695 (*opcode
->parms
)(p
);
5696 output_inst (start
);
5702 CONST
struct asm_opcode
*opcode
;
5704 inst
.size
= INSN_SIZE
;
5705 /* p now points to the end of the opcode, probably white space, but we
5706 have to break the opcode up in case it contains condionals and flags;
5707 keep trying with progressively smaller basic instructions until one
5708 matches, or we run out of opcode. */
5709 q
= (p
- str
> LONGEST_INST
) ? str
+ LONGEST_INST
: p
;
5710 for (; q
!= str
; q
--)
5714 opcode
= (CONST
struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
5716 if (opcode
&& opcode
->template)
5718 unsigned long flag_bits
= 0;
5721 /* Check that this instruction is supported for this CPU */
5722 if ((opcode
->variants
& cpu_variant
) == 0)
5725 inst
.instruction
= opcode
->value
;
5726 if (q
== p
) /* Just a simple opcode */
5728 if (opcode
->comp_suffix
!= 0)
5729 as_bad ("Opcode `%s' must have suffix from <%s>\n", str
,
5730 opcode
->comp_suffix
);
5733 inst
.instruction
|= COND_ALWAYS
;
5734 (*opcode
->parms
)(q
, 0);
5736 output_inst (start
);
5740 /* Now check for a conditional */
5744 CONST
struct asm_cond
*cond
;
5748 cond
= (CONST
struct asm_cond
*) hash_find (arm_cond_hsh
, r
);
5752 if (cond
->value
== 0xf0000000)
5754 "Warning: Use of the 'nv' conditional is deprecated\n");
5756 inst
.instruction
|= cond
->value
;
5760 inst
.instruction
|= COND_ALWAYS
;
5763 inst
.instruction
|= COND_ALWAYS
;
5765 /* if there is a compulsory suffix, it should come here, before
5766 any optional flags. */
5767 if (opcode
->comp_suffix
)
5769 CONST
char *s
= opcode
->comp_suffix
;
5781 as_bad ("Opcode `%s' must have suffix from <%s>\n", str
,
5782 opcode
->comp_suffix
);
5789 /* The remainder, if any should now be flags for the instruction;
5790 Scan these checking each one found with the opcode. */
5794 CONST
struct asm_flg
*flag
= opcode
->flags
;
5803 for (flagno
= 0; flag
[flagno
].template; flagno
++)
5805 if (! strcmp (r
, flag
[flagno
].template))
5807 flag_bits
|= flag
[flagno
].set_bits
;
5813 if (! flag
[flagno
].template)
5820 (*opcode
->parms
) (p
, flag_bits
);
5821 output_inst (start
);
5830 /* It wasn't an instruction, but it might be a register alias of the form
5840 if (*q
&& !strncmp (q
, ".req ", 4))
5843 char * copy_of_str
= str
;
5850 for (r
= q
; *r
!= '\0'; r
++)
5860 regnum
= arm_reg_parse (& q
);
5863 reg
= arm_reg_parse (& str
);
5869 insert_reg_alias (str
, regnum
);
5873 as_warn ("register '%s' does not exist\n", q
);
5876 else if (regnum
!= FAIL
)
5879 as_warn ("ignoring redefinition of register alias '%s'", copy_of_str
);
5881 /* Do not warn abpout redefinitions to the same alias. */
5884 as_warn ("ignoring redefinition of register alias '%s' to non-existant register '%s'",
5888 as_warn ("ignoring incomplete .req pseuso op");
5895 as_bad ("bad instruction `%s'", start
);
5900 * Invocation line includes a switch not recognized by the base assembler.
5901 * See if it's a processor-specific option. These are:
5902 * Cpu variants, the arm part is optional:
5903 * -m[arm]1 Currently not supported.
5904 * -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
5905 * -m[arm]3 Arm 3 processor
5906 * -m[arm]6, Arm 6 processors
5907 * -m[arm]7[t][[d]m] Arm 7 processors
5908 * -mall All (except the ARM1)
5910 * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
5911 * -mfpe-old (No float load/store multiples)
5912 * -mno-fpu Disable all floating point instructions
5913 * Run-time endian selection:
5914 * -EB big endian cpu
5915 * -EL little endian cpu
5916 * ARM Procedure Calling Standard:
5917 * -mapcs-32 32 bit APCS
5918 * -mapcs-26 26 bit APCS
5919 * -mapcs-float Pass floats in float regs
5920 * -mapcs-reentrant Position independent code
5921 * -mthumb-interwork Code supports Arm/Thumb interworking
5924 CONST
char *md_shortopts
= "m:";
5925 struct option md_longopts
[] =
5927 #ifdef ARM_BI_ENDIAN
5928 #define OPTION_EB (OPTION_MD_BASE + 0)
5929 {"EB", no_argument
, NULL
, OPTION_EB
},
5930 #define OPTION_EL (OPTION_MD_BASE + 1)
5931 {"EL", no_argument
, NULL
, OPTION_EL
},
5933 {NULL
, no_argument
, NULL
, 0}
5935 size_t md_longopts_size
= sizeof (md_longopts
);
5938 md_parse_option (c
, arg
)
5946 #ifdef ARM_BI_ENDIAN
5948 target_big_endian
= 1;
5951 target_big_endian
= 0;
5959 if (! strcmp (str
, "fpa10"))
5960 cpu_variant
= (cpu_variant
& ~FPU_ALL
) | FPU_FPA10
;
5961 else if (! strcmp (str
, "fpa11"))
5962 cpu_variant
= (cpu_variant
& ~FPU_ALL
) | FPU_FPA11
;
5963 else if (! strcmp (str
, "fpe-old"))
5964 cpu_variant
= (cpu_variant
& ~FPU_ALL
) | FPU_CORE
;
5970 if (! strcmp (str
, "no-fpu"))
5971 cpu_variant
&= ~FPU_ALL
;
5975 /* Limit assembler to generating only Thumb instructions: */
5976 if (! strcmp (str
, "thumb"))
5978 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_THUMB
;
5979 cpu_variant
= (cpu_variant
& ~FPU_ALL
) | FPU_NONE
;
5982 else if (! strcmp (str
, "thumb-interwork"))
5984 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_THUMB
| ARM_ARCHv4
;
5986 support_interwork
= true;
5994 if (! strcmp (str
, "all"))
5996 cpu_variant
= ARM_ALL
| FPU_ALL
;
6000 if (! strncmp (str
, "apcs-", 5))
6002 /* GCC passes on all command line options starting "-mapcs-..."
6003 to us, so we must parse them here. */
6007 if (! strcmp (str
, "32"))
6009 uses_apcs_26
= false;
6012 else if (! strcmp (str
, "26"))
6014 uses_apcs_26
= true;
6017 else if (! strcmp (str
, "frame"))
6019 /* Stack frames are being generated - does not affect
6023 else if (! strcmp (str
, "stack-check"))
6025 /* Stack checking is being performed - does not affect
6026 linkage, but does require that the functions
6027 __rt_stkovf_split_small and __rt_stkovf_split_big be
6028 present in the final link. */
6032 else if (! strcmp (str
, "float"))
6034 /* Floating point arguments are being passed in the floating
6035 point registers. This does affect linking, since this
6036 version of the APCS is incompatible with the version that
6037 passes floating points in the integer registers. */
6039 uses_apcs_float
= true;
6042 else if (! strcmp (str
, "reentrant"))
6044 /* Reentrant code has been generated. This does affect
6045 linking, since there is no point in linking reentrant/
6046 position independent code with absolute position code. */
6051 as_bad ("Unrecognised APCS switch -m%s", arg
);
6055 /* Strip off optional "arm" */
6056 if (! strncmp (str
, "arm", 3))
6062 if (! strcmp (str
, "1"))
6063 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_1
;
6069 if (! strcmp (str
, "2"))
6070 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_2
;
6071 else if (! strcmp (str
, "250"))
6072 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_250
;
6078 if (! strcmp (str
, "3"))
6079 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_3
;
6085 if (! strcmp (str
, "strongarm") || ! strcmp (str
, "strongarm110"))
6086 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
| ARM_ARCHv4
| ARM_LONGMUL
;
6092 if (! strcmp (str
, "8"))
6093 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
| ARM_ARCHv4
| ARM_LONGMUL
;
6099 if (! strcmp (str
, "6"))
6100 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_6
;
6106 str
++; /* eat the '7' */
6107 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
;
6113 cpu_variant
|= (ARM_THUMB
| ARM_ARCHv4
);
6117 cpu_variant
|= ARM_LONGMUL
;
6120 case 'f': /* fe => fp enabled cpu. */
6126 case 'c': /* Unknown */
6127 case 'd': /* debug */
6128 case 'i': /* embedded ice */
6129 /* Included for completeness in ARM processor naming. */
6139 /* Select variant based on architecture rather than processor */
6145 case 'a': cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_3
; break;
6146 case 0: cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_2
; break;
6147 default: as_bad ("Invalid architecture variant -m%s", arg
); break;
6152 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_7
;
6156 case 'm': cpu_variant
|= ARM_LONGMUL
; break;
6158 default: as_bad ("Invalid architecture variant -m%s", arg
); break;
6163 cpu_variant
= (cpu_variant
& ~ARM_ANY
) | ARM_ARCHv4
;
6167 case 't': cpu_variant
|= ARM_THUMB
; break;
6169 default: as_bad ("Invalid architecture variant -m%s", arg
); break;
6174 as_bad ("Invalid architecture variant -m%s", arg
);
6181 as_bad ("Invalid processor variant -m%s", arg
);
6199 "-m[arm][<processor name>] select processor variant\n\
6200 -m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n\
6201 -mthumb\t\t\tonly allow Thumb instructions\n\
6202 -mthumb-interwork\tmark the assembled code as supporting interworking\n\
6203 -mall\t\t\tallow any instruction\n\
6204 -mfpa10, -mfpa11\tselect floating point architecture\n\
6205 -mfpe-old\t\tdon't allow floating-point multiple instructions\n\
6206 -mno-fpu\t\tdon't allow any floating-point instructions.\n");
6209 "-mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n");
6211 "-mapcs-float\t\tfloating point args are passed in floating point regs\n");
6213 "-mapcs-reentrant\tposition independent/reentrant code has been generated\n");
6215 #ifdef ARM_BI_ENDIAN
6217 "-EB\t\t\tassemble code for a big endian cpu\n\
6218 -EL\t\t\tassemble code for a little endian cpu\n");
6222 /* We need to be able to fix up arbitrary expressions in some statements.
6223 This is so that we can handle symbols that are an arbitrary distance from
6224 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
6225 which returns part of an address in a form which will be valid for
6226 a data instruction. We do this by pushing the expression into a symbol
6227 in the expr_section, and creating a fix for that. */
6230 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
6239 arm_fix_data
*arm_data
;
6247 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
6251 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
6256 /* Mark whether the fix is to a THUMB instruction, or an ARM instruction */
6257 arm_data
= (arm_fix_data
*) obstack_alloc (¬es
, sizeof (arm_fix_data
));
6258 new_fix
->tc_fix_data
= (PTR
) arm_data
;
6259 arm_data
->thumb_mode
= thumb_mode
;
6264 /* A good place to do this, although this was probably not intended
6265 * for this kind of use. We need to dump the literal pool before
6266 * references are made to a null symbol pointer. */
6270 if (current_poolP
!= NULL
)
6272 subseg_set (text_section
, 0); /* Put it at the end of text section */
6274 listing_prev_line ();
6279 arm_start_line_hook ()
6281 last_label_seen
= NULL
;
6285 arm_frob_label (sym
)
6288 last_label_seen
= sym
;
6289 ARM_SET_THUMB (sym
, thumb_mode
);
6291 ARM_SET_INTERWORK (sym
, support_interwork
);
6294 if (label_is_thumb_function_name
)
6296 /* When the address of a Thumb function is taken the bottom
6297 bit of that address should be set. This will allow
6298 interworking between Arm and Thumb functions to work
6301 THUMB_SET_FUNC (sym
, 1);
6303 label_is_thumb_function_name
= false;
6307 /* Adjust the symbol table. This marks Thumb symbols as distinct from
6311 arm_adjust_symtab ()
6316 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
6318 if (ARM_IS_THUMB (sym
))
6320 if (THUMB_IS_FUNC (sym
))
6322 /* Mark the symbol as a Thumb function. */
6323 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
6324 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
6325 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
6326 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
6327 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
6329 as_bad ("%s: unexpected function type: %d", S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
6331 else switch (S_GET_STORAGE_CLASS (sym
))
6334 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
6337 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
6340 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
6342 default: /* do nothing */
6347 if (ARM_IS_INTERWORK (sym
))
6349 coffsymbol(sym
->bsym
)->native
->u
.syment
.n_flags
= 0xFF;
6358 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
6360 *input_line_pointer
= '/';
6361 input_line_pointer
+= 5;
6362 *input_line_pointer
= 0;
6369 arm_canonicalize_symbol_name (name
)
6374 if (thumb_mode
&& (len
= strlen (name
)) > 5
6375 && ! strcmp (name
+ len
- 5, "/data"))
6377 *(name
+ len
- 5) = 0;
6384 arm_validate_fix (fixP
)
6387 /* If the destination of the branch is a defined symbol which does not have
6388 the THUMB_FUNC attribute, then we must be calling a function which has
6389 the (interfacearm) attribute. We look for the Thumb entry point to that
6390 function and change the branch to refer to that function instead. */
6391 if ( fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
6392 && fixP
->fx_addsy
!= NULL
6393 && S_IS_DEFINED (fixP
->fx_addsy
)
6394 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
6396 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);