xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/s390/predicates.md (revision fa28c6faa16e0b00edee7acdcaf4899797043def)
1;; Predicate definitions for S/390 and zSeries.
2;; Copyright (C) 2005-2013 Free Software Foundation, Inc.
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
10;; the Free Software Foundation; either version 3, or (at your option)
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
19;; along with GCC; see the file COPYING3.  If not see
20;; <http://www.gnu.org/licenses/>.
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"
64  (ior (and (match_code "symbol_ref")
65	    (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)"))
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
78;; Return true if OP is a valid operand as shift count or setmem.
79
80(define_predicate "shift_count_or_setmem_operand"
81  (match_code "reg, subreg, plus, const_int")
82{
83  HOST_WIDE_INT offset;
84  rtx base;
85
86  /* Extract base register and offset.  */
87  if (!s390_decompose_shift_count (op, &base, &offset))
88    return false;
89
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))
94    return false;
95
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
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
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)
117    return (!SYMBOL_REF_ALIGN1_P (op)
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;
132      if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
133	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
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
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
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
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)))
184    return false;
185
186  return (s390_branch_condition_mask (op) >= 0);
187})
188
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
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
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
214(define_predicate "s390_brx_operator"
215  (match_code "le, gt"))
216
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
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)))
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{
317  enum machine_mode elt_mode;
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
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;
377  rtx insn;
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
409  extract_insn (insn);
410  constrain_operands (1);
411
412  return which_alternative >= 0;
413})
414
415;; Return true if OP is a store multiple operation.  It is known to be a
416;; PARALLEL and the first section will be tested.
417
418(define_special_predicate "store_multiple_operation"
419  (match_code "parallel")
420{
421  enum machine_mode elt_mode;
422  int count = XVECLEN (op, 0);
423  unsigned int src_regno;
424  rtx dest_addr;
425  int i, off;
426
427  /* Perform a quick check so we don't blow up below.  */
428  if (count <= 1
429      || GET_CODE (XVECEXP (op, 0, 0)) != SET
430      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
431      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
432    return false;
433
434  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
435  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
436  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
437
438  /* Check, is base, or base + displacement.  */
439
440  if (GET_CODE (dest_addr) == REG)
441    off = 0;
442  else if (GET_CODE (dest_addr) == PLUS
443	   && GET_CODE (XEXP (dest_addr, 0)) == REG
444	   && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
445    {
446      off = INTVAL (XEXP (dest_addr, 1));
447      dest_addr = XEXP (dest_addr, 0);
448    }
449  else
450    return false;
451
452  for (i = 1; i < count; i++)
453    {
454      rtx elt = XVECEXP (op, 0, i);
455
456      if (GET_CODE (elt) != SET
457	  || GET_CODE (SET_SRC (elt)) != REG
458	  || GET_MODE (SET_SRC (elt)) != elt_mode
459	  || REGNO (SET_SRC (elt)) != src_regno + i
460	  || GET_CODE (SET_DEST (elt)) != MEM
461	  || GET_MODE (SET_DEST (elt)) != elt_mode
462	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
463	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
464	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
465	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
466	     != off + i * GET_MODE_SIZE (elt_mode))
467	return false;
468    }
469  return true;
470})
471