(root)/
gcc-13.2.0/
gcc/
config/
sh/
sh-protos.h
       1  /* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
       2     Copyright (C) 1993-2023 Free Software Foundation, Inc.
       3     Contributed by Steve Chamberlain (sac@cygnus.com).
       4     Improved by Jim Wilson (wilson@cygnus.com).
       5  
       6  This file is part of GCC.
       7  
       8  GCC 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  GCC 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 GCC; see the file COPYING3.  If not see
      20  <http://www.gnu.org/licenses/>.  */
      21  
      22  #ifndef GCC_SH_PROTOS_H
      23  #define GCC_SH_PROTOS_H
      24  
      25  enum sh_function_kind {
      26    /* A function with normal C ABI  */
      27    FUNCTION_ORDINARY,
      28    /* A special function that guarantees that some otherwise call-clobbered
      29       registers are not clobbered.  These can't go through the SH5 resolver,
      30       because it only saves argument passing registers.  */
      31    SFUNC_GOT,
      32    /* A special function that should be linked statically.  These are typically
      33       smaller or not much larger than a PLT entry.
      34       Some also have a non-standard ABI which precludes dynamic linking.  */
      35    SFUNC_STATIC
      36  };
      37  
      38  #ifdef RTX_CODE
      39  extern rtx sh_fsca_sf2int (void);
      40  extern rtx sh_fsca_int2sf (void);
      41  
      42  /* Declare functions defined in sh.cc and used in templates.  */
      43  extern bool sh_lra_p (void);
      44  
      45  extern const char *output_branch (int, rtx_insn *, rtx *);
      46  extern const char *output_ieee_ccmpeq (rtx_insn *, rtx *);
      47  extern const char *output_branchy_insn (enum rtx_code, const char *,
      48  					rtx_insn *, rtx *);
      49  extern const char *output_movedouble (rtx, rtx[], machine_mode);
      50  extern const char *output_movepcrel (rtx, rtx[], machine_mode);
      51  extern const char *output_far_jump (rtx_insn *, rtx);
      52  
      53  extern rtx sfunc_uses_reg (rtx_insn *);
      54  extern int barrier_align (rtx_insn *);
      55  extern int sh_loop_align (rtx_insn *);
      56  extern bool fp_zero_operand (rtx);
      57  extern bool fp_one_operand (rtx);
      58  extern bool sh_legitimate_index_p (machine_mode, rtx, bool, bool);
      59  extern bool sh_legitimize_reload_address (rtx *, machine_mode, int, int);
      60  extern rtx legitimize_pic_address (rtx, machine_mode, rtx);
      61  extern bool nonpic_symbol_mentioned_p (rtx);
      62  extern void output_pic_addr_const (FILE *, rtx);
      63  extern bool expand_block_move (rtx *);
      64  extern void prepare_move_operands (rtx[], machine_mode mode);
      65  extern bool sh_expand_cmpstr (rtx *);
      66  extern bool sh_expand_cmpnstr (rtx *);
      67  extern bool sh_expand_strlen  (rtx *);
      68  extern void sh_expand_setmem (rtx *);
      69  extern enum rtx_code prepare_cbranch_operands (rtx *, machine_mode mode,
      70  					       enum rtx_code comparison);
      71  extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison);
      72  extern bool expand_cbranchdi4 (rtx *operands, enum rtx_code comparison);
      73  extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx);
      74  extern void sh_emit_compare_and_branch (rtx *, machine_mode);
      75  extern void sh_emit_compare_and_set (rtx *, machine_mode);
      76  extern bool sh_ashlsi_clobbers_t_reg_p (rtx);
      77  extern bool sh_lshrsi_clobbers_t_reg_p (rtx);
      78  extern void gen_shifty_op (int, rtx *);
      79  extern void gen_shifty_hi_op (int, rtx *);
      80  extern bool expand_ashiftrt (rtx *);
      81  extern bool sh_dynamicalize_shift_p (rtx);
      82  extern int shl_and_kind (rtx, rtx, int *);
      83  extern int shl_and_length (rtx);
      84  extern int shl_and_scr_length (rtx);
      85  extern bool gen_shl_and (rtx, rtx, rtx, rtx);
      86  extern int shl_sext_kind (rtx, rtx, int *);
      87  extern int shl_sext_length (rtx);
      88  extern bool gen_shl_sext (rtx, rtx, rtx, rtx);
      89  extern int regs_used (rtx, int);
      90  extern void fixup_addr_diff_vecs (rtx_insn *);
      91  extern int get_dest_uid (rtx_insn *, int);
      92  extern void final_prescan_insn (rtx_insn *, rtx *, int);
      93  extern enum tls_model tls_symbolic_operand (rtx, machine_mode);
      94  extern bool system_reg_operand (rtx, machine_mode);
      95  extern bool reg_unused_after (rtx, rtx_insn *);
      96  extern int sh_insn_length_adjustment (rtx_insn *);
      97  extern bool sh_expand_t_scc (rtx *);
      98  extern rtx sh_gen_truncate (machine_mode, rtx, int);
      99  extern bool sh_vector_mode_supported_p (machine_mode);
     100  extern bool sh_cfun_trap_exit_p (void);
     101  extern rtx sh_find_equiv_gbr_addr (rtx_insn* cur_insn, rtx mem);
     102  extern int sh_eval_treg_value (rtx op);
     103  extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op);
     104  extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a);
     105  extern bool sh_movsf_ie_ra_split_p (rtx, rtx, rtx);
     106  extern void sh_expand_sym_label2reg (rtx, rtx, rtx, bool);
     107  
     108  /* Result value of sh_find_set_of_reg.  */
     109  struct set_of_reg
     110  {
     111    /* The insn where sh_find_set_of_reg stopped looking.
     112       Can be NULL_RTX if the end of the insn list was reached.  */
     113    rtx_insn* insn;
     114  
     115    /* The set rtx of the specified reg if found, NULL_RTX otherwise.  */
     116    const_rtx set_rtx;
     117  
     118    /* The set source rtx of the specified reg if found, NULL_RTX otherwise.
     119       Usually, this is the most interesting return value.  */
     120    rtx set_src;
     121  };
     122  
     123  /* Given a reg rtx and a start insn, try to find the insn that sets
     124     the specified reg by using the specified insn stepping function,
     125     such as 'prev_nonnote_nondebug_insn_bb'.  When the insn is found,
     126     try to extract the rtx of the reg set.  */
     127  template <typename F> inline set_of_reg
     128  sh_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc,
     129  		    bool ignore_reg_reg_copies = false)
     130  {
     131    set_of_reg result;
     132    result.insn = insn;
     133    result.set_rtx = NULL_RTX;
     134    result.set_src = NULL_RTX;
     135  
     136    if (!REG_P (reg) || insn == NULL_RTX)
     137      return result;
     138  
     139    for (rtx_insn* i = stepfunc (insn); i != NULL_RTX; i = stepfunc (i))
     140      {
     141        if (BARRIER_P (i))
     142  	break;
     143        if (!INSN_P (i) || DEBUG_INSN_P (i))
     144  	  continue;
     145        if (reg_set_p (reg, i))
     146  	{
     147  	  if (CALL_P (i))
     148  	    break;
     149  
     150  	  result.insn = i;
     151  	  result.set_rtx = set_of (reg, i);
     152  
     153  	  if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
     154  	    break;
     155  
     156  	  result.set_src = XEXP (result.set_rtx, 1);
     157  
     158  	  if (ignore_reg_reg_copies && REG_P (result.set_src))
     159  	    {
     160  	      reg = result.set_src;
     161  	      continue;
     162  	    }
     163  	  if (ignore_reg_reg_copies && SUBREG_P (result.set_src)
     164  	      && REG_P (SUBREG_REG (result.set_src)))
     165  	    {
     166  	      reg = SUBREG_REG (result.set_src);
     167  	      continue;
     168  	    }
     169  
     170  	  break;
     171  	}
     172      }
     173  
     174    /* If the searched reg is found inside a (mem (post_inc:SI (reg))), set_of
     175       will return NULL and set_rtx will be NULL.
     176       In this case report a 'not found'.  result.insn will always be non-null
     177       at this point, so no need to check it.  */
     178    if (result.set_src != NULL && result.set_rtx == NULL)
     179      result.set_src = NULL;
     180  
     181    return result;
     182  }
     183  
     184  /* Result value of sh_find_extending_set_of_reg.  */
     185  struct sh_extending_set_of_reg : public set_of_reg
     186  {
     187    /* The mode the set is extending from (QImode or HImode), or VOIDmode if
     188       this is not a zero/sign extending set.  */
     189    machine_mode from_mode;
     190  
     191    /* ZERO_EXTEND, SIGN_EXTEND or UNKNOWN.  */
     192    rtx_code ext_code;
     193  
     194    sh_extending_set_of_reg (rtx_insn* i)
     195    {
     196      insn = i;
     197      set_rtx = NULL;
     198      set_src = NULL;
     199      from_mode = VOIDmode;
     200      ext_code = UNKNOWN;
     201    }
     202  
     203    sh_extending_set_of_reg (const set_of_reg& rhs)
     204    {
     205      *((set_of_reg*)this) = rhs;
     206      from_mode = VOIDmode;
     207      ext_code = UNKNOWN;
     208    }
     209  
     210    /* Returns true if it's possible to use the source reg of the sign
     211       or zero extending set directly, bypassing the extension.  */
     212    bool can_use_as_unextended_reg (void) const;
     213  
     214    /* Returns the reg rtx of the sign or zero extending set source, that can
     215       be safely used at the specified insn in SImode.  */
     216    rtx use_as_unextended_reg (rtx_insn* use_at_insn) const;
     217  
     218    /* Returns the reg rtx of the sign or zero extending result, that can be
     219       safely used at the specified insn in SImode.  If the set source is an
     220       implicitly sign extending mem load, the mem load is converted into an
     221       explicitly sign extending mem load.  */
     222    rtx use_as_extended_reg (rtx_insn* use_at_insn) const;
     223  };
     224  
     225  extern sh_extending_set_of_reg sh_find_extending_set_of_reg (rtx reg,
     226  							     rtx_insn* insn);
     227  
     228  extern bool sh_is_logical_t_store_expr (rtx op, rtx_insn* insn);
     229  extern rtx sh_try_omit_signzero_extend (rtx extended_op, rtx_insn* insn);
     230  extern bool sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn,
     231  					     rtx operands[]);
     232  extern void sh_split_tst_subregs (rtx_insn* curr_insn,
     233  				  machine_mode subreg_mode, int subreg_offset,
     234  				  rtx operands[]);
     235  
     236  extern bool sh_is_nott_insn (const rtx_insn* i);
     237  extern rtx sh_movt_set_dest (const rtx_insn* i);
     238  extern rtx sh_movt_set_dest (const_rtx i);
     239  extern rtx sh_movrt_set_dest (const rtx_insn* i);
     240  extern rtx sh_movrt_set_dest (const_rtx i);
     241  
     242  inline bool sh_is_movt_insn (const rtx_insn* i)
     243  {
     244    return sh_movt_set_dest (i) != NULL;
     245  }
     246  
     247  inline bool sh_is_movrt_insn (const rtx_insn* i)
     248  {
     249    return sh_movrt_set_dest (i) != NULL;
     250  }
     251  
     252  extern bool sh_insn_operands_modified_between_p (rtx_insn* operands_insn,
     253  						 const rtx_insn* from,
     254  						 const rtx_insn* to);
     255  
     256  extern bool sh_reg_dead_or_unused_after_insn (const rtx_insn* i, int regno);
     257  extern void sh_remove_reg_dead_or_unused_notes (rtx_insn* i, int regno);
     258  extern rtx_insn* sh_check_add_incdec_notes (rtx_insn* i);
     259  extern rtx sh_remove_overlapping_post_inc (rtx dst, rtx src);
     260  extern rtx_insn* sh_peephole_emit_move_insn (rtx dst, rtx src);
     261  
     262  extern bool sh_in_recog_treg_set_expr (void);
     263  extern bool sh_recog_treg_set_expr (rtx op, machine_mode mode);
     264  
     265  /* Result value of sh_split_treg_set_expr.  Contains the first insn emitted
     266     and the optional trailing nott insn.  */
     267  class sh_treg_insns
     268  {
     269  public:
     270    sh_treg_insns (void) : m_first_insn (NULL), m_trailing_nott_insn (NULL) { }
     271    sh_treg_insns (rtx_insn* first_insn, rtx_insn* nott_insn)
     272    : m_first_insn (first_insn),
     273      m_trailing_nott_insn (nott_insn)
     274    { }
     275  
     276    bool was_treg_operand (void) const { return m_first_insn == NULL; }
     277    bool has_trailing_nott (void) const { return m_trailing_nott_insn != NULL; }
     278    rtx_insn* trailing_nott (void) const { return m_trailing_nott_insn; }
     279    rtx_insn* first_insn (void) const { return m_first_insn; }
     280  
     281    /* If there is a trailing nott, remove it from the emitted insns and
     282       return true.  Return false otherwise.  */
     283    bool
     284    remove_trailing_nott (void)
     285    {
     286      if (!has_trailing_nott ())
     287        return false;
     288  
     289      remove_insn (trailing_nott ());
     290      return true;
     291    }
     292  
     293  private:
     294    rtx_insn* m_first_insn;
     295    rtx_insn* m_trailing_nott_insn;
     296  };
     297  
     298  extern sh_treg_insns sh_split_treg_set_expr (rtx x, rtx_insn* curr_insn);
     299  
     300  enum
     301  {
     302    /* An effective conditional branch distance of zero bytes is impossible.
     303       Hence we can use it to designate an unknown value.  */
     304    unknown_cbranch_distance = 0u,
     305    infinite_cbranch_distance = ~0u
     306  };
     307  
     308  unsigned int
     309  sh_cbranch_distance (rtx_insn* cbranch_insn,
     310  		     unsigned int max_dist = infinite_cbranch_distance);
     311  
     312  #endif /* RTX_CODE */
     313  
     314  extern void sh_cpu_cpp_builtins (cpp_reader* pfile);
     315  
     316  extern const char *output_jump_label_table (void);
     317  extern rtx get_t_reg_rtx (void);
     318  extern void sh_expand_prologue (void);
     319  extern void sh_expand_epilogue (bool);
     320  extern void sh_set_return_address (rtx, rtx);
     321  extern int initial_elimination_offset (int, int);
     322  extern bool sh_hard_regno_rename_ok (unsigned int, unsigned int);
     323  extern bool sh_cfun_interrupt_handler_p (void);
     324  extern bool sh_cfun_resbank_handler_p (void);
     325  extern bool sh_attr_renesas_p (const_tree);
     326  extern bool sh_cfun_attr_renesas_p (void);
     327  extern bool sh_small_register_classes_for_mode_p (machine_mode);
     328  extern void sh_mark_label (rtx, int);
     329  extern bool check_use_sfunc_addr (rtx_insn *, rtx);
     330  
     331  #ifdef HARD_CONST
     332  extern void fpscr_set_from_mem (int, HARD_REG_SET);
     333  #endif
     334  
     335  extern void sh_pr_interrupt (struct cpp_reader *);
     336  extern void sh_pr_trapa (struct cpp_reader *);
     337  extern void sh_pr_nosave_low_regs (struct cpp_reader *);
     338  
     339  struct function_symbol_result
     340  {
     341    function_symbol_result (void) : sym (NULL), lab (NULL) { }
     342    function_symbol_result (rtx s, rtx l) : sym (s), lab (l) { }
     343  
     344    rtx sym;
     345    rtx lab;
     346  };
     347  
     348  extern function_symbol_result function_symbol (rtx, const char *,
     349  					       sh_function_kind);
     350  extern rtx sh_get_fdpic_reg_initial_val (void);
     351  extern rtx sh_get_pr_initial_val (void);
     352  
     353  extern void sh_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree,
     354  				     signed int, machine_mode);
     355  extern rtx sh_dwarf_register_span (rtx);
     356  
     357  extern bool sh_contains_memref_p (rtx);
     358  extern bool sh_loads_bankedreg_p (rtx);
     359  extern int sh2a_get_function_vector_number (rtx);
     360  extern bool sh2a_is_function_vector_call (rtx);
     361  extern void sh_fix_range (const char *);
     362  extern machine_mode sh_hard_regno_caller_save_mode (unsigned int, unsigned int,
     363  						    machine_mode);
     364  extern bool sh_can_use_simple_return_p (void);
     365  extern rtx sh_load_function_descriptor (rtx);
     366  #endif /* ! GCC_SH_PROTOS_H */