predicates.md revision 303975
1240116Smarcel;; Predicate definitions for S/390 and zSeries.
2240116Smarcel;; Copyright (C) 2005 Free Software Foundation, Inc.
3240116Smarcel;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
4240116Smarcel;;                Ulrich Weigand (uweigand@de.ibm.com).
5240116Smarcel;;
6240116Smarcel;; This file is part of GCC.
7240116Smarcel;;
8240116Smarcel;; GCC is free software; you can redistribute it and/or modify
9240116Smarcel;; it under the terms of the GNU General Public License as published by
10240116Smarcel;; the Free Software Foundation; either version 2, or (at your option)
11240116Smarcel;; any later version.
12240116Smarcel;;
13240116Smarcel;; GCC is distributed in the hope that it will be useful,
14240116Smarcel;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15240116Smarcel;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16240116Smarcel;; GNU General Public License for more details.
17240116Smarcel;;
18240116Smarcel;; You should have received a copy of the GNU General Public License
19240116Smarcel;; along with GCC; see the file COPYING.  If not, write to
20240116Smarcel;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21240116Smarcel;; Boston, MA 02110-1301, USA.
22240116Smarcel
23240116Smarcel;; OP is the current operation.
24240116Smarcel;; MODE is the current operation mode.
25240116Smarcel
26240116Smarcel;; operands --------------------------------------------------------------
27240116Smarcel
28240116Smarcel;; Return true if OP a (const_int 0) operand.
29240116Smarcel
30240116Smarcel(define_predicate "const0_operand"
31240116Smarcel  (and (match_code "const_int, const_double")
32240116Smarcel       (match_test "op == CONST0_RTX (mode)")))
33240116Smarcel
34240116Smarcel;; Return true if OP is constant.
35240116Smarcel
36240116Smarcel(define_special_predicate "consttable_operand"
37240116Smarcel  (and (match_code "symbol_ref, label_ref, const, const_int, const_double")
38240116Smarcel       (match_test "CONSTANT_P (op)")))
39240116Smarcel
40240116Smarcel;; Return true if OP is a valid S-type operand.
41240116Smarcel
42240116Smarcel(define_predicate "s_operand"
43240116Smarcel  (and (match_code "subreg, mem")
44240116Smarcel       (match_operand 0 "general_operand"))
45240116Smarcel{
46240116Smarcel  /* Just like memory_operand, allow (subreg (mem ...))
47240116Smarcel     after reload.  */
48240116Smarcel  if (reload_completed
49240116Smarcel      && GET_CODE (op) == SUBREG
50240116Smarcel      && GET_CODE (SUBREG_REG (op)) == MEM)
51240116Smarcel    op = SUBREG_REG (op);
52240116Smarcel
53240116Smarcel  if (GET_CODE (op) != MEM)
54240116Smarcel    return false;
55240116Smarcel  if (!s390_legitimate_address_without_index_p (op))
56240116Smarcel    return false;
57240116Smarcel
58240116Smarcel  return true;
59240116Smarcel})
60240116Smarcel
61240116Smarcel;; Return true if OP is a valid operand for the BRAS instruction.
62240116Smarcel;; Allow SYMBOL_REFs and @PLT stubs.
63240116Smarcel
64240116Smarcel(define_special_predicate "bras_sym_operand"
65240116Smarcel  (ior (and (match_code "symbol_ref")
66240116Smarcel	    (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)"))
67240116Smarcel       (and (match_code "const")
68240116Smarcel	    (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
69240116Smarcel		 (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT")))))
70240116Smarcel
71240116Smarcel;; Return true if OP is a PLUS that is not a legitimate
72240116Smarcel;; operand for the LA instruction.
73240116Smarcel
74240116Smarcel(define_predicate "s390_plus_operand"
75240116Smarcel  (and (match_code "plus")
76240116Smarcel       (and (match_test "mode == Pmode")
77240116Smarcel	    (match_test "!legitimate_la_operand_p (op)"))))
78240116Smarcel
79240116Smarcel;; Return true if OP is a valid operand as shift count or setmem.
80240116Smarcel
81240116Smarcel(define_predicate "shift_count_or_setmem_operand"
82240116Smarcel  (match_code "reg, subreg, plus, const_int")
83240116Smarcel{
84240116Smarcel  HOST_WIDE_INT offset;
85240116Smarcel  rtx base;
86240116Smarcel
87240116Smarcel  /* Extract base register and offset.  */
88240116Smarcel  if (!s390_decompose_shift_count (op, &base, &offset))
89240116Smarcel    return false;
90240116Smarcel
91240116Smarcel  /* Don't allow any non-base hard registers.  Doing so without
92240116Smarcel     confusing reload and/or regrename would be tricky, and doesn't
93240116Smarcel     buy us much anyway.  */
94240116Smarcel  if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base))
95240116Smarcel    return false;
96240116Smarcel
97240116Smarcel  /* Unfortunately we have to reject constants that are invalid
98240116Smarcel     for an address, or else reload will get confused.  */
99240116Smarcel  if (!DISP_IN_RANGE (offset))
100240116Smarcel    return false;
101240116Smarcel
102240116Smarcel  return true;
103240116Smarcel})
104240116Smarcel
105240116Smarcel;;  Return true if OP a valid operand for the LARL instruction.
106240116Smarcel
107240116Smarcel(define_predicate "larl_operand"
108240116Smarcel  (match_code "label_ref, symbol_ref, const, const_int, const_double")
109240116Smarcel{
110240116Smarcel  /* Allow labels and local symbols.  */
111240116Smarcel  if (GET_CODE (op) == LABEL_REF)
112240116Smarcel    return true;
113240116Smarcel  if (GET_CODE (op) == SYMBOL_REF)
114240116Smarcel    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
115240116Smarcel	    && SYMBOL_REF_TLS_MODEL (op) == 0
116240116Smarcel	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
117240116Smarcel
118240116Smarcel  /* Everything else must have a CONST, so strip it.  */
119240116Smarcel  if (GET_CODE (op) != CONST)
120240116Smarcel    return false;
121240116Smarcel  op = XEXP (op, 0);
122240116Smarcel
123240116Smarcel  /* Allow adding *even* in-range constants.  */
124240116Smarcel  if (GET_CODE (op) == PLUS)
125240116Smarcel    {
126240116Smarcel      if (GET_CODE (XEXP (op, 1)) != CONST_INT
127240116Smarcel          || (INTVAL (XEXP (op, 1)) & 1) != 0)
128240116Smarcel        return false;
129240116Smarcel      if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
130240116Smarcel	  || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
131240116Smarcel        return false;
132240116Smarcel      op = XEXP (op, 0);
133240116Smarcel    }
134240116Smarcel
135240116Smarcel  /* Labels and local symbols allowed here as well.  */
136240116Smarcel  if (GET_CODE (op) == LABEL_REF)
137240116Smarcel    return true;
138240116Smarcel  if (GET_CODE (op) == SYMBOL_REF)
139240116Smarcel    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
140240116Smarcel	    && SYMBOL_REF_TLS_MODEL (op) == 0
141240116Smarcel	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
142240116Smarcel
143240116Smarcel  /* Now we must have a @GOTENT offset or @PLT stub
144240116Smarcel     or an @INDNTPOFF TLS offset.  */
145240116Smarcel  if (GET_CODE (op) == UNSPEC
146240116Smarcel      && XINT (op, 1) == UNSPEC_GOTENT)
147240116Smarcel    return true;
148240116Smarcel  if (GET_CODE (op) == UNSPEC
149240116Smarcel      && XINT (op, 1) == UNSPEC_PLT)
150240116Smarcel    return true;
151240116Smarcel  if (GET_CODE (op) == UNSPEC
152240116Smarcel      && XINT (op, 1) == UNSPEC_INDNTPOFF)
153240116Smarcel    return true;
154240116Smarcel
155240116Smarcel  return false;
156})
157
158;; operators --------------------------------------------------------------
159
160;; Return nonzero if OP is a valid comparison operator
161;; for a branch condition.
162
163(define_predicate "s390_comparison"
164  (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu,
165	       uneq, unlt, ungt, unle, unge, ltgt,
166	       unordered, ordered")
167{
168  if (GET_CODE (XEXP (op, 0)) != REG
169      || REGNO (XEXP (op, 0)) != CC_REGNUM
170      || XEXP (op, 1) != const0_rtx)
171    return false;
172
173  return (s390_branch_condition_mask (op) >= 0);
174})
175
176;; Return nonzero if OP is a valid comparison operator
177;; for an ALC condition.
178
179(define_predicate "s390_alc_comparison"
180  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
181{
182  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
183    op = XEXP (op, 0);
184
185  if (!COMPARISON_P (op))
186    return false;
187
188  if (GET_CODE (XEXP (op, 0)) != REG
189      || REGNO (XEXP (op, 0)) != CC_REGNUM
190      || XEXP (op, 1) != const0_rtx)
191    return false;
192
193  switch (GET_MODE (XEXP (op, 0)))
194    {
195    case CCL1mode:
196      return GET_CODE (op) == LTU;
197
198    case CCL2mode:
199      return GET_CODE (op) == LEU;
200
201    case CCL3mode:
202      return GET_CODE (op) == GEU;
203
204    case CCUmode:
205      return GET_CODE (op) == GTU;
206
207    case CCURmode:
208      return GET_CODE (op) == LTU;
209
210    case CCSmode:
211      return GET_CODE (op) == UNGT;
212
213    case CCSRmode:
214      return GET_CODE (op) == UNLT;
215
216    default:
217      return false;
218    }
219})
220
221;; Return nonzero if OP is a valid comparison operator
222;; for an SLB condition.
223
224(define_predicate "s390_slb_comparison"
225  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
226{
227  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
228    op = XEXP (op, 0);
229
230  if (!COMPARISON_P (op))
231    return false;
232
233  if (GET_CODE (XEXP (op, 0)) != REG
234      || REGNO (XEXP (op, 0)) != CC_REGNUM
235      || XEXP (op, 1) != const0_rtx)
236    return false;
237
238  switch (GET_MODE (XEXP (op, 0)))
239    {
240    case CCL1mode:
241      return GET_CODE (op) == GEU;
242
243    case CCL2mode:
244      return GET_CODE (op) == GTU;
245
246    case CCL3mode:
247      return GET_CODE (op) == LTU;
248
249    case CCUmode:
250      return GET_CODE (op) == LEU;
251
252    case CCURmode:
253      return GET_CODE (op) == GEU;
254
255    case CCSmode:
256      return GET_CODE (op) == LE;
257
258    case CCSRmode:
259      return GET_CODE (op) == GE;
260
261    default:
262      return false;
263    }
264})
265
266;; Return true if OP is a load multiple operation.  It is known to be a
267;; PARALLEL and the first section will be tested.
268
269(define_special_predicate "load_multiple_operation"
270  (match_code "parallel")
271{
272  enum machine_mode elt_mode;
273  int count = XVECLEN (op, 0);
274  unsigned int dest_regno;
275  rtx src_addr;
276  int i, off;
277
278  /* Perform a quick check so we don't blow up below.  */
279  if (count <= 1
280      || GET_CODE (XVECEXP (op, 0, 0)) != SET
281      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
282      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
283    return false;
284
285  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
286  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
287  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
288
289  /* Check, is base, or base + displacement.  */
290
291  if (GET_CODE (src_addr) == REG)
292    off = 0;
293  else if (GET_CODE (src_addr) == PLUS
294	   && GET_CODE (XEXP (src_addr, 0)) == REG
295	   && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
296    {
297      off = INTVAL (XEXP (src_addr, 1));
298      src_addr = XEXP (src_addr, 0);
299    }
300  else
301    return false;
302
303  for (i = 1; i < count; i++)
304    {
305      rtx elt = XVECEXP (op, 0, i);
306
307      if (GET_CODE (elt) != SET
308	  || GET_CODE (SET_DEST (elt)) != REG
309	  || GET_MODE (SET_DEST (elt)) != elt_mode
310	  || REGNO (SET_DEST (elt)) != dest_regno + i
311	  || GET_CODE (SET_SRC (elt)) != MEM
312	  || GET_MODE (SET_SRC (elt)) != elt_mode
313	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
314	  || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
315	  || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
316	  || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
317	     != off + i * GET_MODE_SIZE (elt_mode))
318	return false;
319    }
320
321  return true;
322})
323
324;; Return true if OP is a store multiple operation.  It is known to be a
325;; PARALLEL and the first section will be tested.
326
327(define_special_predicate "store_multiple_operation"
328  (match_code "parallel")
329{
330  enum machine_mode elt_mode;
331  int count = XVECLEN (op, 0);
332  unsigned int src_regno;
333  rtx dest_addr;
334  int i, off;
335
336  /* Perform a quick check so we don't blow up below.  */
337  if (count <= 1
338      || GET_CODE (XVECEXP (op, 0, 0)) != SET
339      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
340      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
341    return false;
342
343  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
344  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
345  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
346
347  /* Check, is base, or base + displacement.  */
348
349  if (GET_CODE (dest_addr) == REG)
350    off = 0;
351  else if (GET_CODE (dest_addr) == PLUS
352	   && GET_CODE (XEXP (dest_addr, 0)) == REG
353	   && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
354    {
355      off = INTVAL (XEXP (dest_addr, 1));
356      dest_addr = XEXP (dest_addr, 0);
357    }
358  else
359    return false;
360
361  for (i = 1; i < count; i++)
362    {
363      rtx elt = XVECEXP (op, 0, i);
364
365      if (GET_CODE (elt) != SET
366	  || GET_CODE (SET_SRC (elt)) != REG
367	  || GET_MODE (SET_SRC (elt)) != elt_mode
368	  || REGNO (SET_SRC (elt)) != src_regno + i
369	  || GET_CODE (SET_DEST (elt)) != MEM
370	  || GET_MODE (SET_DEST (elt)) != elt_mode
371	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
372	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
373	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
374	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
375	     != off + i * GET_MODE_SIZE (elt_mode))
376	return false;
377    }
378  return true;
379})
380