1  /* tc-ppc.h -- Header file for tc-ppc.c.
       2     Copyright (C) 1994-2023 Free Software Foundation, Inc.
       3     Written by Ian Lance Taylor, Cygnus Support.
       4  
       5     This file is part of GAS, the GNU Assembler.
       6  
       7     GAS is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 3, or (at your option)
      10     any later version.
      11  
      12     GAS is distributed in the hope that it will be useful,
      13     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15     GNU General Public License for more details.
      16  
      17     You should have received a copy of the GNU General Public License
      18     along with GAS; see the file COPYING.  If not, write to the Free
      19     Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
      20     02110-1301, USA.  */
      21  
      22  #define TC_PPC
      23  
      24  #include "opcode/ppc.h"
      25  
      26  struct fix;
      27  
      28  /* Set the endianness we are using.  Default to big endian.  */
      29  #ifndef TARGET_BYTES_BIG_ENDIAN
      30  #define TARGET_BYTES_BIG_ENDIAN 1
      31  #endif
      32  
      33  /* If OBJ_COFF is defined we are assembling XCOFF for AIX or PowerMac.  */
      34  #ifdef OBJ_COFF
      35  #define OBJ_XCOFF
      36  #endif
      37  
      38  /* The target BFD architecture.  */
      39  #define TARGET_ARCH (ppc_arch ())
      40  #define TARGET_MACH (ppc_mach ())
      41  extern enum bfd_architecture ppc_arch (void);
      42  extern unsigned long ppc_mach (void);
      43  
      44  /* Whether or not the target is big endian */
      45  extern int target_big_endian;
      46  
      47  /* The target BFD format.  */
      48  #define TARGET_FORMAT (ppc_target_format ())
      49  extern const char *ppc_target_format (void);
      50  
      51  /* Permit temporary numeric labels.  */
      52  #define LOCAL_LABELS_FB 1
      53  
      54  /* $ is used to refer to the current location.  */
      55  #define DOLLAR_DOT
      56  
      57  /* Strings do not use backslash escapes under COFF.  */
      58  #ifdef OBJ_COFF
      59  #define TC_STRING_ESCAPES 0
      60  #endif
      61  
      62  #ifdef OBJ_ELF
      63  #define DIFF_EXPR_OK		/* foo-. gets turned into PC relative relocs */
      64  #endif
      65  
      66  #if TARGET_BYTES_BIG_ENDIAN
      67  #define PPC_BIG_ENDIAN 1
      68  #else
      69  #define PPC_BIG_ENDIAN 0
      70  #endif
      71  
      72  /* We don't need to handle .word strangely.  */
      73  #define WORKING_DOT_WORD
      74  
      75  #define MAX_MEM_FOR_RS_ALIGN_CODE 4
      76  #define HANDLE_ALIGN(FRAGP)						\
      77    if ((FRAGP)->fr_type == rs_align_code)				\
      78      ppc_handle_align (FRAGP);
      79  
      80  extern unsigned int ppc_nop_select (void);
      81  #define NOP_OPCODE ppc_nop_select ()
      82  
      83  extern void ppc_handle_align (struct frag *);
      84  extern void ppc_frag_check (struct frag *);
      85  
      86  #ifdef OBJ_ELF
      87  #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
      88  #endif
      89  
      90  #define md_frag_check(FRAGP) ppc_frag_check (FRAGP)
      91  
      92  /* Arrange to store the value of ppc_cpu at the site of a fixup
      93     for later use in md_apply_fix.  */
      94  struct _ppc_fix_extra
      95  {
      96    ppc_cpu_t ppc_cpu;
      97  };
      98  
      99  extern ppc_cpu_t ppc_cpu;
     100  
     101  #define TC_FIX_TYPE struct _ppc_fix_extra
     102  #define TC_INIT_FIX_DATA(FIXP) \
     103    do { (FIXP)->tc_fix_data.ppc_cpu = ppc_cpu; } while (0)
     104  
     105  #ifdef OBJ_XCOFF
     106  
     107  /* Declarations needed when generating XCOFF code.  XCOFF is an
     108     extension of COFF, used only on the RS/6000.  Rather than create an
     109     obj-xcoff, we just use obj-coff, and handle the extensions here in
     110     tc-ppc.  */
     111  
     112  /* We need to keep some information for symbols.  */
     113  struct ppc_tc_sy
     114  {
     115    /* We keep a few linked lists of symbols.  */
     116    symbolS *next;
     117    /* The real name, if the symbol was renamed.  */
     118    char *real_name;
     119    /* Non-zero if the symbol should be output.  The RS/6000 assembler
     120       only outputs symbols that are external or are mentioned in a
     121       .globl or .lglobl statement.  */
     122    unsigned char output;
     123    /* The symbol class.  */
     124    short symbol_class;
     125    /* For a csect or common symbol, the alignment to use.  */
     126    unsigned char align;
     127    /* For a csect symbol, the subsegment we are using.  This is zero
     128       for symbols that are not csects.  */
     129    subsegT subseg;
     130    /* For a csect symbol, the last symbol which has been defined in
     131       this csect, or NULL if none have been defined so far.
     132       For a .bs symbol, the referenced csect symbol.
     133       For a C_STSYM symbol, the containing block (.bs symbol).
     134       For a label, the enclosing csect.  */
     135    symbolS *within;
     136    union
     137    {
     138      /* For a function symbol, a symbol whose value is the size.  The
     139         field is NULL if there is no size.  */
     140      symbolS *size;
     141      /* For a dwarf symbol, the corresponding dwarf subsection.  */
     142      struct dw_subsection *dw;
     143    } u;
     144  };
     145  
     146  #define TC_SYMFIELD_TYPE struct ppc_tc_sy
     147  
     148  /* We need an additional auxent for function symbols.  */
     149  #define OBJ_COFF_MAX_AUXENTRIES 4
     150  
     151  /* Square and curly brackets are permitted in symbol names.  */
     152  #define LEX_BR 3
     153  
     154  /* Canonicalize the symbol name.  */
     155  #define tc_canonicalize_symbol_name(name) ppc_canonicalize_symbol_name (name)
     156  extern char *ppc_canonicalize_symbol_name (char *);
     157  
     158  /* Get the symbol class from the name.  */
     159  #define tc_symbol_new_hook(sym) ppc_symbol_new_hook (sym)
     160  extern void ppc_symbol_new_hook (symbolS *);
     161  
     162  /* TOC relocs requires special handling.  */
     163  #define tc_fix_adjustable(FIX) ppc_fix_adjustable (FIX)
     164  extern int ppc_fix_adjustable (struct fix *);
     165  
     166  /* We need to set the section VMA.  */
     167  #define tc_frob_section(sec) ppc_frob_section (sec)
     168  extern void ppc_frob_section (asection *);
     169  
     170  /* Finish up the symbol.  */
     171  #define tc_frob_symbol(sym, punt) punt = ppc_frob_symbol (sym)
     172  extern int ppc_frob_symbol (symbolS *);
     173  
     174  /* Finish up the entire symtab.  */
     175  #define tc_adjust_symtab() ppc_adjust_symtab ()
     176  extern void ppc_adjust_symtab (void);
     177  
     178  /* We also need to copy, in particular, the class of the symbol,
     179     over what obj-coff would otherwise have copied.  */
     180  #define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src)			\
     181  do {								\
     182    if (SF_GET_GET_SEGMENT (dest))				\
     183      S_SET_SEGMENT (dest, S_GET_SEGMENT (src));			\
     184    symbol_get_tc (dest)->u = symbol_get_tc (src)->u;		\
     185    symbol_get_tc (dest)->align = symbol_get_tc (src)->align;	\
     186    symbol_get_tc (dest)->symbol_class = symbol_get_tc (src)->symbol_class;	\
     187    symbol_get_tc (dest)->within = symbol_get_tc (src)->within;	\
     188  } while (0)
     189  
     190  extern void ppc_xcoff_md_finish (void);
     191  #define md_finish ppc_xcoff_md_finish
     192  
     193  #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES)	\
     194    ppc_xcoff_parse_cons (EXP, NBYTES)
     195  extern bfd_reloc_code_real_type ppc_xcoff_parse_cons (expressionS *,
     196  						    unsigned int);
     197  /* XCOFF format allows only few predefined sections. Gather all
     198     information in a common structure.  */
     199  struct ppc_xcoff_section {
     200    /* Main segment of the section.  */
     201    segT segment;
     202  
     203    /* Next subsegment to allocate within the segment.  */
     204    subsegT next_subsegment;
     205  
     206    /* Linked list of csects in the section.  */
     207    symbolS *csects;
     208  };
     209  
     210  #endif /* OBJ_XCOFF */
     211  
     212  #define tc_new_dot_label(sym) ppc_new_dot_label (sym)
     213  extern void ppc_new_dot_label (symbolS *);
     214  
     215  extern const char       ppc_symbol_chars[];
     216  #define tc_symbol_chars ppc_symbol_chars
     217  
     218  #ifdef OBJ_ELF
     219  
     220  /* Support for SHT_ORDERED */
     221  extern int ppc_section_type (char *, size_t);
     222  extern int ppc_section_flags (flagword, bfd_vma, int);
     223  
     224  #define md_elf_section_type(STR, LEN)		ppc_section_type (STR, LEN)
     225  #define md_elf_section_flags(FLAGS, ATTR, TYPE)	ppc_section_flags (FLAGS, ATTR, TYPE)
     226  
     227  #define tc_comment_chars ppc_comment_chars
     228  extern const char *ppc_comment_chars;
     229  
     230  #define md_elf_section_letter		ppc_elf_section_letter
     231  extern bfd_vma ppc_elf_section_letter (int, const char **);
     232  
     233  /* Keep relocations relative to the GOT, or non-PC relative.  */
     234  #define tc_fix_adjustable(FIX) ppc_fix_adjustable (FIX)
     235  extern int ppc_fix_adjustable (struct fix *);
     236  
     237  /* Values passed to md_apply_fix don't include symbol values.  */
     238  #define MD_APPLY_SYM_VALUE(FIX) 0
     239  
     240  #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
     241    ppc_elf_parse_cons (EXP, NBYTES)
     242  extern bfd_reloc_code_real_type ppc_elf_parse_cons (expressionS *,
     243  						    unsigned int);
     244  #define TC_CONS_FIX_CHECK(EXP, NBYTES, FIX) \
     245    ppc_elf_cons_fix_check (EXP, NBYTES, FIX)
     246  extern void ppc_elf_cons_fix_check (expressionS *, unsigned int, struct fix *);
     247  
     248  #define tc_frob_file_before_adjust ppc_frob_file_before_adjust
     249  extern void ppc_frob_file_before_adjust (void);
     250  
     251  #define tc_adjust_symtab() ppc_elf_adjust_symtab ()
     252  extern void ppc_elf_adjust_symtab (void);
     253  
     254  extern void ppc_elf_md_finish (void);
     255  #define md_finish ppc_elf_md_finish
     256  
     257  #endif /* OBJ_ELF */
     258  
     259  extern void ppc_md_end (void);
     260  #define md_end ppc_md_end
     261  
     262  #if defined (OBJ_ELF) || defined (OBJ_XCOFF)
     263  #define TC_FORCE_RELOCATION(FIX) ppc_force_relocation (FIX)
     264  extern int ppc_force_relocation (struct fix *);
     265  #endif
     266  
     267  #ifdef OBJ_ELF
     268  /* Don't allow the generic code to convert fixups involving the
     269     subtraction of a label in the current section to pc-relative if we
     270     don't have the necessary pc-relative relocation.  */
     271  #define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \
     272    (!((FIX)->fx_r_type == BFD_RELOC_64				\
     273       || (FIX)->fx_r_type == BFD_RELOC_32			\
     274       || (FIX)->fx_r_type == BFD_RELOC_16			\
     275       || (FIX)->fx_r_type == BFD_RELOC_LO16			\
     276       || (FIX)->fx_r_type == BFD_RELOC_HI16			\
     277       || (FIX)->fx_r_type == BFD_RELOC_HI16_S			\
     278       || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGH		\
     279       || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHA	\
     280       || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER		\
     281       || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER_S		\
     282       || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST		\
     283       || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST_S		\
     284       || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHER34	\
     285       || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHERA34	\
     286       || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHEST34	\
     287       || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHESTA34	\
     288       || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA		\
     289       || (FIX)->fx_r_type == BFD_RELOC_PPC64_D34			\
     290       || (FIX)->fx_r_type == BFD_RELOC_PPC64_D28))
     291  
     292  #endif /* OBJ_ELF */
     293  
     294  #define RELOC_EXPANSION_POSSIBLE
     295  #define MAX_RELOC_EXPANSION 2
     296  
     297  #if defined (OBJ_XCOFF)
     298  /* Force a relocation when the fix is negative. */
     299  #define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG)				\
     300    (GENERIC_FORCE_RELOCATION_SUB_SAME(FIX, SEG)				\
     301     || (((SEG)->flags & SEC_DEBUGGING) == 0				\
     302  	&& (FIX)->fx_addsy && (FIX)->fx_subsy				\
     303  	&& (S_GET_VALUE (fixP->fx_addsy) < S_GET_VALUE (fixP->fx_subsy))))
     304  
     305  /* XCOFF allows undefined differences which will be encoded with
     306     R_NEG relocations.  */
     307  #define UNDEFINED_DIFFERENCE_OK
     308  
     309  #define TC_VALIDATE_FIX_SUB(FIX, SEG) \
     310    (md_register_arithmetic || (SEG) != reg_section)
     311  
     312  #endif /* OBJ_XCOFF */
     313  
     314  /* Various frobbings of labels and their addresses.  */
     315  #define md_start_line_hook() ppc_start_line_hook ()
     316  extern void ppc_start_line_hook (void);
     317  
     318  /* Set the symbol class of a label based on the csect.  */
     319  #define tc_frob_label(sym) ppc_frob_label (sym)
     320  extern void ppc_frob_label (symbolS *);
     321  
     322  /* call md_pcrel_from_section, not md_pcrel_from */
     323  #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC)
     324  
     325  #define md_parse_name(name, exp, mode, c) \
     326    (ppc_parse_name (name, exp, mode), true)
     327  extern void ppc_parse_name (const char *, struct expressionS *, enum expr_mode);
     328  
     329  #define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right)
     330  extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *);
     331  
     332  #define md_cleanup() ppc_cleanup ()
     333  extern void ppc_cleanup (void);
     334  
     335  #if (defined TE_AIX5 || defined TE_AIX					\
     336       || defined TE_FreeBSD || defined TE_NetBSD || defined TE_LYNX)
     337  /* ppc uses different register numbers between .eh_frame and .debug_frame.
     338     This macro translates the .eh_frame register numbers to .debug_frame
     339     register numbers.  */
     340  #define md_reg_eh_frame_to_debug_frame(regno)				\
     341    ((regno) == 70 ? 64	/* cr2 */					\
     342     : (regno) == 65 ? 108 /* lr */					\
     343     : (regno) == 66 ? 109 /* ctr */					\
     344     : (regno) >= 68 && (regno) <= 75 ? (regno) + 86 - 68 /* crN */	\
     345     : (regno) == 76 ? 101 /* xer */					\
     346     : (regno) >= 77 && (regno) <= 108 ? (regno) + 1124 - 77 /* vrN */	\
     347     : (regno) == 109 ? 356 /* vrsave */					\
     348     : (regno) == 110 ? 67 /* vscr */					\
     349     : (regno) == 111 ? 99 /* spe_acc */					\
     350     : (regno) == 112 ? 612 /* spefscr */					\
     351     : (regno))
     352  #endif
     353  
     354  #define TARGET_USE_CFIPOP 1
     355  
     356  #define tc_cfi_frame_initial_instructions ppc_cfi_frame_initial_instructions
     357  extern void ppc_cfi_frame_initial_instructions (void);
     358  
     359  #define tc_regname_to_dw2regnum tc_ppc_regname_to_dw2regnum
     360  extern int tc_ppc_regname_to_dw2regnum (char *);
     361  
     362  extern int ppc_cie_data_alignment;
     363  
     364  extern int ppc_dwarf2_line_min_insn_length;
     365  
     366  #define DWARF2_LINE_MIN_INSN_LENGTH     ppc_dwarf2_line_min_insn_length
     367  #define DWARF2_DEFAULT_RETURN_COLUMN    0x41
     368  #define DWARF2_CIE_DATA_ALIGNMENT       ppc_cie_data_alignment
     369  #define EH_FRAME_ALIGNMENT		2