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