]>
Commit | Line | Data |
---|---|---|
0bfc3f69 | 1 | ;; Predicate definitions for S/390 and zSeries. |
7adcbafe | 2 | ;; Copyright (C) 2005-2022 Free Software Foundation, Inc. |
0bfc3f69 AS |
3 | ;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and |
4 | ;; Ulrich Weigand (uweigand@de.ibm.com). | |
5 | ;; | |
6 | ;; This file is part of GCC. | |
7 | ;; | |
8 | ;; GCC is free software; you can redistribute it and/or modify | |
9 | ;; it under the terms of the GNU General Public License as published by | |
2f83c7d6 | 10 | ;; the Free Software Foundation; either version 3, or (at your option) |
0bfc3f69 AS |
11 | ;; any later version. |
12 | ;; | |
13 | ;; GCC is distributed in the hope that it will be useful, | |
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ;; GNU General Public License for more details. | |
17 | ;; | |
18 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
19 | ;; along with GCC; see the file COPYING3. If not see |
20 | ;; <http://www.gnu.org/licenses/>. | |
0bfc3f69 AS |
21 | |
22 | ;; OP is the current operation. | |
23 | ;; MODE is the current operation mode. | |
24 | ||
25 | ;; operands -------------------------------------------------------------- | |
26 | ||
085261c8 | 27 | ;; Return true if OP a const 0 operand (int/float/vector). |
0bfc3f69 | 28 | (define_predicate "const0_operand" |
089b05b1 | 29 | (and (match_code "const_int,const_wide_int,const_double,const_vector") |
0bfc3f69 AS |
30 | (match_test "op == CONST0_RTX (mode)"))) |
31 | ||
916c0f6a RD |
32 | ;; Return true if OP an all ones operand (int/vector). |
33 | (define_predicate "all_ones_operand" | |
34 | (and (match_code "const_int, const_wide_int, const_vector") | |
35 | (match_test "INTEGRAL_MODE_P (GET_MODE (op))") | |
085261c8 AK |
36 | (match_test "op == CONSTM1_RTX (mode)"))) |
37 | ||
e970b4b0 AK |
38 | ;; Return true if OP is a 4 bit mask operand |
39 | (define_predicate "const_mask_operand" | |
40 | (and (match_code "const_int") | |
41 | (match_test "UINTVAL (op) < 16"))) | |
42 | ||
0bfc3f69 AS |
43 | ;; Return true if OP is constant. |
44 | ||
45 | (define_special_predicate "consttable_operand" | |
089b05b1 | 46 | (and (match_code "symbol_ref, label_ref, const, const_int, const_wide_int, const_double, const_vector") |
0bfc3f69 AS |
47 | (match_test "CONSTANT_P (op)"))) |
48 | ||
2541c40f AK |
49 | ; An operand used as vector permutation pattern |
50 | ||
51 | ; This in particular accepts constants which would otherwise be | |
52 | ; rejected. These constants require special post reload handling | |
53 | ||
54 | (define_special_predicate "permute_pattern_operand" | |
55 | (and (match_code "const_vector,mem,reg,subreg") | |
56 | (match_test "GET_MODE (op) == V16QImode") | |
57 | (match_test "!MEM_P (op) || s390_mem_constraint (\"R\", op)"))) | |
58 | ||
0bfc3f69 AS |
59 | ;; Return true if OP is a valid S-type operand. |
60 | ||
61 | (define_predicate "s_operand" | |
62 | (and (match_code "subreg, mem") | |
63 | (match_operand 0 "general_operand")) | |
64 | { | |
65 | /* Just like memory_operand, allow (subreg (mem ...)) | |
66 | after reload. */ | |
67 | if (reload_completed | |
68 | && GET_CODE (op) == SUBREG | |
69 | && GET_CODE (SUBREG_REG (op)) == MEM) | |
70 | op = SUBREG_REG (op); | |
71 | ||
72 | if (GET_CODE (op) != MEM) | |
73 | return false; | |
74 | if (!s390_legitimate_address_without_index_p (op)) | |
75 | return false; | |
76 | ||
77 | return true; | |
78 | }) | |
79 | ||
f9dcf14a AK |
80 | ;; Return true of the address of the mem operand plus 16 is still a |
81 | ;; valid Q constraint address. | |
82 | ||
83 | (define_predicate "plus16_Q_operand" | |
84 | (and (match_code "mem") | |
85 | (match_operand 0 "general_operand")) | |
86 | { | |
87 | rtx addr = XEXP (op, 0); | |
88 | if (REG_P (addr)) | |
89 | return true; | |
90 | ||
91 | if (GET_CODE (addr) != PLUS | |
92 | || !REG_P (XEXP (addr, 0)) | |
93 | || !CONST_INT_P (XEXP (addr, 1))) | |
94 | return false; | |
95 | ||
96 | return SHORT_DISP_IN_RANGE (INTVAL (XEXP (addr, 1)) + 16); | |
97 | }) | |
98 | ||
0bfc3f69 AS |
99 | ;; Return true if OP is a valid operand for the BRAS instruction. |
100 | ;; Allow SYMBOL_REFs and @PLT stubs. | |
101 | ||
102 | (define_special_predicate "bras_sym_operand" | |
6915c1ce | 103 | (ior (and (match_code "symbol_ref") |
0990d93d IL |
104 | (ior (match_test "!flag_pic") |
105 | (match_test "SYMBOL_REF_LOCAL_P (op)") | |
106 | (and (match_test "TARGET_64BIT") | |
107 | (match_test "SYMBOL_REF_FUNCTION_P (op)")))) | |
0bfc3f69 AS |
108 | (and (match_code "const") |
109 | (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC") | |
0990d93d | 110 | (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT31"))))) |
0bfc3f69 AS |
111 | |
112 | ;; Return true if OP is a PLUS that is not a legitimate | |
113 | ;; operand for the LA instruction. | |
114 | ||
115 | (define_predicate "s390_plus_operand" | |
116 | (and (match_code "plus") | |
117 | (and (match_test "mode == Pmode") | |
118 | (match_test "!legitimate_la_operand_p (op)")))) | |
119 | ||
9e8ea2fc | 120 | ;; Return true if OP is a valid operand as scalar shift count or setmem. |
f83a336d | 121 | |
dd95128b | 122 | (define_predicate "setmem_operand" |
f83a336d AK |
123 | (match_code "reg, subreg, plus, const_int") |
124 | { | |
d98ad410 UW |
125 | HOST_WIDE_INT offset; |
126 | rtx base; | |
127 | ||
9e8ea2fc AK |
128 | if (GET_MODE (op) != VOIDmode |
129 | && GET_MODE_CLASS (GET_MODE (op)) != MODE_INT) | |
130 | return false; | |
131 | ||
4989e88a | 132 | /* Extract base register and offset. */ |
dd95128b | 133 | if (!s390_decompose_addrstyle_without_index (op, &base, &offset)) |
0bfc3f69 AS |
134 | return false; |
135 | ||
d98ad410 UW |
136 | /* Don't allow any non-base hard registers. Doing so without |
137 | confusing reload and/or regrename would be tricky, and doesn't | |
138 | buy us much anyway. */ | |
139 | if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base)) | |
db21e1d0 AK |
140 | return false; |
141 | ||
0bfc3f69 AS |
142 | /* Unfortunately we have to reject constants that are invalid |
143 | for an address, or else reload will get confused. */ | |
144 | if (!DISP_IN_RANGE (offset)) | |
145 | return false; | |
146 | ||
147 | return true; | |
148 | }) | |
149 | ||
191eb16d AK |
150 | ; An integer operand with the lowest order 6 bits all ones. |
151 | (define_predicate "const_int_6bitset_operand" | |
152 | (and (match_code "const_int") | |
153 | (match_test "(INTVAL (op) & 63) == 63"))) | |
1a2e356e RH |
154 | (define_predicate "nonzero_shift_count_operand" |
155 | (and (match_code "const_int") | |
156 | (match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)"))) | |
157 | ||
0bfc3f69 AS |
158 | ;; Return true if OP a valid operand for the LARL instruction. |
159 | ||
160 | (define_predicate "larl_operand" | |
986e29bc | 161 | (match_code "label_ref, symbol_ref, const") |
0bfc3f69 AS |
162 | { |
163 | /* Allow labels and local symbols. */ | |
164 | if (GET_CODE (op) == LABEL_REF) | |
165 | return true; | |
935b5226 | 166 | if (SYMBOL_REF_P (op)) |
e63d44c2 | 167 | return (!SYMBOL_FLAG_NOTALIGN2_P (op) |
0bfc3f69 | 168 | && SYMBOL_REF_TLS_MODEL (op) == 0 |
935b5226 | 169 | && s390_rel_address_ok_p (op)); |
0bfc3f69 AS |
170 | |
171 | /* Everything else must have a CONST, so strip it. */ | |
172 | if (GET_CODE (op) != CONST) | |
173 | return false; | |
174 | op = XEXP (op, 0); | |
175 | ||
176 | /* Allow adding *even* in-range constants. */ | |
177 | if (GET_CODE (op) == PLUS) | |
178 | { | |
179 | if (GET_CODE (XEXP (op, 1)) != CONST_INT | |
180 | || (INTVAL (XEXP (op, 1)) & 1) != 0) | |
181 | return false; | |
406fde6e DV |
182 | if (INTVAL (XEXP (op, 1)) >= HOST_WIDE_INT_1 << 31 |
183 | || INTVAL (XEXP (op, 1)) < -(HOST_WIDE_INT_1 << 31)) | |
0bfc3f69 AS |
184 | return false; |
185 | op = XEXP (op, 0); | |
186 | } | |
187 | ||
188 | /* Labels and local symbols allowed here as well. */ | |
189 | if (GET_CODE (op) == LABEL_REF) | |
190 | return true; | |
935b5226 | 191 | if (SYMBOL_REF_P (op)) |
e63d44c2 | 192 | return (!SYMBOL_FLAG_NOTALIGN2_P (op) |
0bfc3f69 | 193 | && SYMBOL_REF_TLS_MODEL (op) == 0 |
935b5226 AK |
194 | && s390_rel_address_ok_p (op)); |
195 | ||
0bfc3f69 AS |
196 | |
197 | /* Now we must have a @GOTENT offset or @PLT stub | |
198 | or an @INDNTPOFF TLS offset. */ | |
199 | if (GET_CODE (op) == UNSPEC | |
200 | && XINT (op, 1) == UNSPEC_GOTENT) | |
201 | return true; | |
202 | if (GET_CODE (op) == UNSPEC | |
0990d93d | 203 | && XINT (op, 1) == UNSPEC_PLT31) |
0bfc3f69 AS |
204 | return true; |
205 | if (GET_CODE (op) == UNSPEC | |
206 | && XINT (op, 1) == UNSPEC_INDNTPOFF) | |
207 | return true; | |
208 | ||
209 | return false; | |
210 | }) | |
211 | ||
c2586c82 | 212 | ; Predicate that always allows wraparound of the one-bit range. |
75ca1b39 RH |
213 | (define_predicate "contiguous_bitmask_operand" |
214 | (match_code "const_int") | |
215 | { | |
c2586c82 DV |
216 | return s390_contiguous_bitmask_p (INTVAL (op), true, |
217 | GET_MODE_BITSIZE (mode), NULL, NULL); | |
218 | }) | |
219 | ||
220 | ; Same without wraparound. | |
221 | (define_predicate "contiguous_bitmask_nowrap_operand" | |
222 | (match_code "const_int") | |
223 | { | |
224 | return s390_contiguous_bitmask_p | |
225 | (INTVAL (op), false, GET_MODE_BITSIZE (mode), NULL, NULL); | |
75ca1b39 RH |
226 | }) |
227 | ||
88e845c0 | 228 | ;; Return true if OP is legitimate for any LOC instruction. |
bf749919 DV |
229 | |
230 | (define_predicate "loc_operand" | |
231 | (ior (match_operand 0 "nonimmediate_operand") | |
232 | (and (match_code "const_int") | |
233 | (match_test "INTVAL (op) <= 32767 && INTVAL (op) >= -32768")))) | |
234 | ||
3cb9ee2f AK |
235 | (define_predicate "reload_const_wide_int_operand" |
236 | (and (match_code "const_wide_int") | |
237 | (match_test "legitimate_reload_constant_p (op)"))) | |
238 | ||
239 | ||
0bfc3f69 AS |
240 | ;; operators -------------------------------------------------------------- |
241 | ||
242 | ;; Return nonzero if OP is a valid comparison operator | |
243 | ;; for a branch condition. | |
244 | ||
245 | (define_predicate "s390_comparison" | |
246 | (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu, | |
247 | uneq, unlt, ungt, unle, unge, ltgt, | |
248 | unordered, ordered") | |
249 | { | |
250 | if (GET_CODE (XEXP (op, 0)) != REG | |
251 | || REGNO (XEXP (op, 0)) != CC_REGNUM | |
5a3fe9b6 AK |
252 | || (XEXP (op, 1) != const0_rtx |
253 | && !(CONST_INT_P (XEXP (op, 1)) | |
254 | && GET_MODE (XEXP (op, 0)) == CCRAWmode | |
255 | && INTVAL (XEXP (op, 1)) >= 0 | |
256 | && INTVAL (XEXP (op, 1)) <= 15))) | |
0bfc3f69 AS |
257 | return false; |
258 | ||
259 | return (s390_branch_condition_mask (op) >= 0); | |
260 | }) | |
261 | ||
4a77c72b PB |
262 | ;; Return true if op is the cc register. |
263 | (define_predicate "cc_reg_operand" | |
264 | (and (match_code "reg") | |
265 | (match_test "REGNO (op) == CC_REGNUM"))) | |
266 | ||
963fc8d0 AK |
267 | (define_predicate "s390_signed_integer_comparison" |
268 | (match_code "eq, ne, lt, gt, le, ge") | |
269 | { | |
270 | return (s390_compare_and_branch_condition_mask (op) >= 0); | |
271 | }) | |
272 | ||
273 | (define_predicate "s390_unsigned_integer_comparison" | |
274 | (match_code "eq, ne, ltu, gtu, leu, geu") | |
275 | { | |
276 | return (s390_compare_and_branch_condition_mask (op) >= 0); | |
277 | }) | |
278 | ||
f90b7a5a PB |
279 | ;; Return nonzero if OP is a valid comparison operator for the |
280 | ;; cstore expanders -- respectively cstorecc4 and integer cstore. | |
281 | (define_predicate "s390_eqne_operator" | |
282 | (match_code "eq, ne")) | |
283 | ||
284 | (define_predicate "s390_scond_operator" | |
285 | (match_code "ltu, gtu, leu, geu")) | |
286 | ||
f1149235 AK |
287 | (define_predicate "s390_brx_operator" |
288 | (match_code "le, gt")) | |
289 | ||
0bfc3f69 AS |
290 | ;; Return nonzero if OP is a valid comparison operator |
291 | ;; for an ALC condition. | |
292 | ||
293 | (define_predicate "s390_alc_comparison" | |
294 | (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu") | |
295 | { | |
296 | while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) | |
297 | op = XEXP (op, 0); | |
298 | ||
299 | if (!COMPARISON_P (op)) | |
300 | return false; | |
301 | ||
302 | if (GET_CODE (XEXP (op, 0)) != REG | |
303 | || REGNO (XEXP (op, 0)) != CC_REGNUM | |
5a3fe9b6 AK |
304 | || (XEXP (op, 1) != const0_rtx |
305 | && !(CONST_INT_P (XEXP (op, 1)) | |
306 | && GET_MODE (XEXP (op, 0)) == CCRAWmode | |
307 | && INTVAL (XEXP (op, 1)) >= 0 | |
308 | && INTVAL (XEXP (op, 1)) <= 15))) | |
0bfc3f69 AS |
309 | return false; |
310 | ||
311 | switch (GET_MODE (XEXP (op, 0))) | |
312 | { | |
4e10a5a7 | 313 | case E_CCL1mode: |
0bfc3f69 AS |
314 | return GET_CODE (op) == LTU; |
315 | ||
4e10a5a7 | 316 | case E_CCL2mode: |
0bfc3f69 AS |
317 | return GET_CODE (op) == LEU; |
318 | ||
4e10a5a7 | 319 | case E_CCL3mode: |
0bfc3f69 AS |
320 | return GET_CODE (op) == GEU; |
321 | ||
4e10a5a7 | 322 | case E_CCUmode: |
0bfc3f69 AS |
323 | return GET_CODE (op) == GTU; |
324 | ||
4e10a5a7 | 325 | case E_CCURmode: |
0bfc3f69 AS |
326 | return GET_CODE (op) == LTU; |
327 | ||
4e10a5a7 | 328 | case E_CCSmode: |
0bfc3f69 AS |
329 | return GET_CODE (op) == UNGT; |
330 | ||
4e10a5a7 | 331 | case E_CCSRmode: |
0bfc3f69 AS |
332 | return GET_CODE (op) == UNLT; |
333 | ||
334 | default: | |
335 | return false; | |
336 | } | |
337 | }) | |
338 | ||
339 | ;; Return nonzero if OP is a valid comparison operator | |
340 | ;; for an SLB condition. | |
341 | ||
342 | (define_predicate "s390_slb_comparison" | |
343 | (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu") | |
344 | { | |
345 | while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) | |
346 | op = XEXP (op, 0); | |
347 | ||
348 | if (!COMPARISON_P (op)) | |
349 | return false; | |
350 | ||
351 | if (GET_CODE (XEXP (op, 0)) != REG | |
352 | || REGNO (XEXP (op, 0)) != CC_REGNUM | |
353 | || XEXP (op, 1) != const0_rtx) | |
354 | return false; | |
355 | ||
356 | switch (GET_MODE (XEXP (op, 0))) | |
357 | { | |
4e10a5a7 | 358 | case E_CCL1mode: |
0bfc3f69 AS |
359 | return GET_CODE (op) == GEU; |
360 | ||
4e10a5a7 | 361 | case E_CCL2mode: |
0bfc3f69 AS |
362 | return GET_CODE (op) == GTU; |
363 | ||
4e10a5a7 | 364 | case E_CCL3mode: |
0bfc3f69 AS |
365 | return GET_CODE (op) == LTU; |
366 | ||
4e10a5a7 | 367 | case E_CCUmode: |
0bfc3f69 AS |
368 | return GET_CODE (op) == LEU; |
369 | ||
4e10a5a7 | 370 | case E_CCURmode: |
0bfc3f69 AS |
371 | return GET_CODE (op) == GEU; |
372 | ||
4e10a5a7 | 373 | case E_CCSmode: |
0bfc3f69 AS |
374 | return GET_CODE (op) == LE; |
375 | ||
4e10a5a7 | 376 | case E_CCSRmode: |
0bfc3f69 AS |
377 | return GET_CODE (op) == GE; |
378 | ||
379 | default: | |
380 | return false; | |
381 | } | |
382 | }) | |
383 | ||
384 | ;; Return true if OP is a load multiple operation. It is known to be a | |
385 | ;; PARALLEL and the first section will be tested. | |
386 | ||
387 | (define_special_predicate "load_multiple_operation" | |
388 | (match_code "parallel") | |
389 | { | |
ef4bddc2 | 390 | machine_mode elt_mode; |
0bfc3f69 AS |
391 | int count = XVECLEN (op, 0); |
392 | unsigned int dest_regno; | |
393 | rtx src_addr; | |
394 | int i, off; | |
395 | ||
396 | /* Perform a quick check so we don't blow up below. */ | |
397 | if (count <= 1 | |
398 | || GET_CODE (XVECEXP (op, 0, 0)) != SET | |
399 | || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG | |
400 | || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) | |
401 | return false; | |
402 | ||
403 | dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); | |
404 | src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); | |
405 | elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0))); | |
406 | ||
407 | /* Check, is base, or base + displacement. */ | |
408 | ||
409 | if (GET_CODE (src_addr) == REG) | |
410 | off = 0; | |
411 | else if (GET_CODE (src_addr) == PLUS | |
412 | && GET_CODE (XEXP (src_addr, 0)) == REG | |
413 | && GET_CODE (XEXP (src_addr, 1)) == CONST_INT) | |
414 | { | |
415 | off = INTVAL (XEXP (src_addr, 1)); | |
416 | src_addr = XEXP (src_addr, 0); | |
417 | } | |
418 | else | |
419 | return false; | |
420 | ||
421 | for (i = 1; i < count; i++) | |
422 | { | |
423 | rtx elt = XVECEXP (op, 0, i); | |
424 | ||
425 | if (GET_CODE (elt) != SET | |
426 | || GET_CODE (SET_DEST (elt)) != REG | |
427 | || GET_MODE (SET_DEST (elt)) != elt_mode | |
428 | || REGNO (SET_DEST (elt)) != dest_regno + i | |
429 | || GET_CODE (SET_SRC (elt)) != MEM | |
430 | || GET_MODE (SET_SRC (elt)) != elt_mode | |
431 | || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS | |
432 | || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) | |
433 | || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT | |
434 | || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) | |
435 | != off + i * GET_MODE_SIZE (elt_mode)) | |
436 | return false; | |
437 | } | |
438 | ||
439 | return true; | |
440 | }) | |
441 | ||
2771c2f9 AK |
442 | ;; For an execute pattern the target instruction is embedded into the |
443 | ;; RTX but will not get checked for validity by recog automatically. | |
444 | ;; The execute_operation predicate extracts the target RTX and invokes | |
445 | ;; recog. | |
446 | (define_special_predicate "execute_operation" | |
447 | (match_code "parallel") | |
448 | { | |
449 | rtx pattern = op; | |
647d790d | 450 | rtx_insn *insn; |
2771c2f9 AK |
451 | int icode; |
452 | ||
453 | /* This is redundant but since this predicate is evaluated | |
454 | first when recognizing the insn we can prevent the more | |
455 | expensive code below from being executed for many cases. */ | |
456 | if (GET_CODE (XVECEXP (pattern, 0, 0)) != UNSPEC | |
457 | || XINT (XVECEXP (pattern, 0, 0), 1) != UNSPEC_EXECUTE) | |
458 | return false; | |
459 | ||
460 | /* Keep in sync with s390_execute_target. */ | |
461 | if (XVECLEN (pattern, 0) == 2) | |
462 | { | |
463 | pattern = copy_rtx (XVECEXP (pattern, 0, 1)); | |
464 | } | |
465 | else | |
466 | { | |
467 | rtvec vec = rtvec_alloc (XVECLEN (pattern, 0) - 1); | |
468 | int i; | |
469 | ||
470 | for (i = 0; i < XVECLEN (pattern, 0) - 1; i++) | |
471 | RTVEC_ELT (vec, i) = copy_rtx (XVECEXP (pattern, 0, i + 1)); | |
472 | ||
473 | pattern = gen_rtx_PARALLEL (VOIDmode, vec); | |
474 | } | |
475 | ||
476 | /* Since we do not have the wrapping insn here we have to build one. */ | |
477 | insn = make_insn_raw (pattern); | |
478 | icode = recog_memoized (insn); | |
479 | if (icode < 0) | |
480 | return false; | |
481 | ||
75d25a02 | 482 | extract_constrain_insn (insn); |
2771c2f9 AK |
483 | |
484 | return which_alternative >= 0; | |
485 | }) | |
486 | ||
0bfc3f69 AS |
487 | ;; Return true if OP is a store multiple operation. It is known to be a |
488 | ;; PARALLEL and the first section will be tested. | |
489 | ||
490 | (define_special_predicate "store_multiple_operation" | |
491 | (match_code "parallel") | |
492 | { | |
ef4bddc2 | 493 | machine_mode elt_mode; |
0bfc3f69 AS |
494 | int count = XVECLEN (op, 0); |
495 | unsigned int src_regno; | |
496 | rtx dest_addr; | |
497 | int i, off; | |
498 | ||
499 | /* Perform a quick check so we don't blow up below. */ | |
500 | if (count <= 1 | |
501 | || GET_CODE (XVECEXP (op, 0, 0)) != SET | |
502 | || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM | |
503 | || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) | |
504 | return false; | |
505 | ||
506 | src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); | |
507 | dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); | |
508 | elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0))); | |
509 | ||
510 | /* Check, is base, or base + displacement. */ | |
511 | ||
512 | if (GET_CODE (dest_addr) == REG) | |
513 | off = 0; | |
514 | else if (GET_CODE (dest_addr) == PLUS | |
515 | && GET_CODE (XEXP (dest_addr, 0)) == REG | |
516 | && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT) | |
517 | { | |
518 | off = INTVAL (XEXP (dest_addr, 1)); | |
519 | dest_addr = XEXP (dest_addr, 0); | |
520 | } | |
521 | else | |
522 | return false; | |
523 | ||
524 | for (i = 1; i < count; i++) | |
525 | { | |
526 | rtx elt = XVECEXP (op, 0, i); | |
527 | ||
528 | if (GET_CODE (elt) != SET | |
529 | || GET_CODE (SET_SRC (elt)) != REG | |
530 | || GET_MODE (SET_SRC (elt)) != elt_mode | |
531 | || REGNO (SET_SRC (elt)) != src_regno + i | |
532 | || GET_CODE (SET_DEST (elt)) != MEM | |
533 | || GET_MODE (SET_DEST (elt)) != elt_mode | |
534 | || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS | |
535 | || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) | |
536 | || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT | |
537 | || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) | |
538 | != off + i * GET_MODE_SIZE (elt_mode)) | |
539 | return false; | |
540 | } | |
541 | return true; | |
542 | }) | |
252c6f56 AK |
543 | |
544 | (define_predicate "const_shift_by_byte_operand" | |
545 | (match_code "const_int") | |
546 | { | |
547 | unsigned HOST_WIDE_INT val = INTVAL (op); | |
548 | return val <= 128 && val % 8 == 0; | |
549 | }) | |
bdb57bcb IL |
550 | |
551 | ;; Certain operations (e.g. CS) cannot access SYMBOL_REF directly, it needs to | |
552 | ;; be loaded into some register first. In theory, if we put a SYMBOL_REF into | |
553 | ;; a corresponding insn anyway, reload will generate a load for it, but, when | |
554 | ;; coupled with constant propagation, this will lead to an inefficient code | |
555 | ;; (see PR 80080). | |
556 | ||
557 | (define_predicate "nonsym_memory_operand" | |
558 | (match_code "mem") | |
559 | { | |
560 | return memory_operand (op, mode) && !contains_symbol_ref_p (op); | |
561 | }) | |
e2839e47 RD |
562 | |
563 | ;; Check for a valid shift count operand with an implicit | |
564 | ;; shift truncation mask of 63. | |
565 | ||
566 | (define_predicate "shift_count_operand" | |
567 | (and (match_code "reg, subreg, and, plus, const_int") | |
568 | (match_test "CONST_INT_P (op) || GET_MODE (op) == E_QImode")) | |
569 | { | |
570 | return s390_valid_shift_count (op, 63); | |
571 | } | |
572 | ) | |
573 | ||
574 | ;; This is used as operand predicate. As we do not know | |
575 | ;; the mode of the first operand here and the shift truncation | |
576 | ;; mask depends on the mode, we cannot check the mask. | |
577 | ;; This is supposed to happen in the insn condition which | |
578 | ;; calls s390_valid_shift_count with the proper mode size. | |
579 | ;; We need two separate predicates for non-vector and vector | |
580 | ;; shifts since the (less restrictive) insn condition is checked | |
581 | ;; after the more restrictive operand predicate which will | |
582 | ;; disallow the operand before we can check the condition. | |
583 | ||
584 | (define_predicate "shift_count_operand_vec" | |
585 | (and (match_code "reg, subreg, and, plus, const_int") | |
586 | (match_test "CONST_INT_P (op) || GET_MODE (op) == E_QImode")) | |
587 | { | |
588 | return s390_valid_shift_count (op, 0); | |
589 | } | |
590 | ) | |
4caa6bab AK |
591 | |
592 | ; An integer constant which can be used in a signed add with overflow | |
593 | ; pattern without being reloaded. | |
594 | (define_predicate "addv_const_operand" | |
595 | (and (match_code "const_int") | |
596 | (match_test "INTVAL (op) >= -32768 && INTVAL (op) <= 32767"))) |