summaryrefslogtreecommitdiff
path: root/gcc/config/rx/rx-protos.h
blob: 7e9817cfaf7bf7f7974a2223ff8aa95a25ee2ea2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* Exported function prototypes from the Renesas RX backend.
   Copyright (C) 2008-2018 Free Software Foundation, Inc.
   Contributed by Red Hat.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   GCC is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  */

#ifndef GCC_RX_PROTOS_H
#define GCC_RX_PROTOS_H

extern bool             rx_can_use_simple_return (void);
extern void		rx_expand_epilogue (bool);
extern void		rx_expand_prologue (void);
extern int		rx_initial_elimination_offset (int, int);

bool is_interrupt_func (const_tree decl);
bool is_fast_interrupt_func (const_tree decl);

/* rx_atomic_sequence is used to emit the header and footer
   of an atomic sequence.  It's supposed to be used in a scope.
   When constructed, it will emit the atomic sequence header insns.
   When destructred (goes out of scope), it will emit the
   corresponding atomic sequence footer insns.  */
class rx_atomic_sequence
{
public:
  rx_atomic_sequence (const_tree fun_decl);
  ~rx_atomic_sequence (void);

private:
  rx_atomic_sequence (void);
  rx_atomic_sequence (const rx_atomic_sequence&);
  rx_atomic_sequence& operator = (const rx_atomic_sequence&);

  rtx m_prev_psw_reg;
};

#ifdef RTX_CODE
extern int		rx_adjust_insn_length (rtx_insn *, int);
extern align_flags	rx_align_for_label (rtx_insn *, int);
extern void             rx_emit_stack_popm (rtx *, bool);
extern void             rx_emit_stack_pushm (rtx *);
extern char *		rx_gen_move_template (rtx *, bool);
extern bool		rx_is_legitimate_constant (machine_mode, rtx);
extern bool		rx_is_restricted_memory_address (rtx,
							 machine_mode);
extern bool		rx_match_ccmode (rtx, machine_mode);
extern rtx		rx_maybe_pidify_operand (rtx, int);
extern void		rx_notice_update_cc (rtx, rtx);
extern void		rx_split_cbranch (machine_mode, enum rtx_code,
					  rtx, rtx, rtx);
extern machine_mode	rx_select_cc_mode (enum rtx_code, rtx, rtx);

extern bool rx_reg_dead_or_unused_after_insn (const rtx_insn* i, int regno);
extern void rx_copy_reg_dead_or_unused_notes (rtx reg, const rtx_insn* src,
					      rtx_insn* dst);

extern bool rx_fuse_in_memory_bitop (rtx* operands, rtx_insn* curr_insn,
				     rtx (*gen_insn)(rtx, rtx));

/* Result value of rx_find_set_of_reg.  */
struct set_of_reg
{
  /* The insn where sh_find_set_of_reg stopped looking.
     Can be NULL_RTX if the end of the insn list was reached.  */
  rtx_insn* insn;

  /* The set rtx of the specified reg if found, NULL_RTX otherwise.  */
  const_rtx set_rtx;

  /* The set source rtx of the specified reg if found, NULL_RTX otherwise.
     Usually, this is the most interesting return value.  */
  rtx set_src;
};

/* FIXME: Copy-pasta from SH.  Move to rtl.h.
   Given a reg rtx and a start insn, try to find the insn that sets
   the specified reg by using the specified insn stepping function,
   such as 'prev_nonnote_nondebug_insn_bb'.  When the insn is found,
   try to extract the rtx of the reg set.  */
template <typename F> inline set_of_reg
rx_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc,
		    bool ignore_reg_reg_copies = false)
{
  set_of_reg result;
  result.insn = insn;
  result.set_rtx = NULL_RTX;
  result.set_src = NULL_RTX;

  if (!REG_P (reg) || insn == NULL_RTX)
    return result;

  for (rtx_insn* i = stepfunc (insn); i != NULL_RTX; i = stepfunc (i))
    {
      if (BARRIER_P (i))
	break;
      if (!INSN_P (i) || DEBUG_INSN_P (i))
	  continue;
      if (reg_set_p (reg, i))
	{
	  if (CALL_P (i))
	    break;

	  result.insn = i;
	  result.set_rtx = set_of (reg, i);

	  if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
	    break;

	  result.set_src = XEXP (result.set_rtx, 1);

	  if (ignore_reg_reg_copies && REG_P (result.set_src))
	    {
	      reg = result.set_src;
	      continue;
	    }
	  if (ignore_reg_reg_copies && SUBREG_P (result.set_src)
	      && REG_P (SUBREG_REG (result.set_src)))
	    {
	      reg = SUBREG_REG (result.set_src);
	      continue;
	    }

	  break;
	}
    }

  /* If the searched reg is found inside a (mem (post_inc:SI (reg))), set_of
     will return NULL and set_rtx will be NULL.
     In this case report a 'not found'.  result.insn will always be non-null
     at this point, so no need to check it.  */
  if (result.set_src != NULL && result.set_rtx == NULL)
    result.set_src = NULL;

  return result;
}

/* FIXME: Move to rtlh.h.  */
template <typename F> inline rtx_insn*
rx_find_use_of_reg (rtx reg, rtx_insn* insn, F stepfunc)
{
  if (!REG_P (reg) || insn == NULL_RTX)
    return NULL;

  for (rtx_insn* i = stepfunc (insn); i != NULL_RTX; i = stepfunc (i))
    {
      if (BARRIER_P (i))
	break;
      if (!INSN_P (i) || DEBUG_INSN_P (i))
	continue;
      if (reg_overlap_mentioned_p (reg, PATTERN (i))
	  || (CALL_P (i) && find_reg_fusage (i, USE, reg)))
	return i;
    }

  return NULL;
}

#endif

#endif /* GCC_RX_PROTOS_H */