1 ;; Predicate definitions for Renesas RX.
2 ;; Copyright (C) 2008-2013 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 (ior (match_operand 0 "register_operand")
41 (and (match_code "const_int")
42 (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
45 (define_predicate "rx_constshift_operand"
46 (and (match_code "const_int")
47 (match_test "IN_RANGE (INTVAL (op), 0, 31)"))
50 (define_predicate "rx_restricted_mem_operand"
51 (and (match_code "mem")
52 (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)"))
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 (ior (match_operand 0 "register_operand")
61 (match_operand 0 "immediate_operand")
62 (match_operand 0 "rx_restricted_mem_operand"))
65 ;; Check that the operand is suitable as the source operand
66 ;; for a comparison instruction. This is the same as
67 ;; rx_source_operand except that SUBREGs are allowed but
68 ;; CONST_INTs are not.
70 (define_predicate "rx_compare_operand"
71 (ior (match_operand 0 "register_operand")
72 (match_operand 0 "rx_restricted_mem_operand"))
75 ;; Check that the operand is suitable as the source operand
76 ;; for a min/max instruction. This is the same as
77 ;; rx_source_operand except that CONST_INTs are allowed but
78 ;; REGs and SUBREGs are not.
80 (define_predicate "rx_minmaxex_operand"
81 (ior (match_operand 0 "immediate_operand")
82 (match_operand 0 "rx_restricted_mem_operand"))
85 ;; Return true if OP is a store multiple operation. This looks like:
87 ;; [(set (SP) (MINUS (SP) (INT)))
88 ;; (set (MEM (SP)) (REG))
89 ;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
92 (define_special_predicate "rx_store_multiple_vector"
93 (match_code "parallel")
95 int count = XVECLEN (op, 0);
96 unsigned int src_regno;
100 /* Perform a quick check so we don't blow up below. */
104 /* Check that the first element of the vector is the stack adjust. */
105 element = XVECEXP (op, 0, 0);
106 if ( ! SET_P (element)
107 || ! REG_P (SET_DEST (element))
108 || REGNO (SET_DEST (element)) != SP_REG
109 || GET_CODE (SET_SRC (element)) != MINUS
110 || ! REG_P (XEXP (SET_SRC (element), 0))
111 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
112 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
115 /* Check that the next element is the first push. */
116 element = XVECEXP (op, 0, 1);
117 if ( ! SET_P (element)
118 || ! REG_P (SET_SRC (element))
119 || GET_MODE (SET_SRC (element)) != SImode
120 || ! MEM_P (SET_DEST (element))
121 || GET_MODE (SET_DEST (element)) != SImode
122 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
123 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
124 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
125 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
126 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
127 != GET_MODE_SIZE (SImode))
130 src_regno = REGNO (SET_SRC (element));
132 /* Check that the remaining elements use SP-<disp>
133 addressing and decreasing register numbers. */
134 for (i = 2; i < count; i++)
136 element = XVECEXP (op, 0, i);
138 if ( ! SET_P (element)
139 || ! REG_P (SET_SRC (element))
140 || GET_MODE (SET_SRC (element)) != SImode
141 || REGNO (SET_SRC (element)) != src_regno - (i - 1)
142 || ! MEM_P (SET_DEST (element))
143 || GET_MODE (SET_DEST (element)) != SImode
144 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
145 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
146 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
147 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
148 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
149 != i * GET_MODE_SIZE (SImode))
155 ;; Return true if OP is a load multiple operation.
157 ;; [(set (SP) (PLUS (SP) (INT)))
158 ;; (set (REG) (MEM (SP)))
159 ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
162 (define_special_predicate "rx_load_multiple_vector"
163 (match_code "parallel")
165 int count = XVECLEN (op, 0);
166 unsigned int dest_regno;
170 /* Perform a quick check so we don't blow up below. */
174 /* Check that the first element of the vector is the stack adjust. */
175 element = XVECEXP (op, 0, 0);
176 if ( ! SET_P (element)
177 || ! REG_P (SET_DEST (element))
178 || REGNO (SET_DEST (element)) != SP_REG
179 || GET_CODE (SET_SRC (element)) != PLUS
180 || ! REG_P (XEXP (SET_SRC (element), 0))
181 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
182 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
185 /* Check that the next element is the first push. */
186 element = XVECEXP (op, 0, 1);
187 if ( ! SET_P (element)
188 || ! REG_P (SET_DEST (element))
189 || ! MEM_P (SET_SRC (element))
190 || ! REG_P (XEXP (SET_SRC (element), 0))
191 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
194 dest_regno = REGNO (SET_DEST (element));
196 /* Check that the remaining elements use SP+<disp>
197 addressing and incremental register numbers. */
198 for (i = 2; i < count; i++)
200 element = XVECEXP (op, 0, i);
202 if ( ! SET_P (element)
203 || ! REG_P (SET_DEST (element))
204 || GET_MODE (SET_DEST (element)) != SImode
205 || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
206 || ! MEM_P (SET_SRC (element))
207 || GET_MODE (SET_SRC (element)) != SImode
208 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
209 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
210 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
211 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
212 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
213 != (i - 1) * GET_MODE_SIZE (SImode))
219 ;; Return true if OP is a pop-and-return load multiple operation.
221 ;; [(set (SP) (PLUS (SP) (INT)))
222 ;; (set (REG) (MEM (SP)))
223 ;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
227 (define_special_predicate "rx_rtsd_vector"
228 (match_code "parallel")
230 int count = XVECLEN (op, 0);
231 unsigned int dest_regno;
235 /* Perform a quick check so we don't blow up below. */
239 /* Check that the first element of the vector is the stack adjust. */
240 element = XVECEXP (op, 0, 0);
241 if ( ! SET_P (element)
242 || ! REG_P (SET_DEST (element))
243 || REGNO (SET_DEST (element)) != SP_REG
244 || GET_CODE (SET_SRC (element)) != PLUS
245 || ! REG_P (XEXP (SET_SRC (element), 0))
246 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
247 || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
250 /* Check that the next element is the first push. */
251 element = XVECEXP (op, 0, 1);
252 if ( ! SET_P (element)
253 || ! REG_P (SET_DEST (element))
254 || ! MEM_P (SET_SRC (element))
255 || ! REG_P (XEXP (SET_SRC (element), 0))
256 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
259 dest_regno = REGNO (SET_DEST (element));
261 /* Check that the remaining elements, if any, and except
262 for the last one, use SP+<disp> addressing and incremental
264 for (i = 2; i < count - 1; i++)
266 element = XVECEXP (op, 0, i);
268 if ( ! SET_P (element)
269 || ! REG_P (SET_DEST (element))
270 || GET_MODE (SET_DEST (element)) != SImode
271 || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
272 || ! MEM_P (SET_SRC (element))
273 || GET_MODE (SET_SRC (element)) != SImode
274 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
275 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
276 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
277 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
278 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
279 != (i - 1) * GET_MODE_SIZE (SImode))
283 /* The last element must be a RETURN. */
284 element = XVECEXP (op, 0, count - 1);
285 return GET_CODE (element) == RETURN;
288 (define_predicate "label_ref_operand"
289 (match_code "label_ref")
292 (define_predicate "rx_z_comparison_operator"
296 (define_predicate "rx_zs_comparison_operator"
297 (match_code "eq,ne,lt,ge")
300 ;; GT and LE omitted due to operand swap required.
301 (define_predicate "rx_fp_comparison_operator"
302 (match_code "eq,ne,lt,ge,ordered,unordered")
305 (define_predicate "rshift_operator"
306 (match_code "ashiftrt,lshiftrt")