]>
Commit | Line | Data |
---|---|---|
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 | }) |