]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/rx/predicates.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / rx / predicates.md
CommitLineData
65a324b4 1;; Predicate definitions for Renesas RX.
8d9254fc 2;; Copyright (C) 2008-2020 Free Software Foundation, Inc.
65a324b4
NC
3;; Contributed by Red Hat.
4;;
5;; This file is part of GCC.
6;;
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)
10;; any later version.
11;;
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.
16;;
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/>.
20
21
22
23;; Check that the operand is suitable for a call insn.
24;; Only registers and symbol refs are allowed.
25
26(define_predicate "rx_call_operand"
eb457a8c
DD
27 (ior (match_code "reg")
28 (and (match_test "!TARGET_JSR")
29 (match_code "symbol_ref")))
65a324b4
NC
30)
31
32;; For sibcall operations we can only use a symbolic address.
33
34(define_predicate "rx_symbolic_call_operand"
35 (match_code "symbol_ref")
36)
37
38;; Check that the operand is suitable for a shift insn
39;; Only small integers or a value in a register are permitted.
40
41(define_predicate "rx_shift_operand"
8a5b5449
RH
42 (ior (match_operand 0 "register_operand")
43 (and (match_code "const_int")
44 (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
65a324b4
NC
45)
46
cf6521b4 47(define_predicate "rx_constshift_operand"
8a5b5449
RH
48 (and (match_code "const_int")
49 (match_test "IN_RANGE (INTVAL (op), 0, 31)"))
50)
51
52(define_predicate "rx_restricted_mem_operand"
53 (and (match_code "mem")
54 (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)"))
cf6521b4
DD
55)
56
65a324b4
NC
57;; Check that the operand is suitable as the source operand
58;; for a logic or arithmeitc instruction. Registers, integers
59;; and a restricted subset of memory addresses are allowed.
60
61(define_predicate "rx_source_operand"
8a5b5449
RH
62 (ior (match_operand 0 "register_operand")
63 (match_operand 0 "immediate_operand")
64 (match_operand 0 "rx_restricted_mem_operand"))
65a324b4
NC
65)
66
67;; Check that the operand is suitable as the source operand
68;; for a comparison instruction. This is the same as
69;; rx_source_operand except that SUBREGs are allowed but
70;; CONST_INTs are not.
71
72(define_predicate "rx_compare_operand"
8a5b5449
RH
73 (ior (match_operand 0 "register_operand")
74 (match_operand 0 "rx_restricted_mem_operand"))
65a324b4
NC
75)
76
783465f8
NC
77;; Check that the operand is suitable as the source operand
78;; for a min/max instruction. This is the same as
79;; rx_source_operand except that CONST_INTs are allowed but
80;; REGs and SUBREGs are not.
81
82(define_predicate "rx_minmaxex_operand"
83 (ior (match_operand 0 "immediate_operand")
84 (match_operand 0 "rx_restricted_mem_operand"))
85)
86
65a324b4
NC
87;; Return true if OP is a store multiple operation. This looks like:
88;;
89;; [(set (SP) (MINUS (SP) (INT)))
90;; (set (MEM (SP)) (REG))
91;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
92;; ]
93
94(define_special_predicate "rx_store_multiple_vector"
95 (match_code "parallel")
96{
97 int count = XVECLEN (op, 0);
98 unsigned int src_regno;
99 rtx element;
100 int i;
101
102 /* Perform a quick check so we don't blow up below. */
103 if (count <= 2)
104 return false;
105
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)))
115 return false;
116
117 /* Check that the next element is the first push. */
118 element = XVECEXP (op, 0, 1);
119 if ( ! SET_P (element)
9595a419
NC
120 || ! REG_P (SET_SRC (element))
121 || GET_MODE (SET_SRC (element)) != SImode
65a324b4 122 || ! MEM_P (SET_DEST (element))
9595a419
NC
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))
65a324b4
NC
130 return false;
131
132 src_regno = REGNO (SET_SRC (element));
133
134 /* Check that the remaining elements use SP-<disp>
9595a419 135 addressing and decreasing register numbers. */
65a324b4
NC
136 for (i = 2; i < count; i++)
137 {
138 element = XVECEXP (op, 0, i);
139
140 if ( ! SET_P (element)
141 || ! REG_P (SET_SRC (element))
142 || GET_MODE (SET_SRC (element)) != SImode
9595a419 143 || REGNO (SET_SRC (element)) != src_regno - (i - 1)
65a324b4
NC
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))
9595a419 151 != i * GET_MODE_SIZE (SImode))
65a324b4
NC
152 return false;
153 }
154 return true;
155})
156
157;; Return true if OP is a load multiple operation.
158;; This looks like:
159;; [(set (SP) (PLUS (SP) (INT)))
160;; (set (REG) (MEM (SP)))
161;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
162;; ]
163
164(define_special_predicate "rx_load_multiple_vector"
165 (match_code "parallel")
166{
167 int count = XVECLEN (op, 0);
168 unsigned int dest_regno;
169 rtx element;
170 int i;
171
172 /* Perform a quick check so we don't blow up below. */
173 if (count <= 2)
174 return false;
175
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)))
185 return false;
186
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)
194 return false;
195
196 dest_regno = REGNO (SET_DEST (element));
197
198 /* Check that the remaining elements use SP+<disp>
199 addressing and incremental register numbers. */
200 for (i = 2; i < count; i++)
201 {
202 element = XVECEXP (op, 0, i);
203
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))
216 return false;
217 }
218 return true;
219})
220
221;; Return true if OP is a pop-and-return load multiple operation.
222;; This looks like:
223;; [(set (SP) (PLUS (SP) (INT)))
224;; (set (REG) (MEM (SP)))
225;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
226;; (return)
227;; ]
228
229(define_special_predicate "rx_rtsd_vector"
230 (match_code "parallel")
231{
232 int count = XVECLEN (op, 0);
233 unsigned int dest_regno;
234 rtx element;
235 int i;
236
237 /* Perform a quick check so we don't blow up below. */
238 if (count <= 2)
239 return false;
240
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)))
250 return false;
251
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)
259 return false;
260
261 dest_regno = REGNO (SET_DEST (element));
262
263 /* Check that the remaining elements, if any, and except
264 for the last one, use SP+<disp> addressing and incremental
265 register numbers. */
266 for (i = 2; i < count - 1; i++)
267 {
268 element = XVECEXP (op, 0, i);
269
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))
282 return false;
283 }
284
285 /* The last element must be a RETURN. */
286 element = XVECEXP (op, 0, count - 1);
287 return GET_CODE (element) == RETURN;
288})
e963cb1a
RH
289
290(define_predicate "label_ref_operand"
291 (match_code "label_ref")
292)
293
294(define_predicate "rx_z_comparison_operator"
295 (match_code "eq,ne")
296)
297
298(define_predicate "rx_zs_comparison_operator"
72602cd1 299 (match_code "eq,ne,lt,ge")
e963cb1a
RH
300)
301
440eb8de 302;; GT and LE omitted due to operand swap required.
e963cb1a 303(define_predicate "rx_fp_comparison_operator"
440eb8de 304 (match_code "eq,ne,lt,ge,ordered,unordered")
e963cb1a 305)
f033541c
RH
306
307(define_predicate "rshift_operator"
308 (match_code "ashiftrt,lshiftrt")
309)