]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pru/predicates.md
pru: Fix register class checks in predicates
[thirdparty/gcc.git] / gcc / config / pru / predicates.md
CommitLineData
8d2af3a2 1;; Predicate definitions for TI PRU.
a945c346 2;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
8d2af3a2
DD
3;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
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(define_predicate "const_1_operand"
22 (and (match_code "const_int")
23 (match_test "INTVAL (op) == 1")))
24
ee077d0c
DD
25(define_predicate "const_0_operand"
26 (and (match_code "const_int")
27 (match_test "INTVAL (op) == 0")))
28
8d2af3a2
DD
29; Note: Always pass a valid mode!
30(define_predicate "const_ubyte_operand"
31 (match_code "const_int")
32{
33 gcc_assert (mode != VOIDmode);
34 return IN_RANGE (INTVAL (op) & GET_MODE_MASK (mode), 0, 0xff);
35})
36
37(define_predicate "const_uhword_operand"
38 (match_code "const_int")
39{
40 gcc_assert (mode != VOIDmode);
41 return IN_RANGE (INTVAL (op) & GET_MODE_MASK (mode), 0, 0xffff);
42})
43
44; TRUE for comparisons we support.
45(define_predicate "pru_cmp_operator"
46 (match_code "eq,ne,leu,ltu,geu,gtu"))
47
48; TRUE for signed comparisons that need special handling for PRU.
49(define_predicate "pru_signed_cmp_operator"
50 (match_code "ge,gt,le,lt"))
51
52;; FP Comparisons handled by pru_expand_pru_compare.
53(define_predicate "pru_fp_comparison_operator"
54 (match_code "eq,ne,lt,gt,le,ge"))
55
ee077d0c
DD
56;; TRUE for comparisons supported by PRU's cstore.
57(define_predicate "pru_cstore_comparison_operator"
58 (match_code "eq,ne,gtu"))
59
8d2af3a2
DD
60;; Return true if OP is a constant that contains only one 1 in its
61;; binary representation.
62(define_predicate "single_one_operand"
63 (and (match_code "const_int")
64 (match_test "exact_log2 (INTVAL (op) & GET_MODE_MASK (mode)) >= 0")))
65
66;; Return true if OP is a constant that contains only one 0 in its
67;; binary representation.
68(define_predicate "single_zero_operand"
69 (and (match_code "const_int")
70 (match_test "exact_log2 (~INTVAL (op) & GET_MODE_MASK (mode)) >= 0")))
71
72(define_predicate "pru_muldst_operand"
73 (match_code "subreg,reg")
74{
75 if (register_operand (op, mode))
76 {
77 int regno;
78
79 if (REG_P (op))
80 regno = REGNO (op);
81 else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
82 regno = REGNO (SUBREG_REG (op));
83 else
84 return 0;
85
86 return REGNO_REG_CLASS (regno) == MULDST_REGS
87 || regno >= FIRST_PSEUDO_REGISTER;
88 }
89 return 0;
90})
91
92(define_predicate "pru_mulsrc0_operand"
93 (match_code "subreg,reg")
94{
95 if (register_operand (op, mode))
96 {
97 int regno;
98
99 if (REG_P (op))
100 regno = REGNO (op);
101 else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
102 regno = REGNO (SUBREG_REG (op));
103 else
104 return 0;
105
d4d30461 106 return REGNO_REG_CLASS (regno) == MULSRC0_REGS
8d2af3a2
DD
107 || regno >= FIRST_PSEUDO_REGISTER;
108 }
109 return 0;
110})
111
112(define_predicate "pru_mulsrc1_operand"
113 (match_code "subreg,reg")
114{
115 if (register_operand (op, mode))
116 {
117 int regno;
118
119 if (REG_P (op))
120 regno = REGNO (op);
121 else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
122 regno = REGNO (SUBREG_REG (op));
123 else
124 return 0;
125
d4d30461 126 return REGNO_REG_CLASS (regno) == MULSRC1_REGS
8d2af3a2
DD
127 || regno >= FIRST_PSEUDO_REGISTER;
128 }
129 return 0;
130})
131
8bafc964
DD
132(define_predicate "regio_operand"
133 (match_code "subreg,reg")
134{
135 if (register_operand (op, mode))
136 {
137 int regno;
138
139 if (REG_P (op))
140 regno = REGNO (op);
141 else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
142 regno = REGNO (SUBREG_REG (op));
143 else
144 return 0;
145
146 return REGNO_REG_CLASS (regno) == REGIO_REGS;
147 }
148 return 0;
149})
150
8d2af3a2
DD
151(define_predicate "reg_or_const_int_operand"
152 (ior (match_operand 0 "const_int_operand")
153 (match_operand 0 "register_operand")))
154
155(define_predicate "reg_or_ubyte_operand"
156 (ior (match_operand 0 "const_ubyte_operand")
157 (match_operand 0 "register_operand")))
158
159(define_predicate "reg_or_const_1_operand"
160 (ior (match_operand 0 "const_1_operand")
161 (match_operand 0 "register_operand")))
162
163(define_predicate "const_shift_operand"
164 (and (match_code "const_int")
165 (match_test "SHIFT_INT (INTVAL (op))")))
166
167(define_predicate "shift_operand"
168 (ior (match_operand 0 "const_shift_operand")
169 (match_operand 0 "register_operand")))
170
171(define_predicate "ctable_addr_operand"
172 (and (match_code "const_int")
173 (match_test "pru_get_ctable_base_index (INTVAL (op)) >= 0")))
174
175(define_predicate "ctable_base_operand"
176 (and (match_code "const_int")
177 (match_test "pru_get_ctable_exact_base_index (INTVAL (op)) >= 0")))
178
179;; Ideally we should enforce a restriction to all text labels to fit in
180;; 16bits, as required by the PRU ISA. But for the time being we'll rely on
181;; binutils to catch text segment overflows.
182(define_predicate "call_operand"
183 (ior (match_operand 0 "immediate_operand")
184 (match_operand 0 "register_operand")))
185
186;; Return true if OP is a text segment reference.
187;; This is needed for program memory address expressions. Borrowed from AVR.
188(define_predicate "text_segment_operand"
189 (match_code "code_label,label_ref,symbol_ref,plus,minus")
190{
191 poly_int64 offset;
192 rtx base = strip_offset (op, &offset);
193
194 switch (GET_CODE (base))
195 {
196 case CODE_LABEL:
197 /* Why AVR lists this as a valid option? Let's catch it. */
198 gcc_unreachable ();
199 return false;
200 case LABEL_REF:
201 return true;
202 case SYMBOL_REF:
203 return SYMBOL_REF_FUNCTION_P (base);
204 case PLUS:
205 case MINUS:
206 /* Handle constructs like (&&label1 - &&label2). See pr70460.c. */
207 return text_segment_operand (XEXP (op, 0), VOIDmode);
208 default:
209 return false;
210 }
211})
212
213;; Return true if OP is a load multiple operation. It is known to be a
214;; PARALLEL and the first section will be tested.
215
216(define_special_predicate "load_multiple_operation"
217 (match_code "parallel")
218{
219 machine_mode elt_mode;
220 int count = XVECLEN (op, 0);
221 unsigned int dest_regno;
222 rtx src_addr, base_reg;
223 poly_int64 base_offs;
224 int i;
225
226 /* Perform a quick check so we don't blow up below. */
227 if (GET_CODE (XVECEXP (op, 0, 0)) != SET
228 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
229 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
230 return false;
231
232 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
233 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
234 elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
235
236 base_reg = strip_offset (src_addr, &base_offs);
237 if (GET_CODE (base_reg) != REG)
238 return false;
239
240 for (i = 1; i < count; i++)
241 {
242 rtx elt_reg;
243 poly_int64 elt_offs;
244 rtx elt = XVECEXP (op, 0, i);
245
246 if (GET_CODE (elt) != SET
247 || GET_CODE (SET_DEST (elt)) != REG
248 || GET_MODE (SET_DEST (elt)) != elt_mode
249 || REGNO (SET_DEST (elt)) != dest_regno + i * GET_MODE_SIZE (elt_mode)
250 || GET_CODE (SET_SRC (elt)) != MEM
251 || GET_MODE (SET_SRC (elt)) != elt_mode)
252 return false;
253
254 elt_reg = strip_offset (XEXP (SET_SRC (elt), 0), &elt_offs);
255
256 if (GET_CODE (elt_reg) != REG
257 || ! rtx_equal_p (elt_reg, base_reg)
258 || elt_offs != base_offs + i * GET_MODE_SIZE (elt_mode))
259 return false;
260 }
261
262 return true;
263})
264
265;; Return true if OP is a store multiple operation. It is known to be a
266;; PARALLEL and the first section will be tested.
267
268(define_special_predicate "store_multiple_operation"
269 (match_code "parallel")
270{
271 machine_mode elt_mode;
272 int count = XVECLEN (op, 0);
273 unsigned int src_regno;
274 rtx dest_addr, base_reg;
275 poly_int64 base_offs;
276 int i;
277
278 /* Perform a quick check so we don't blow up below. */
279 if (GET_CODE (XVECEXP (op, 0, 0)) != SET
280 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
281 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
282 return false;
283
284 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
285 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
286 elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
287
288 base_reg = strip_offset (dest_addr, &base_offs);
289 if (GET_CODE (base_reg) != REG)
290 return false;
291
292 for (i = 1; i < count; i++)
293 {
294 rtx elt_reg;
295 poly_int64 elt_offs;
296 rtx elt = XVECEXP (op, 0, i);
297
298 if (GET_CODE (elt) != SET
299 || GET_CODE (SET_SRC (elt)) != REG
300 || GET_MODE (SET_SRC (elt)) != elt_mode
301 || REGNO (SET_SRC (elt)) != src_regno + i * GET_MODE_SIZE (elt_mode)
302 || GET_CODE (SET_DEST (elt)) != MEM
303 || GET_MODE (SET_DEST (elt)) != elt_mode)
304 return false;
305
306 elt_reg = strip_offset (XEXP (SET_DEST (elt), 0), &elt_offs);
307
308 if (GET_CODE (elt_reg) != REG
309 || ! rtx_equal_p (elt_reg, base_reg)
310 || elt_offs != base_offs + i * GET_MODE_SIZE (elt_mode))
311 return false;
312 }
313 return true;
314})
10dd6dea
DD
315
316;; Return true if OP is a constant integer with one single consecutive
317;; range of bytes with value 0xff, and the rest of the bytes are 0x00.
318(define_predicate "const_fillbytes_operand"
319 (match_code "const_int")
320{
321 gcc_assert (mode != VOIDmode);
322
323 pru_byterange r = pru_calc_byterange (INTVAL (op), mode);
324 return r.start >=0 && r.nbytes > 0;
325})
326
327;; Return true if OP is a constant integer with one single consecutive
328;; range of bytes with value 0x00, and the rest of the bytes are 0xff.
329(define_predicate "const_zerobytes_operand"
330 (match_code "const_int")
331{
332 gcc_assert (mode != VOIDmode);
333
334 pru_byterange r = pru_calc_byterange (~INTVAL (op), mode);
335 return r.start >=0 && r.nbytes > 0;
336})