Home | History | Annotate | Line # | Download | only in sh
sh-protos.h revision 1.1.1.4
      1 /* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
      2    Copyright (C) 1993-2016 Free Software Foundation, Inc.
      3    Contributed by Steve Chamberlain (sac (at) cygnus.com).
      4    Improved by Jim Wilson (wilson (at) 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 /* Atomic model.  */
     39 struct sh_atomic_model
     40 {
     41   enum enum_type
     42   {
     43     none = 0,
     44     soft_gusa,
     45     hard_llcs,
     46     soft_tcb,
     47     soft_imask,
     48 
     49     num_models
     50   };
     51 
     52   /*  If strict is set, disallow mixing of different models, as it would
     53       happen on SH4A.  */
     54   bool strict;
     55   enum_type type;
     56 
     57   /* Name string as it was specified on the command line.  */
     58   const char* name;
     59 
     60   /* Name string as it is used in C/C++ defines.  */
     61   const char* cdef_name;
     62 
     63   /* GBR offset variable for TCB model.  */
     64   int tcb_gbr_offset;
     65 };
     66 
     67 extern const sh_atomic_model& selected_atomic_model (void);
     68 
     69 /* Shortcuts to check the currently selected atomic model.  */
     70 #define TARGET_ATOMIC_ANY \
     71   (selected_atomic_model ().type != sh_atomic_model::none)
     72 
     73 #define TARGET_ATOMIC_STRICT \
     74   (selected_atomic_model ().strict)
     75 
     76 #define TARGET_ATOMIC_SOFT_GUSA \
     77   (selected_atomic_model ().type == sh_atomic_model::soft_gusa)
     78 
     79 #define TARGET_ATOMIC_HARD_LLCS \
     80   (selected_atomic_model ().type == sh_atomic_model::hard_llcs)
     81 
     82 #define TARGET_ATOMIC_SOFT_TCB \
     83   (selected_atomic_model ().type == sh_atomic_model::soft_tcb)
     84 
     85 #define TARGET_ATOMIC_SOFT_TCB_GBR_OFFSET_RTX \
     86   GEN_INT (selected_atomic_model ().tcb_gbr_offset)
     87 
     88 #define TARGET_ATOMIC_SOFT_IMASK \
     89   (selected_atomic_model ().type == sh_atomic_model::soft_imask)
     90 
     91 #ifdef RTX_CODE
     92 extern rtx sh_fsca_sf2int (void);
     93 extern rtx sh_fsca_int2sf (void);
     94 
     95 /* Declare functions defined in sh.c and used in templates.  */
     96 extern bool sh_lra_p (void);
     97 
     98 extern const char *output_branch (int, rtx_insn *, rtx *);
     99 extern const char *output_ieee_ccmpeq (rtx_insn *, rtx *);
    100 extern const char *output_branchy_insn (enum rtx_code, const char *,
    101 					rtx_insn *, rtx *);
    102 extern const char *output_movedouble (rtx, rtx[], machine_mode);
    103 extern const char *output_movepcrel (rtx, rtx[], machine_mode);
    104 extern const char *output_far_jump (rtx_insn *, rtx);
    105 
    106 extern rtx sfunc_uses_reg (rtx_insn *);
    107 extern int barrier_align (rtx_insn *);
    108 extern int sh_loop_align (rtx_insn *);
    109 extern bool fp_zero_operand (rtx);
    110 extern bool fp_one_operand (rtx);
    111 extern bool sh_legitimate_index_p (machine_mode, rtx, bool, bool);
    112 extern bool sh_legitimize_reload_address (rtx *, machine_mode, int, int);
    113 extern rtx legitimize_pic_address (rtx, machine_mode, rtx);
    114 extern bool nonpic_symbol_mentioned_p (rtx);
    115 extern void output_pic_addr_const (FILE *, rtx);
    116 extern bool expand_block_move (rtx *);
    117 extern void prepare_move_operands (rtx[], machine_mode mode);
    118 extern bool sh_expand_cmpstr (rtx *);
    119 extern bool sh_expand_cmpnstr (rtx *);
    120 extern bool sh_expand_strlen  (rtx *);
    121 extern void sh_expand_setmem (rtx *);
    122 extern enum rtx_code prepare_cbranch_operands (rtx *, machine_mode mode,
    123 					       enum rtx_code comparison);
    124 extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int);
    125 extern bool expand_cbranchdi4 (rtx *operands, enum rtx_code comparison);
    126 extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx);
    127 extern rtx sh_emit_cheap_store_flag (machine_mode, enum rtx_code, rtx, rtx);
    128 extern void sh_emit_compare_and_branch (rtx *, machine_mode);
    129 extern void sh_emit_compare_and_set (rtx *, machine_mode);
    130 extern bool sh_ashlsi_clobbers_t_reg_p (rtx);
    131 extern bool sh_lshrsi_clobbers_t_reg_p (rtx);
    132 extern void gen_shifty_op (int, rtx *);
    133 extern void gen_shifty_hi_op (int, rtx *);
    134 extern bool expand_ashiftrt (rtx *);
    135 extern bool sh_dynamicalize_shift_p (rtx);
    136 extern int shl_and_kind (rtx, rtx, int *);
    137 extern int shl_and_length (rtx);
    138 extern int shl_and_scr_length (rtx);
    139 extern bool gen_shl_and (rtx, rtx, rtx, rtx);
    140 extern int shl_sext_kind (rtx, rtx, int *);
    141 extern int shl_sext_length (rtx);
    142 extern bool gen_shl_sext (rtx, rtx, rtx, rtx);
    143 extern rtx gen_datalabel_ref (rtx);
    144 extern int regs_used (rtx, int);
    145 extern void fixup_addr_diff_vecs (rtx_insn *);
    146 extern int get_dest_uid (rtx, int);
    147 extern void final_prescan_insn (rtx_insn *, rtx *, int);
    148 extern enum tls_model tls_symbolic_operand (rtx, machine_mode);
    149 extern bool system_reg_operand (rtx, machine_mode);
    150 extern bool reg_unused_after (rtx, rtx_insn *);
    151 extern int sh_insn_length_adjustment (rtx_insn *);
    152 extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx);
    153 extern void sh_expand_binop_v2sf (enum rtx_code, rtx, rtx, rtx);
    154 extern bool sh_expand_t_scc (rtx *);
    155 extern rtx sh_gen_truncate (machine_mode, rtx, int);
    156 extern bool sh_vector_mode_supported_p (machine_mode);
    157 extern bool sh_cfun_trap_exit_p (void);
    158 extern rtx sh_find_equiv_gbr_addr (rtx_insn* cur_insn, rtx mem);
    159 extern int sh_eval_treg_value (rtx op);
    160 extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op);
    161 extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a);
    162 extern bool sh_movsf_ie_ra_split_p (rtx, rtx, rtx);
    163 extern void sh_expand_sym_label2reg (rtx, rtx, rtx, bool);
    164 
    165 /* Result value of sh_find_set_of_reg.  */
    166 struct set_of_reg
    167 {
    168   /* The insn where sh_find_set_of_reg stopped looking.
    169      Can be NULL_RTX if the end of the insn list was reached.  */
    170   rtx_insn* insn;
    171 
    172   /* The set rtx of the specified reg if found, NULL_RTX otherwise.  */
    173   const_rtx set_rtx;
    174 
    175   /* The set source rtx of the specified reg if found, NULL_RTX otherwise.
    176      Usually, this is the most interesting return value.  */
    177   rtx set_src;
    178 };
    179 
    180 /* Given a reg rtx and a start insn, try to find the insn that sets the
    181    specified reg by using the specified insn stepping function, such as
    182    'prev_nonnote_insn_bb'.  When the insn is found, try to extract the rtx
    183    of the reg set.  */
    184 template <typename F> inline set_of_reg
    185 sh_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc,
    186 		    bool ignore_reg_reg_copies = false)
    187 {
    188   set_of_reg result;
    189   result.insn = insn;
    190   result.set_rtx = NULL_RTX;
    191   result.set_src = NULL_RTX;
    192 
    193   if (!REG_P (reg) || insn == NULL_RTX)
    194     return result;
    195 
    196   for (rtx_insn* i = stepfunc (insn); i != NULL_RTX; i = stepfunc (i))
    197     {
    198       if (BARRIER_P (i))
    199 	break;
    200       if (!INSN_P (i) || DEBUG_INSN_P (i))
    201 	  continue;
    202       if (reg_set_p (reg, i))
    203 	{
    204 	  if (CALL_P (i))
    205 	    break;
    206 
    207 	  result.insn = i;
    208 	  result.set_rtx = set_of (reg, i);
    209 
    210 	  if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
    211 	    break;
    212 
    213 	  result.set_src = XEXP (result.set_rtx, 1);
    214 
    215 	  if (ignore_reg_reg_copies && REG_P (result.set_src))
    216 	    {
    217 	      reg = result.set_src;
    218 	      continue;
    219 	    }
    220 	  if (ignore_reg_reg_copies && SUBREG_P (result.set_src)
    221 	      && REG_P (SUBREG_REG (result.set_src)))
    222 	    {
    223 	      reg = SUBREG_REG (result.set_src);
    224 	      continue;
    225 	    }
    226 
    227 	  break;
    228 	}
    229     }
    230 
    231   if (result.set_src != NULL)
    232     gcc_assert (result.insn != NULL && result.set_rtx != NULL);
    233 
    234   return result;
    235 }
    236 
    237 /* Result value of sh_find_extending_set_of_reg.  */
    238 struct sh_extending_set_of_reg : public set_of_reg
    239 {
    240   /* The mode the set is extending from (QImode or HImode), or VOIDmode if
    241      this is not a zero/sign extending set.  */
    242   machine_mode from_mode;
    243 
    244   /* ZERO_EXTEND, SIGN_EXTEND or UNKNOWN.  */
    245   rtx_code ext_code;
    246 
    247   sh_extending_set_of_reg (rtx_insn* i)
    248   {
    249     insn = i;
    250     set_rtx = NULL;
    251     set_src = NULL;
    252     from_mode = VOIDmode;
    253     ext_code = UNKNOWN;
    254   }
    255 
    256   sh_extending_set_of_reg (const set_of_reg& rhs)
    257   {
    258     *((set_of_reg*)this) = rhs;
    259     from_mode = VOIDmode;
    260     ext_code = UNKNOWN;
    261   }
    262 
    263   /* Returns true if it's possible to use the source reg of the sign
    264      or zero extending set directly, bypassing the extension.  */
    265   bool can_use_as_unextended_reg (void) const;
    266 
    267   /* Returns the reg rtx of the sign or zero extending set source, that can
    268      be safely used at the specified insn in SImode.  */
    269   rtx use_as_unextended_reg (rtx_insn* use_at_insn) const;
    270 
    271   /* Returns the reg rtx of the sign or zero extending result, that can be
    272      safely used at the specified insn in SImode.  If the set source is an
    273      implicitly sign extending mem load, the mem load is converted into an
    274      explicitly sign extending mem load.  */
    275   rtx use_as_extended_reg (rtx_insn* use_at_insn) const;
    276 };
    277 
    278 extern sh_extending_set_of_reg sh_find_extending_set_of_reg (rtx reg,
    279 							     rtx_insn* insn);
    280 
    281 extern bool sh_is_logical_t_store_expr (rtx op, rtx_insn* insn);
    282 extern rtx sh_try_omit_signzero_extend (rtx extended_op, rtx_insn* insn);
    283 extern bool sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn,
    284 					     rtx operands[]);
    285 extern void sh_split_tst_subregs (rtx_insn* curr_insn,
    286 				  machine_mode subreg_mode, int subreg_offset,
    287 				  rtx operands[]);
    288 
    289 extern bool sh_is_nott_insn (const rtx_insn* i);
    290 extern rtx sh_movt_set_dest (const rtx_insn* i);
    291 extern rtx sh_movrt_set_dest (const rtx_insn* i);
    292 
    293 inline bool sh_is_movt_insn (const rtx_insn* i)
    294 {
    295   return sh_movt_set_dest (i) != NULL;
    296 }
    297 
    298 inline bool sh_is_movrt_insn (const rtx_insn* i)
    299 {
    300   return sh_movrt_set_dest (i) != NULL;
    301 }
    302 
    303 extern bool sh_insn_operands_modified_between_p (rtx_insn* operands_insn,
    304 						 const rtx_insn* from,
    305 						 const rtx_insn* to);
    306 
    307 extern bool sh_reg_dead_or_unused_after_insn (const rtx_insn* i, int regno);
    308 extern void sh_remove_reg_dead_or_unused_notes (rtx_insn* i, int regno);
    309 extern rtx_insn* sh_check_add_incdec_notes (rtx_insn* i);
    310 extern rtx sh_remove_overlapping_post_inc (rtx dst, rtx src);
    311 extern rtx_insn* sh_peephole_emit_move_insn (rtx dst, rtx src);
    312 
    313 extern bool sh_in_recog_treg_set_expr (void);
    314 extern bool sh_recog_treg_set_expr (rtx op, machine_mode mode);
    315 
    316 /* Result value of sh_split_treg_set_expr.  Contains the first insn emitted
    317    and the optional trailing nott insn.  */
    318 class sh_treg_insns
    319 {
    320 public:
    321   sh_treg_insns (void) : m_first_insn (NULL), m_trailing_nott_insn (NULL) { }
    322   sh_treg_insns (rtx_insn* first_insn, rtx_insn* nott_insn)
    323   : m_first_insn (first_insn),
    324     m_trailing_nott_insn (nott_insn)
    325   { }
    326 
    327   bool was_treg_operand (void) const { return m_first_insn == NULL; }
    328   bool has_trailing_nott (void) const { return m_trailing_nott_insn != NULL; }
    329   rtx_insn* trailing_nott (void) const { return m_trailing_nott_insn; }
    330   rtx_insn* first_insn (void) const { return m_first_insn; }
    331 
    332   /* If there is a trailing nott, remove it from the emitted insns and
    333      return true.  Return false otherwise.  */
    334   bool
    335   remove_trailing_nott (void)
    336   {
    337     if (!has_trailing_nott ())
    338       return false;
    339 
    340     remove_insn (trailing_nott ());
    341     return true;
    342   }
    343 
    344 private:
    345   rtx_insn* m_first_insn;
    346   rtx_insn* m_trailing_nott_insn;
    347 };
    348 
    349 extern sh_treg_insns sh_split_treg_set_expr (rtx x, rtx_insn* curr_insn);
    350 
    351 #endif /* RTX_CODE */
    352 
    353 extern void sh_cpu_cpp_builtins (cpp_reader* pfile);
    354 
    355 extern const char *output_jump_label_table (void);
    356 extern rtx get_t_reg_rtx (void);
    357 extern int sh_media_register_for_return (void);
    358 extern void sh_expand_prologue (void);
    359 extern void sh_expand_epilogue (bool);
    360 extern void sh_set_return_address (rtx, rtx);
    361 extern int initial_elimination_offset (int, int);
    362 extern bool sh_hard_regno_rename_ok (unsigned int, unsigned int);
    363 extern bool sh_cfun_interrupt_handler_p (void);
    364 extern bool sh_cfun_resbank_handler_p (void);
    365 extern bool sh_attr_renesas_p (const_tree);
    366 extern bool sh_cfun_attr_renesas_p (void);
    367 extern bool sh_cannot_change_mode_class
    368 	      (machine_mode, machine_mode, enum reg_class);
    369 extern bool sh_small_register_classes_for_mode_p (machine_mode);
    370 extern void sh_mark_label (rtx, int);
    371 extern bool check_use_sfunc_addr (rtx_insn *, rtx);
    372 
    373 #ifdef HARD_CONST
    374 extern void fpscr_set_from_mem (int, HARD_REG_SET);
    375 #endif
    376 
    377 extern void sh_pr_interrupt (struct cpp_reader *);
    378 extern void sh_pr_trapa (struct cpp_reader *);
    379 extern void sh_pr_nosave_low_regs (struct cpp_reader *);
    380 
    381 struct function_symbol_result
    382 {
    383   function_symbol_result (void) : sym (NULL), lab (NULL) { }
    384   function_symbol_result (rtx s, rtx l) : sym (s), lab (l) { }
    385 
    386   rtx sym;
    387   rtx lab;
    388 };
    389 
    390 extern function_symbol_result function_symbol (rtx, const char *,
    391 					       sh_function_kind);
    392 extern rtx sh_get_fdpic_reg_initial_val (void);
    393 extern rtx sh_get_pr_initial_val (void);
    394 
    395 extern void sh_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree,
    396 				     signed int, machine_mode);
    397 extern rtx sh_dwarf_register_span (rtx);
    398 
    399 extern int shmedia_cleanup_truncate (rtx);
    400 
    401 extern bool sh_contains_memref_p (rtx);
    402 extern bool sh_loads_bankedreg_p (rtx);
    403 extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall);
    404 extern int sh2a_get_function_vector_number (rtx);
    405 extern bool sh2a_is_function_vector_call (rtx);
    406 extern void sh_fix_range (const char *);
    407 extern bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
    408 extern machine_mode sh_hard_regno_caller_save_mode (unsigned int, unsigned int,
    409 						    machine_mode);
    410 extern bool sh_can_use_simple_return_p (void);
    411 extern rtx sh_load_function_descriptor (rtx);
    412 #endif /* ! GCC_SH_PROTOS_H */
    413