1 ;; Predicate definitions for Renesas RX.
2 ;; Copyright (C) 2008, 2009 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 ;; Check that the operand is suitable as the source operand
49 ;; for a logic or arithmeitc instruction. Registers, integers
50 ;; and a restricted subset of memory addresses are allowed.
52 (define_predicate "rx_source_operand"
53 (match_code "const_int,reg,mem")
56 return rx_is_legitimate_constant (op);
61 /* Do not allow size conversions whilst accessing memory. */
62 if (GET_MODE (op) != mode)
65 return rx_is_restricted_memory_address (XEXP (op, 0), mode);
69 ;; Check that the operand is suitable as the source operand
70 ;; for a comparison instruction. This is the same as
71 ;; rx_source_operand except that SUBREGs are allowed but
72 ;; CONST_INTs are not.
74 (define_predicate "rx_compare_operand"
75 (match_code "subreg,reg,mem")
77 if (GET_CODE (op) == SUBREG)
78 return REG_P (XEXP (op, 0));
83 return rx_is_restricted_memory_address (XEXP (op, 0), mode);
87 ;; Return true if OP is a store multiple operation. This looks like:
89 ;; [(set (SP) (MINUS (SP) (INT)))
90 ;; (set (MEM (SP)) (REG))
91 ;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
94 (define_special_predicate "rx_store_multiple_vector"
95 (match_code "parallel")
97 int count = XVECLEN (op, 0);
98 unsigned int src_regno;
102 /* Perform a quick check so we don't blow up below. */
106 /* Check that the first element of the vector is the stack adjust. */
107 element = XVECEXP (op, 0, 0);
108 if ( ! SET_P (element)
109 || ! REG_P (SET_DEST (element))
110 || REGNO (SET_DEST (element)) != SP_REG
111 || GET_CODE (SET_SRC (element)) != MINUS
112 || ! REG_P (XEXP (SET_SRC (element), 0))
113 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
114 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
117 /* Check that the next element is the first push. */
118 element = XVECEXP (op, 0, 1);
119 if ( ! SET_P (element)
120 || ! REG_P (SET_SRC (element))
121 || GET_MODE (SET_SRC (element)) != SImode
122 || ! MEM_P (SET_DEST (element))
123 || GET_MODE (SET_DEST (element)) != SImode
124 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
125 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
126 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
127 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
128 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
129 != GET_MODE_SIZE (SImode))
132 src_regno = REGNO (SET_SRC (element));
134 /* Check that the remaining elements use SP-<disp>
135 addressing and decreasing register numbers. */
136 for (i = 2; i < count; i++)
138 element = XVECEXP (op, 0, i);
140 if ( ! SET_P (element)
141 || ! REG_P (SET_SRC (element))
142 || GET_MODE (SET_SRC (element)) != SImode
143 || REGNO (SET_SRC (element)) != src_regno - (i - 1)
144 || ! MEM_P (SET_DEST (element))
145 || GET_MODE (SET_DEST (element)) != SImode
146 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
147 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
148 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
149 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
150 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
151 != i * GET_MODE_SIZE (SImode))
157 ;; Return true if OP is a load multiple operation.
159 ;; [(set (SP) (PLUS (SP) (INT)))
160 ;; (set (REG) (MEM (SP)))
161 ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
164 (define_special_predicate "rx_load_multiple_vector"
165 (match_code "parallel")
167 int count = XVECLEN (op, 0);
168 unsigned int dest_regno;
172 /* Perform a quick check so we don't blow up below. */
176 /* Check that the first element of the vector is the stack adjust. */
177 element = XVECEXP (op, 0, 0);
178 if ( ! SET_P (element)
179 || ! REG_P (SET_DEST (element))
180 || REGNO (SET_DEST (element)) != SP_REG
181 || GET_CODE (SET_SRC (element)) != PLUS
182 || ! REG_P (XEXP (SET_SRC (element), 0))
183 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
184 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
187 /* Check that the next element is the first push. */
188 element = XVECEXP (op, 0, 1);
189 if ( ! SET_P (element)
190 || ! REG_P (SET_DEST (element))
191 || ! MEM_P (SET_SRC (element))
192 || ! REG_P (XEXP (SET_SRC (element), 0))
193 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
196 dest_regno = REGNO (SET_DEST (element));
198 /* Check that the remaining elements use SP+<disp>
199 addressing and incremental register numbers. */
200 for (i = 2; i < count; i++)
202 element = XVECEXP (op, 0, i);
204 if ( ! SET_P (element)
205 || ! REG_P (SET_DEST (element))
206 || GET_MODE (SET_DEST (element)) != SImode
207 || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
208 || ! MEM_P (SET_SRC (element))
209 || GET_MODE (SET_SRC (element)) != SImode
210 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
211 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
212 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
213 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
214 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
215 != (i - 1) * GET_MODE_SIZE (SImode))
221 ;; Return true if OP is a pop-and-return load multiple operation.
223 ;; [(set (SP) (PLUS (SP) (INT)))
224 ;; (set (REG) (MEM (SP)))
225 ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
229 (define_special_predicate "rx_rtsd_vector"
230 (match_code "parallel")
232 int count = XVECLEN (op, 0);
233 unsigned int dest_regno;
237 /* Perform a quick check so we don't blow up below. */
241 /* Check that the first element of the vector is the stack adjust. */
242 element = XVECEXP (op, 0, 0);
243 if ( ! SET_P (element)
244 || ! REG_P (SET_DEST (element))
245 || REGNO (SET_DEST (element)) != SP_REG
246 || GET_CODE (SET_SRC (element)) != PLUS
247 || ! REG_P (XEXP (SET_SRC (element), 0))
248 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
249 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
252 /* Check that the next element is the first push. */
253 element = XVECEXP (op, 0, 1);
254 if ( ! SET_P (element)
255 || ! REG_P (SET_DEST (element))
256 || ! MEM_P (SET_SRC (element))
257 || ! REG_P (XEXP (SET_SRC (element), 0))
258 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
261 dest_regno = REGNO (SET_DEST (element));
263 /* Check that the remaining elements, if any, and except
264 for the last one, use SP+<disp> addressing and incremental
266 for (i = 2; i < count - 1; i++)
268 element = XVECEXP (op, 0, i);
270 if ( ! SET_P (element)
271 || ! REG_P (SET_DEST (element))
272 || GET_MODE (SET_DEST (element)) != SImode
273 || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
274 || ! MEM_P (SET_SRC (element))
275 || GET_MODE (SET_SRC (element)) != SImode
276 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
277 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
278 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
279 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
280 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
281 != (i - 1) * GET_MODE_SIZE (SImode))
285 /* The last element must be a RETURN. */
286 element = XVECEXP (op, 0, count - 1);
287 return GET_CODE (element) == RETURN;