]>
Commit | Line | Data |
---|---|---|
8cc5de33 | 1 | ;; Predicate definitions for S/390 and zSeries. |
3aea1f79 | 2 | ;; Copyright (C) 2005-2014 Free Software Foundation, Inc. |
8cc5de33 | 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 | |
038d1e19 | 10 | ;; the Free Software Foundation; either version 3, or (at your option) |
8cc5de33 | 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 | |
038d1e19 | 19 | ;; along with GCC; see the file COPYING3. If not see |
20 | ;; <http://www.gnu.org/licenses/>. | |
8cc5de33 | 21 | |
22 | ;; OP is the current operation. | |
23 | ;; MODE is the current operation mode. | |
24 | ||
25 | ;; operands -------------------------------------------------------------- | |
26 | ||
27 | ;; Return true if OP a (const_int 0) operand. | |
28 | ||
29 | (define_predicate "const0_operand" | |
30 | (and (match_code "const_int, const_double") | |
31 | (match_test "op == CONST0_RTX (mode)"))) | |
32 | ||
33 | ;; Return true if OP is constant. | |
34 | ||
35 | (define_special_predicate "consttable_operand" | |
36 | (and (match_code "symbol_ref, label_ref, const, const_int, const_double") | |
37 | (match_test "CONSTANT_P (op)"))) | |
38 | ||
39 | ;; Return true if OP is a valid S-type operand. | |
40 | ||
41 | (define_predicate "s_operand" | |
42 | (and (match_code "subreg, mem") | |
43 | (match_operand 0 "general_operand")) | |
44 | { | |
45 | /* Just like memory_operand, allow (subreg (mem ...)) | |
46 | after reload. */ | |
47 | if (reload_completed | |
48 | && GET_CODE (op) == SUBREG | |
49 | && GET_CODE (SUBREG_REG (op)) == MEM) | |
50 | op = SUBREG_REG (op); | |
51 | ||
52 | if (GET_CODE (op) != MEM) | |
53 | return false; | |
54 | if (!s390_legitimate_address_without_index_p (op)) | |
55 | return false; | |
56 | ||
57 | return true; | |
58 | }) | |
59 | ||
60 | ;; Return true if OP is a valid operand for the BRAS instruction. | |
61 | ;; Allow SYMBOL_REFs and @PLT stubs. | |
62 | ||
63 | (define_special_predicate "bras_sym_operand" | |
88f9884f | 64 | (ior (and (match_code "symbol_ref") |
65 | (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)")) | |
8cc5de33 | 66 | (and (match_code "const") |
67 | (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC") | |
68 | (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT"))))) | |
69 | ||
70 | ;; Return true if OP is a PLUS that is not a legitimate | |
71 | ;; operand for the LA instruction. | |
72 | ||
73 | (define_predicate "s390_plus_operand" | |
74 | (and (match_code "plus") | |
75 | (and (match_test "mode == Pmode") | |
76 | (match_test "!legitimate_la_operand_p (op)")))) | |
77 | ||
417cba42 | 78 | ;; Return true if OP is a valid operand as shift count or setmem. |
9a09ba70 | 79 | |
417cba42 | 80 | (define_predicate "shift_count_or_setmem_operand" |
9a09ba70 | 81 | (match_code "reg, subreg, plus, const_int") |
82 | { | |
6d6be381 | 83 | HOST_WIDE_INT offset; |
84 | rtx base; | |
85 | ||
417cba42 | 86 | /* Extract base register and offset. */ |
87 | if (!s390_decompose_shift_count (op, &base, &offset)) | |
8cc5de33 | 88 | return false; |
89 | ||
6d6be381 | 90 | /* Don't allow any non-base hard registers. Doing so without |
91 | confusing reload and/or regrename would be tricky, and doesn't | |
92 | buy us much anyway. */ | |
93 | if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base)) | |
3a5502f9 | 94 | return false; |
95 | ||
8cc5de33 | 96 | /* Unfortunately we have to reject constants that are invalid |
97 | for an address, or else reload will get confused. */ | |
98 | if (!DISP_IN_RANGE (offset)) | |
99 | return false; | |
100 | ||
101 | return true; | |
102 | }) | |
103 | ||
6bc28655 | 104 | (define_predicate "nonzero_shift_count_operand" |
105 | (and (match_code "const_int") | |
106 | (match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)"))) | |
107 | ||
8cc5de33 | 108 | ;; Return true if OP a valid operand for the LARL instruction. |
109 | ||
110 | (define_predicate "larl_operand" | |
111 | (match_code "label_ref, symbol_ref, const, const_int, const_double") | |
112 | { | |
113 | /* Allow labels and local symbols. */ | |
114 | if (GET_CODE (op) == LABEL_REF) | |
115 | return true; | |
116 | if (GET_CODE (op) == SYMBOL_REF) | |
e68d6a13 | 117 | return (!SYMBOL_REF_ALIGN1_P (op) |
8cc5de33 | 118 | && SYMBOL_REF_TLS_MODEL (op) == 0 |
119 | && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); | |
120 | ||
121 | /* Everything else must have a CONST, so strip it. */ | |
122 | if (GET_CODE (op) != CONST) | |
123 | return false; | |
124 | op = XEXP (op, 0); | |
125 | ||
126 | /* Allow adding *even* in-range constants. */ | |
127 | if (GET_CODE (op) == PLUS) | |
128 | { | |
129 | if (GET_CODE (XEXP (op, 1)) != CONST_INT | |
130 | || (INTVAL (XEXP (op, 1)) & 1) != 0) | |
131 | return false; | |
240fd4a0 | 132 | if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31 |
133 | || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31)) | |
8cc5de33 | 134 | return false; |
135 | op = XEXP (op, 0); | |
136 | } | |
137 | ||
138 | /* Labels and local symbols allowed here as well. */ | |
139 | if (GET_CODE (op) == LABEL_REF) | |
140 | return true; | |
141 | if (GET_CODE (op) == SYMBOL_REF) | |
142 | return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0 | |
143 | && SYMBOL_REF_TLS_MODEL (op) == 0 | |
144 | && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); | |
145 | ||
146 | /* Now we must have a @GOTENT offset or @PLT stub | |
147 | or an @INDNTPOFF TLS offset. */ | |
148 | if (GET_CODE (op) == UNSPEC | |
149 | && XINT (op, 1) == UNSPEC_GOTENT) | |
150 | return true; | |
151 | if (GET_CODE (op) == UNSPEC | |
152 | && XINT (op, 1) == UNSPEC_PLT) | |
153 | return true; | |
154 | if (GET_CODE (op) == UNSPEC | |
155 | && XINT (op, 1) == UNSPEC_INDNTPOFF) | |
156 | return true; | |
157 | ||
158 | return false; | |
159 | }) | |
160 | ||
0d46035f | 161 | (define_predicate "contiguous_bitmask_operand" |
162 | (match_code "const_int") | |
163 | { | |
164 | return s390_contiguous_bitmask_p (INTVAL (op), GET_MODE_BITSIZE (mode), NULL, NULL); | |
165 | }) | |
166 | ||
8cc5de33 | 167 | ;; operators -------------------------------------------------------------- |
168 | ||
169 | ;; Return nonzero if OP is a valid comparison operator | |
170 | ;; for a branch condition. | |
171 | ||
172 | (define_predicate "s390_comparison" | |
173 | (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu, | |
174 | uneq, unlt, ungt, unle, unge, ltgt, | |
175 | unordered, ordered") | |
176 | { | |
177 | if (GET_CODE (XEXP (op, 0)) != REG | |
178 | || REGNO (XEXP (op, 0)) != CC_REGNUM | |
5ada7a14 | 179 | || (XEXP (op, 1) != const0_rtx |
180 | && !(CONST_INT_P (XEXP (op, 1)) | |
181 | && GET_MODE (XEXP (op, 0)) == CCRAWmode | |
182 | && INTVAL (XEXP (op, 1)) >= 0 | |
183 | && INTVAL (XEXP (op, 1)) <= 15))) | |
8cc5de33 | 184 | return false; |
185 | ||
186 | return (s390_branch_condition_mask (op) >= 0); | |
187 | }) | |
188 | ||
8e58aded | 189 | ;; Return true if op is the cc register. |
190 | (define_predicate "cc_reg_operand" | |
191 | (and (match_code "reg") | |
192 | (match_test "REGNO (op) == CC_REGNUM"))) | |
193 | ||
e68d6a13 | 194 | (define_predicate "s390_signed_integer_comparison" |
195 | (match_code "eq, ne, lt, gt, le, ge") | |
196 | { | |
197 | return (s390_compare_and_branch_condition_mask (op) >= 0); | |
198 | }) | |
199 | ||
200 | (define_predicate "s390_unsigned_integer_comparison" | |
201 | (match_code "eq, ne, ltu, gtu, leu, geu") | |
202 | { | |
203 | return (s390_compare_and_branch_condition_mask (op) >= 0); | |
204 | }) | |
205 | ||
74f4459c | 206 | ;; Return nonzero if OP is a valid comparison operator for the |
207 | ;; cstore expanders -- respectively cstorecc4 and integer cstore. | |
208 | (define_predicate "s390_eqne_operator" | |
209 | (match_code "eq, ne")) | |
210 | ||
211 | (define_predicate "s390_scond_operator" | |
212 | (match_code "ltu, gtu, leu, geu")) | |
213 | ||
f1443d23 | 214 | (define_predicate "s390_brx_operator" |
215 | (match_code "le, gt")) | |
216 | ||
8cc5de33 | 217 | ;; Return nonzero if OP is a valid comparison operator |
218 | ;; for an ALC condition. | |
219 | ||
220 | (define_predicate "s390_alc_comparison" | |
221 | (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu") | |
222 | { | |
223 | while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) | |
224 | op = XEXP (op, 0); | |
225 | ||
226 | if (!COMPARISON_P (op)) | |
227 | return false; | |
228 | ||
229 | if (GET_CODE (XEXP (op, 0)) != REG | |
230 | || REGNO (XEXP (op, 0)) != CC_REGNUM | |
5ada7a14 | 231 | || (XEXP (op, 1) != const0_rtx |
232 | && !(CONST_INT_P (XEXP (op, 1)) | |
233 | && GET_MODE (XEXP (op, 0)) == CCRAWmode | |
234 | && INTVAL (XEXP (op, 1)) >= 0 | |
235 | && INTVAL (XEXP (op, 1)) <= 15))) | |
8cc5de33 | 236 | return false; |
237 | ||
238 | switch (GET_MODE (XEXP (op, 0))) | |
239 | { | |
240 | case CCL1mode: | |
241 | return GET_CODE (op) == LTU; | |
242 | ||
243 | case CCL2mode: | |
244 | return GET_CODE (op) == LEU; | |
245 | ||
246 | case CCL3mode: | |
247 | return GET_CODE (op) == GEU; | |
248 | ||
249 | case CCUmode: | |
250 | return GET_CODE (op) == GTU; | |
251 | ||
252 | case CCURmode: | |
253 | return GET_CODE (op) == LTU; | |
254 | ||
255 | case CCSmode: | |
256 | return GET_CODE (op) == UNGT; | |
257 | ||
258 | case CCSRmode: | |
259 | return GET_CODE (op) == UNLT; | |
260 | ||
261 | default: | |
262 | return false; | |
263 | } | |
264 | }) | |
265 | ||
266 | ;; Return nonzero if OP is a valid comparison operator | |
267 | ;; for an SLB condition. | |
268 | ||
269 | (define_predicate "s390_slb_comparison" | |
270 | (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu") | |
271 | { | |
272 | while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND) | |
273 | op = XEXP (op, 0); | |
274 | ||
275 | if (!COMPARISON_P (op)) | |
276 | return false; | |
277 | ||
278 | if (GET_CODE (XEXP (op, 0)) != REG | |
279 | || REGNO (XEXP (op, 0)) != CC_REGNUM | |
280 | || XEXP (op, 1) != const0_rtx) | |
281 | return false; | |
282 | ||
283 | switch (GET_MODE (XEXP (op, 0))) | |
284 | { | |
285 | case CCL1mode: | |
286 | return GET_CODE (op) == GEU; | |
287 | ||
288 | case CCL2mode: | |
289 | return GET_CODE (op) == GTU; | |
290 | ||
291 | case CCL3mode: | |
292 | return GET_CODE (op) == LTU; | |
293 | ||
294 | case CCUmode: | |
295 | return GET_CODE (op) == LEU; | |
296 | ||
297 | case CCURmode: | |
298 | return GET_CODE (op) == GEU; | |
299 | ||
300 | case CCSmode: | |
301 | return GET_CODE (op) == LE; | |
302 | ||
303 | case CCSRmode: | |
304 | return GET_CODE (op) == GE; | |
305 | ||
306 | default: | |
307 | return false; | |
308 | } | |
309 | }) | |
310 | ||
311 | ;; Return true if OP is a load multiple operation. It is known to be a | |
312 | ;; PARALLEL and the first section will be tested. | |
313 | ||
314 | (define_special_predicate "load_multiple_operation" | |
315 | (match_code "parallel") | |
316 | { | |
3754d046 | 317 | machine_mode elt_mode; |
8cc5de33 | 318 | int count = XVECLEN (op, 0); |
319 | unsigned int dest_regno; | |
320 | rtx src_addr; | |
321 | int i, off; | |
322 | ||
323 | /* Perform a quick check so we don't blow up below. */ | |
324 | if (count <= 1 | |
325 | || GET_CODE (XVECEXP (op, 0, 0)) != SET | |
326 | || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG | |
327 | || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) | |
328 | return false; | |
329 | ||
330 | dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); | |
331 | src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); | |
332 | elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0))); | |
333 | ||
334 | /* Check, is base, or base + displacement. */ | |
335 | ||
336 | if (GET_CODE (src_addr) == REG) | |
337 | off = 0; | |
338 | else if (GET_CODE (src_addr) == PLUS | |
339 | && GET_CODE (XEXP (src_addr, 0)) == REG | |
340 | && GET_CODE (XEXP (src_addr, 1)) == CONST_INT) | |
341 | { | |
342 | off = INTVAL (XEXP (src_addr, 1)); | |
343 | src_addr = XEXP (src_addr, 0); | |
344 | } | |
345 | else | |
346 | return false; | |
347 | ||
348 | for (i = 1; i < count; i++) | |
349 | { | |
350 | rtx elt = XVECEXP (op, 0, i); | |
351 | ||
352 | if (GET_CODE (elt) != SET | |
353 | || GET_CODE (SET_DEST (elt)) != REG | |
354 | || GET_MODE (SET_DEST (elt)) != elt_mode | |
355 | || REGNO (SET_DEST (elt)) != dest_regno + i | |
356 | || GET_CODE (SET_SRC (elt)) != MEM | |
357 | || GET_MODE (SET_SRC (elt)) != elt_mode | |
358 | || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS | |
359 | || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) | |
360 | || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT | |
361 | || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) | |
362 | != off + i * GET_MODE_SIZE (elt_mode)) | |
363 | return false; | |
364 | } | |
365 | ||
366 | return true; | |
367 | }) | |
368 | ||
e6e45870 | 369 | ;; For an execute pattern the target instruction is embedded into the |
370 | ;; RTX but will not get checked for validity by recog automatically. | |
371 | ;; The execute_operation predicate extracts the target RTX and invokes | |
372 | ;; recog. | |
373 | (define_special_predicate "execute_operation" | |
374 | (match_code "parallel") | |
375 | { | |
376 | rtx pattern = op; | |
ed3e6e5d | 377 | rtx_insn *insn; |
e6e45870 | 378 | int icode; |
379 | ||
380 | /* This is redundant but since this predicate is evaluated | |
381 | first when recognizing the insn we can prevent the more | |
382 | expensive code below from being executed for many cases. */ | |
383 | if (GET_CODE (XVECEXP (pattern, 0, 0)) != UNSPEC | |
384 | || XINT (XVECEXP (pattern, 0, 0), 1) != UNSPEC_EXECUTE) | |
385 | return false; | |
386 | ||
387 | /* Keep in sync with s390_execute_target. */ | |
388 | if (XVECLEN (pattern, 0) == 2) | |
389 | { | |
390 | pattern = copy_rtx (XVECEXP (pattern, 0, 1)); | |
391 | } | |
392 | else | |
393 | { | |
394 | rtvec vec = rtvec_alloc (XVECLEN (pattern, 0) - 1); | |
395 | int i; | |
396 | ||
397 | for (i = 0; i < XVECLEN (pattern, 0) - 1; i++) | |
398 | RTVEC_ELT (vec, i) = copy_rtx (XVECEXP (pattern, 0, i + 1)); | |
399 | ||
400 | pattern = gen_rtx_PARALLEL (VOIDmode, vec); | |
401 | } | |
402 | ||
403 | /* Since we do not have the wrapping insn here we have to build one. */ | |
404 | insn = make_insn_raw (pattern); | |
405 | icode = recog_memoized (insn); | |
406 | if (icode < 0) | |
407 | return false; | |
408 | ||
835b8178 | 409 | extract_constrain_insn (insn); |
e6e45870 | 410 | |
411 | return which_alternative >= 0; | |
412 | }) | |
413 | ||
8cc5de33 | 414 | ;; Return true if OP is a store multiple operation. It is known to be a |
415 | ;; PARALLEL and the first section will be tested. | |
416 | ||
417 | (define_special_predicate "store_multiple_operation" | |
418 | (match_code "parallel") | |
419 | { | |
3754d046 | 420 | machine_mode elt_mode; |
8cc5de33 | 421 | int count = XVECLEN (op, 0); |
422 | unsigned int src_regno; | |
423 | rtx dest_addr; | |
424 | int i, off; | |
425 | ||
426 | /* Perform a quick check so we don't blow up below. */ | |
427 | if (count <= 1 | |
428 | || GET_CODE (XVECEXP (op, 0, 0)) != SET | |
429 | || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM | |
430 | || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) | |
431 | return false; | |
432 | ||
433 | src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); | |
434 | dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); | |
435 | elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0))); | |
436 | ||
437 | /* Check, is base, or base + displacement. */ | |
438 | ||
439 | if (GET_CODE (dest_addr) == REG) | |
440 | off = 0; | |
441 | else if (GET_CODE (dest_addr) == PLUS | |
442 | && GET_CODE (XEXP (dest_addr, 0)) == REG | |
443 | && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT) | |
444 | { | |
445 | off = INTVAL (XEXP (dest_addr, 1)); | |
446 | dest_addr = XEXP (dest_addr, 0); | |
447 | } | |
448 | else | |
449 | return false; | |
450 | ||
451 | for (i = 1; i < count; i++) | |
452 | { | |
453 | rtx elt = XVECEXP (op, 0, i); | |
454 | ||
455 | if (GET_CODE (elt) != SET | |
456 | || GET_CODE (SET_SRC (elt)) != REG | |
457 | || GET_MODE (SET_SRC (elt)) != elt_mode | |
458 | || REGNO (SET_SRC (elt)) != src_regno + i | |
459 | || GET_CODE (SET_DEST (elt)) != MEM | |
460 | || GET_MODE (SET_DEST (elt)) != elt_mode | |
461 | || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS | |
462 | || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) | |
463 | || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT | |
464 | || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) | |
465 | != off + i * GET_MODE_SIZE (elt_mode)) | |
466 | return false; | |
467 | } | |
468 | return true; | |
469 | }) |