1 ;; Predicate definitions for Renesas RX.
2 ;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat.
5 ;; This file is part of GCC.
7 ;; GCC 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)
12 ;; GCC 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.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
23 ;; Check that the operand is suitable for a call insn.
24 ;; Only registers and symbol refs are allowed.
26 (define_predicate "rx_call_operand"
27 (match_code "symbol_ref,reg")
30 ;; For sibcall operations we can only use a symbolic address.
32 (define_predicate "rx_symbolic_call_operand"
33 (match_code "symbol_ref")
36 ;; Check that the operand is suitable for a shift insn
37 ;; Only small integers or a value in a register are permitted.
39 (define_predicate "rx_shift_operand"
40 (match_code "const_int,reg")
43 return IN_RANGE (INTVAL (op), 0, 31);
48 (define_predicate "rx_constshift_operand"
49 (match_code "const_int")
51 return IN_RANGE (INTVAL (op), 0, 31);
55 ;; Check that the operand is suitable as the source operand
56 ;; for a logic or arithmeitc instruction. Registers, integers
57 ;; and a restricted subset of memory addresses are allowed.
59 (define_predicate "rx_source_operand"
60 (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem")
63 return rx_is_legitimate_constant (op);
68 /* Do not allow size conversions whilst accessing memory. */
69 if (GET_MODE (op) != mode)
72 return rx_is_restricted_memory_address (XEXP (op, 0), mode);
76 ;; Check that the operand is suitable as the source operand
77 ;; for a comparison instruction. This is the same as
78 ;; rx_source_operand except that SUBREGs are allowed but
79 ;; CONST_INTs are not.
81 (define_predicate "rx_compare_operand"
82 (match_code "subreg,reg,mem")
84 if (GET_CODE (op) == SUBREG)
85 return REG_P (XEXP (op, 0));
90 return rx_is_restricted_memory_address (XEXP (op, 0), mode);
94 ;; Return true if OP is a store multiple operation. This looks like:
96 ;; [(set (SP) (MINUS (SP) (INT)))
97 ;; (set (MEM (SP)) (REG))
98 ;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
101 (define_special_predicate "rx_store_multiple_vector"
102 (match_code "parallel")
104 int count = XVECLEN (op, 0);
105 unsigned int src_regno;
109 /* Perform a quick check so we don't blow up below. */
113 /* Check that the first element of the vector is the stack adjust. */
114 element = XVECEXP (op, 0, 0);
115 if ( ! SET_P (element)
116 || ! REG_P (SET_DEST (element))
117 || REGNO (SET_DEST (element)) != SP_REG
118 || GET_CODE (SET_SRC (element)) != MINUS
119 || ! REG_P (XEXP (SET_SRC (element), 0))
120 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
121 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
124 /* Check that the next element is the first push. */
125 element = XVECEXP (op, 0, 1);
126 if ( ! SET_P (element)
127 || ! REG_P (SET_SRC (element))
128 || GET_MODE (SET_SRC (element)) != SImode
129 || ! MEM_P (SET_DEST (element))
130 || GET_MODE (SET_DEST (element)) != SImode
131 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
132 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
133 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
134 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
135 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
136 != GET_MODE_SIZE (SImode))
139 src_regno = REGNO (SET_SRC (element));
141 /* Check that the remaining elements use SP-<disp>
142 addressing and decreasing register numbers. */
143 for (i = 2; i < count; i++)
145 element = XVECEXP (op, 0, i);
147 if ( ! SET_P (element)
148 || ! REG_P (SET_SRC (element))
149 || GET_MODE (SET_SRC (element)) != SImode
150 || REGNO (SET_SRC (element)) != src_regno - (i - 1)
151 || ! MEM_P (SET_DEST (element))
152 || GET_MODE (SET_DEST (element)) != SImode
153 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
154 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
155 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
156 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
157 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
158 != i * GET_MODE_SIZE (SImode))
164 ;; Return true if OP is a load multiple operation.
166 ;; [(set (SP) (PLUS (SP) (INT)))
167 ;; (set (REG) (MEM (SP)))
168 ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
171 (define_special_predicate "rx_load_multiple_vector"
172 (match_code "parallel")
174 int count = XVECLEN (op, 0);
175 unsigned int dest_regno;
179 /* Perform a quick check so we don't blow up below. */
183 /* Check that the first element of the vector is the stack adjust. */
184 element = XVECEXP (op, 0, 0);
185 if ( ! SET_P (element)
186 || ! REG_P (SET_DEST (element))
187 || REGNO (SET_DEST (element)) != SP_REG
188 || GET_CODE (SET_SRC (element)) != PLUS
189 || ! REG_P (XEXP (SET_SRC (element), 0))
190 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
191 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
194 /* Check that the next element is the first push. */
195 element = XVECEXP (op, 0, 1);
196 if ( ! SET_P (element)
197 || ! REG_P (SET_DEST (element))
198 || ! MEM_P (SET_SRC (element))
199 || ! REG_P (XEXP (SET_SRC (element), 0))
200 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
203 dest_regno = REGNO (SET_DEST (element));
205 /* Check that the remaining elements use SP+<disp>
206 addressing and incremental register numbers. */
207 for (i = 2; i < count; i++)
209 element = XVECEXP (op, 0, i);
211 if ( ! SET_P (element)
212 || ! REG_P (SET_DEST (element))
213 || GET_MODE (SET_DEST (element)) != SImode
214 || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
215 || ! MEM_P (SET_SRC (element))
216 || GET_MODE (SET_SRC (element)) != SImode
217 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
218 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
219 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
220 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
221 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
222 != (i - 1) * GET_MODE_SIZE (SImode))
228 ;; Return true if OP is a pop-and-return load multiple operation.
230 ;; [(set (SP) (PLUS (SP) (INT)))
231 ;; (set (REG) (MEM (SP)))
232 ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
236 (define_special_predicate "rx_rtsd_vector"
237 (match_code "parallel")
239 int count = XVECLEN (op, 0);
240 unsigned int dest_regno;
244 /* Perform a quick check so we don't blow up below. */
248 /* Check that the first element of the vector is the stack adjust. */
249 element = XVECEXP (op, 0, 0);
250 if ( ! SET_P (element)
251 || ! REG_P (SET_DEST (element))
252 || REGNO (SET_DEST (element)) != SP_REG
253 || GET_CODE (SET_SRC (element)) != PLUS
254 || ! REG_P (XEXP (SET_SRC (element), 0))
255 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
256 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
259 /* Check that the next element is the first push. */
260 element = XVECEXP (op, 0, 1);
261 if ( ! SET_P (element)
262 || ! REG_P (SET_DEST (element))
263 || ! MEM_P (SET_SRC (element))
264 || ! REG_P (XEXP (SET_SRC (element), 0))
265 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
268 dest_regno = REGNO (SET_DEST (element));
270 /* Check that the remaining elements, if any, and except
271 for the last one, use SP+<disp> addressing and incremental
273 for (i = 2; i < count - 1; i++)
275 element = XVECEXP (op, 0, i);
277 if ( ! SET_P (element)
278 || ! REG_P (SET_DEST (element))
279 || GET_MODE (SET_DEST (element)) != SImode
280 || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
281 || ! MEM_P (SET_SRC (element))
282 || GET_MODE (SET_SRC (element)) != SImode
283 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
284 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
285 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
286 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
287 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
288 != (i - 1) * GET_MODE_SIZE (SImode))
292 /* The last element must be a RETURN. */
293 element = XVECEXP (op, 0, count - 1);
294 return GET_CODE (element) == RETURN;