1  /* This file is tc-arm.h
       2     Copyright (C) 1994-2023 Free Software Foundation, Inc.
       3     Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
       4  	Modified by David Taylor (dtaylor@armltd.co.uk)
       5  
       6     This file is part of GAS, the GNU Assembler.
       7  
       8     GAS is free software; you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation; either version 3, or (at your option)
      11     any later version.
      12  
      13     GAS is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with GAS; see the file COPYING.  If not, write to the Free
      20     Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
      21     02110-1301, USA.  */
      22  
      23  #define TC_ARM 1
      24  
      25  #ifndef TARGET_BYTES_BIG_ENDIAN
      26  #define TARGET_BYTES_BIG_ENDIAN 0
      27  #endif
      28  
      29  #define WORKING_DOT_WORD
      30  
      31  #define TARGET_ARCH 	bfd_arch_arm
      32  
      33  #define DIFF_EXPR_OK
      34  
      35  #ifdef  LITTLE_ENDIAN
      36  #undef  LITTLE_ENDIAN
      37  #endif
      38  
      39  #ifdef  BIG_ENDIAN
      40  #undef  BIG_ENDIAN
      41  #endif
      42  
      43  #define LITTLE_ENDIAN 	1234
      44  #define BIG_ENDIAN 	4321
      45  
      46  struct fix;
      47  
      48  #if defined OBJ_COFF
      49  # define ARM_BI_ENDIAN
      50  # if defined TE_PE
      51  #  if defined TE_WINCE
      52  #   define TARGET_FORMAT (target_big_endian ? "pe-arm-wince-big" : "pe-arm-wince-little")
      53  #  else
      54  #   define TARGET_FORMAT (target_big_endian ? "pe-arm-big" : "pe-arm-little")
      55  #  endif
      56  # else
      57  #  define TARGET_FORMAT (target_big_endian ? "coff-arm-big" : "coff-arm-little")
      58  # endif
      59  #elif defined OBJ_ELF
      60  # define ARM_BI_ENDIAN
      61  # define TARGET_FORMAT	elf32_arm_target_format ()
      62  #endif
      63  
      64  /* We support double slash line-comments for compatibility with the ARM AArch64 Assembler.  */
      65  #define DOUBLESLASH_LINE_COMMENTS
      66  
      67  /* We conditionally support labels without a colon.  */
      68  #define LABELS_WITHOUT_COLONS codecomposer_syntax
      69  extern bool codecomposer_syntax;
      70  
      71  #define tc_symbol_chars arm_symbol_chars
      72  extern const char arm_symbol_chars[];
      73  
      74  #define TC_FORCE_RELOCATION(FIX) arm_force_relocation (FIX)
      75  
      76  extern unsigned int arm_frag_max_var (struct frag *);
      77  #define md_frag_max_var arm_frag_max_var
      78  
      79  #define md_relax_frag(segment, fragp, stretch) \
      80    arm_relax_frag (segment, fragp, stretch)
      81  extern int arm_relax_frag (asection *, struct frag *, long);
      82  
      83  #define md_optimize_expr(l,o,r)		arm_optimize_expr (l, o, r)
      84  extern bool arm_optimize_expr (expressionS *, operatorT, expressionS *);
      85  
      86  #define md_cleanup() arm_cleanup ()
      87  
      88  #define md_start_line_hook() arm_start_line_hook ()
      89  
      90  #define TC_START_LABEL_WITHOUT_COLON(NUL_CHAR, NEXT_CHAR) \
      91    tc_start_label_without_colon ()
      92  extern bool tc_start_label_without_colon (void);
      93  
      94  #define tc_frob_label(S) arm_frob_label (S)
      95  
      96  /* We also need to mark assembler created symbols:  */
      97  #define tc_frob_fake_label(S) arm_frob_label (S)
      98  
      99  #ifdef OBJ_ELF
     100  #define md_finish arm_md_finish
     101  extern void arm_md_finish (void);
     102  bool arm_is_eabi (void);
     103  
     104  #define md_post_relax_hook		arm_md_post_relax ()
     105  extern void arm_md_post_relax (void);
     106  #endif
     107  
     108  /* NOTE: The fake label creation in stabs.c:s_stab_generic() has
     109     deliberately not been updated to mark assembler created stabs
     110     symbols as Thumb.  */
     111  
     112  #define TC_FIX_TYPE int
     113  #define TC_INIT_FIX_DATA(FIX) ((FIX)->tc_fix_data = 0)
     114  
     115  /* We need to keep some local information on symbols.  */
     116  
     117  #define TC_SYMFIELD_TYPE 	unsigned int
     118  #define ARM_GET_FLAG(s)   	(*symbol_get_tc (s))
     119  #define ARM_SET_FLAG(s,v) 	(*symbol_get_tc (s) |= (v))
     120  #define ARM_RESET_FLAG(s,v) 	(*symbol_get_tc (s) &= ~(v))
     121  
     122  #define ARM_FLAG_THUMB 		(1 << 0)	/* The symbol is a Thumb symbol rather than an Arm symbol.  */
     123  #define ARM_FLAG_INTERWORK 	(1 << 1)	/* The symbol is attached to code that supports interworking.  */
     124  #define THUMB_FLAG_FUNC		(1 << 2)	/* The symbol is attached to the start of a Thumb function.  */
     125  
     126  #define ARM_IS_THUMB(s)		(ARM_GET_FLAG (s) & ARM_FLAG_THUMB)
     127  #define ARM_IS_INTERWORK(s)	(ARM_GET_FLAG (s) & ARM_FLAG_INTERWORK)
     128  
     129  #ifdef OBJ_ELF
     130  
     131  /* For ELF objects THUMB_IS_FUNC is inferred from
     132     ARM_IS_THUMB and the function type.  */
     133  #define THUMB_IS_FUNC(s)					\
     134    ((s) != NULL							\
     135     && ((arm_is_eabi ()						\
     136  	&& (ARM_IS_THUMB (s))					\
     137  	&& (symbol_get_bfdsym (s)->flags & BSF_FUNCTION))	\
     138         || (ARM_GET_FLAG (s) & THUMB_FLAG_FUNC)))
     139  
     140  #define ARM_IS_FUNC(s)					\
     141    (((s) != NULL						\
     142      && arm_is_eabi ()					\
     143      && !(ARM_IS_THUMB (s))				\
     144      /* && !(THUMB_FLAG_FUNC & ARM_GET_FLAG (s)) \ */	\
     145      && (symbol_get_bfdsym (s)->flags & BSF_FUNCTION)))
     146  
     147  
     148  #else
     149  
     150  #define THUMB_IS_FUNC(s)	((s) && ARM_GET_FLAG (s) & THUMB_FLAG_FUNC)
     151  #define ARM_IS_FUNC(s)          (!THUMB_IS_FUNC (s) \
     152  				 && (s) && (symbol_get_bfdsym (s)->flags & BSF_FUNCTION))
     153  #endif
     154  
     155  #define ARM_SET_THUMB(s,t)      ((t) ? ARM_SET_FLAG (s, ARM_FLAG_THUMB)     : ARM_RESET_FLAG (s, ARM_FLAG_THUMB))
     156  #define ARM_SET_INTERWORK(s,t)  ((t) ? ARM_SET_FLAG (s, ARM_FLAG_INTERWORK) : ARM_RESET_FLAG (s, ARM_FLAG_INTERWORK))
     157  #define THUMB_SET_FUNC(s,t)     ((t) ? ARM_SET_FLAG (s, THUMB_FLAG_FUNC)    : ARM_RESET_FLAG (s, THUMB_FLAG_FUNC))
     158  
     159  void arm_copy_symbol_attributes (symbolS *, symbolS *);
     160  
     161  #ifndef TC_COPY_SYMBOL_ATTRIBUTES
     162  #define TC_COPY_SYMBOL_ATTRIBUTES(DEST, SRC) \
     163    (arm_copy_symbol_attributes (DEST, SRC))
     164  #endif
     165  
     166  #define TC_START_LABEL(STR, NUL_CHAR, NEXT_CHAR)			\
     167    (NEXT_CHAR == ':' || (NEXT_CHAR == '/' && arm_data_in_code ()))
     168  #define tc_canonicalize_symbol_name(str) arm_canonicalize_symbol_name (str);
     169  #define obj_adjust_symtab() 		 arm_adjust_symtab ()
     170  
     171  #define LISTING_HEADER "ARM GAS "
     172  
     173  #define OPTIONAL_REGISTER_PREFIX '%'
     174  
     175  #define LOCAL_LABEL(name)  (name[0] == '.' && name[1] == 'L')
     176  #define LOCAL_LABELS_FB    1
     177  
     178  /* This expression evaluates to true if the relocation is for a local
     179     object for which we still want to do the relocation at runtime.
     180     False if we are willing to perform this relocation while building
     181     the .o file.  GOTOFF does not need to be checked here because it is
     182     not pcrel.  I am not sure if some of the others are ever used with
     183     pcrel, but it is easier to be safe than sorry.  */
     184  
     185  #define TC_FORCE_RELOCATION_LOCAL(FIX)			\
     186    (GENERIC_FORCE_RELOCATION_LOCAL (FIX)			\
     187     || (FIX)->fx_r_type == BFD_RELOC_ARM_GOT32		\
     188     || (FIX)->fx_r_type == BFD_RELOC_32			\
     189     || ((FIX)->fx_addsy != NULL				\
     190         && S_IS_WEAK ((FIX)->fx_addsy)))
     191  
     192  /* Force output of R_ARM_REL32 relocations against thumb function symbols.
     193     This is needed to ensure the low bit is handled correctly.  */
     194  #define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG)	\
     195    (GENERIC_FORCE_RELOCATION_SUB_SAME (FIX, SEG)	\
     196     || THUMB_IS_FUNC ((FIX)->fx_addsy))
     197  
     198  #define TC_FORCE_RELOCATION_ABS(FIX)			\
     199    (((FIX)->fx_pcrel					\
     200      && (FIX)->fx_r_type != BFD_RELOC_32			\
     201      && (FIX)->fx_r_type != BFD_RELOC_ARM_GOT32)		\
     202     || TC_FORCE_RELOCATION(FIX))
     203  
     204  #define TC_CONS_FIX_NEW cons_fix_new_arm
     205  
     206  #define MAX_MEM_ALIGNMENT_BYTES    6
     207  #define MAX_MEM_FOR_RS_ALIGN_CODE ((1 << MAX_MEM_ALIGNMENT_BYTES) - 1)
     208  
     209  /* For frags in code sections we need to record whether they contain
     210     ARM code or THUMB code.  This is that if they have to be aligned,
     211     they can contain the correct type of no-op instruction.  */
     212  struct arm_frag_type
     213  {
     214    int thumb_mode;
     215  #ifdef OBJ_ELF
     216    /* If there is a mapping symbol at offset 0 in this frag,
     217       it will be saved in FIRST_MAP.  If there are any mapping
     218       symbols in this frag, the last one will be saved in
     219       LAST_MAP.  */
     220    symbolS *first_map, *last_map;
     221  #endif
     222  };
     223  
     224  static inline int
     225  arm_min (int am_p1, int am_p2)
     226  {
     227    return am_p1 < am_p2 ? am_p1 : am_p2;
     228  }
     229  
     230  #define TC_FRAG_TYPE		struct arm_frag_type
     231  #define TC_FRAG_INIT(fragp, max_bytes) arm_init_frag (fragp, max_bytes)
     232  #define TC_ALIGN_ZERO_IS_DEFAULT 1
     233  #define HANDLE_ALIGN(fragp)	arm_handle_align (fragp)
     234  /* PR gas/19276: COFF/PE segment alignment is already handled in coff_frob_section().  */
     235  #ifndef TE_PE
     236  #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN)				\
     237    ((!(FRCHAIN)->frch_next && subseg_text_p (SEG))		\
     238     ? arm_min (2, get_recorded_alignment (SEG)) : 0)
     239  #endif
     240  
     241  #define md_do_align(N, FILL, LEN, MAX, LABEL)					\
     242    if (FILL == NULL && (N) != 0 && ! need_pass_2 && subseg_text_p (now_seg))	\
     243      {										\
     244        arm_frag_align_code (N, MAX);						\
     245        goto LABEL;								\
     246      }
     247  
     248  #define DWARF2_LINE_MIN_INSN_LENGTH 	2
     249  
     250  /* The lr register is r14.  */
     251  #define DWARF2_DEFAULT_RETURN_COLUMN  14
     252  
     253  /* Registers are generally saved at negative offsets to the CFA.  */
     254  #define DWARF2_CIE_DATA_ALIGNMENT     (-4)
     255  
     256  /* State variables for predication block handling.  */
     257  enum pred_state
     258  {
     259    OUTSIDE_PRED_BLOCK, MANUAL_PRED_BLOCK, AUTOMATIC_PRED_BLOCK
     260  };
     261  enum pred_type {
     262    SCALAR_PRED, VECTOR_PRED
     263  };
     264  struct current_pred
     265  {
     266    int mask;
     267    enum pred_state state;
     268    int cc;
     269    int block_length;
     270    char *insn;
     271    int state_handled;
     272    int warn_deprecated;
     273    int insn_cond;
     274    enum pred_type type;
     275  };
     276  
     277  #ifdef OBJ_ELF
     278  # define obj_frob_symbol(sym, punt)	armelf_frob_symbol ((sym), & (punt))
     279  # define md_elf_section_change_hook()	arm_elf_change_section ()
     280  # define md_elf_section_type(str, len)	arm_elf_section_type (str, len)
     281  # define GLOBAL_OFFSET_TABLE_NAME	"_GLOBAL_OFFSET_TABLE_"
     282  # define TC_SEGMENT_INFO_TYPE 		struct arm_segment_info_type
     283  
     284  /* This is not really an alignment operation, but it's something we
     285     need to do at the same time: whenever we are figuring out the
     286     alignment for data, we should check whether a $d symbol is
     287     necessary.  */
     288  # define md_cons_align(nbytes)		mapping_state (MAP_DATA)
     289  
     290  enum mstate
     291  {
     292    MAP_UNDEFINED = 0, /* Must be zero, for seginfo in new sections.  */
     293    MAP_DATA,
     294    MAP_ARM,
     295    MAP_THUMB
     296  };
     297  
     298  void mapping_state (enum mstate);
     299  
     300  struct arm_segment_info_type
     301  {
     302    enum mstate mapstate;
     303  
     304    /* Bit N indicates that an R_ARM_NONE relocation has been output for
     305       __aeabi_unwind_cpp_prN already if set. This enables dependencies to be
     306       emitted only once per section, to save unnecessary bloat.  */
     307    unsigned int marked_pr_dependency;
     308  
     309    struct current_pred current_pred;
     310  };
     311  
     312  /* We want .cfi_* pseudo-ops for generating unwind info.  */
     313  #define TARGET_USE_CFIPOP              1
     314  
     315  /* CFI hooks.  */
     316  #define tc_regname_to_dw2regnum            tc_arm_regname_to_dw2regnum
     317  #define tc_cfi_frame_initial_instructions  tc_arm_frame_initial_instructions
     318  
     319  #else /* Not OBJ_ELF.  */
     320  #define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
     321  #endif
     322  
     323  #if defined OBJ_ELF || defined OBJ_COFF
     324  
     325  # define EXTERN_FORCE_RELOC 			1
     326  # define tc_fix_adjustable(FIX) 		arm_fix_adjustable (FIX)
     327  #endif
     328  
     329  #ifdef OBJ_ELF
     330  /* Values passed to md_apply_fix don't include the symbol value.  */
     331  # define MD_APPLY_SYM_VALUE(FIX) 		arm_apply_sym_value (FIX, this_segment)
     332  #endif
     333  
     334  #ifdef OBJ_COFF
     335  # define TC_VALIDATE_FIX(FIX, SEGTYPE, LABEL)	arm_validate_fix (FIX)
     336  /* Values passed to md_apply_fix don't include the symbol value.  */
     337  # define MD_APPLY_SYM_VALUE(FIX) 		0
     338  #endif
     339  
     340  #define MD_PCREL_FROM_SECTION(F,S) md_pcrel_from_section(F,S)
     341  
     342  extern void arm_frag_align_code (int, int);
     343  extern void arm_validate_fix (struct fix *);
     344  extern const char * elf32_arm_target_format (void);
     345  extern void arm_elf_change_section (void);
     346  extern int arm_force_relocation (struct fix *);
     347  extern void arm_cleanup (void);
     348  extern void arm_start_line_hook (void);
     349  extern void arm_frob_label (symbolS *);
     350  extern bool arm_data_in_code (void);
     351  extern char * arm_canonicalize_symbol_name (char *);
     352  extern void arm_adjust_symtab (void);
     353  extern void armelf_frob_symbol (symbolS *, int *);
     354  extern void cons_fix_new_arm (fragS *, int, int, expressionS *,
     355  			      bfd_reloc_code_real_type);
     356  extern void arm_init_frag (struct frag *, int);
     357  extern void arm_handle_align (struct frag *);
     358  extern bool arm_fix_adjustable (struct fix *);
     359  extern int arm_elf_section_type (const char *, size_t);
     360  extern int tc_arm_regname_to_dw2regnum (char *regname);
     361  extern void tc_arm_frame_initial_instructions (void);
     362  
     363  #ifdef TE_PE
     364  
     365  #define O_secrel O_md1
     366  
     367  #define TC_DWARF2_EMIT_OFFSET  tc_pe_dwarf2_emit_offset
     368  void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int);
     369  
     370  #endif /* TE_PE */
     371  
     372  #ifdef OBJ_ELF
     373  #define CONVERT_SYMBOLIC_ATTRIBUTE(name) arm_convert_symbolic_attribute (name)
     374  extern int arm_convert_symbolic_attribute (const char *);
     375  extern int arm_apply_sym_value (struct fix *, segT);
     376  #endif
     377  
     378  #define tc_comment_chars arm_comment_chars
     379  extern char arm_comment_chars[];
     380  
     381  #define tc_line_separator_chars arm_line_separator_chars
     382  extern char arm_line_separator_chars[];
     383  
     384  #define TC_EQUAL_IN_INSN(c, s) arm_tc_equal_in_insn ((c), (s))
     385  extern bool arm_tc_equal_in_insn (int, char *);
     386  
     387  #define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) \
     388  	arm_is_largest_exponent_ok ((PRECISION))
     389  int arm_is_largest_exponent_ok (int precision);