OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [s390/] [predicates.md] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;; Predicate definitions for S/390 and zSeries.
2
;; Copyright (C) 2005, 2007, 2008 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
;; .
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
;;  Return true if OP a valid operand for the LARL instruction.
105
 
106
(define_predicate "larl_operand"
107
  (match_code "label_ref, symbol_ref, const, const_int, const_double")
108
{
109
  /* Allow labels and local symbols.  */
110
  if (GET_CODE (op) == LABEL_REF)
111
    return true;
112
  if (GET_CODE (op) == SYMBOL_REF)
113
    return (!SYMBOL_REF_ALIGN1_P (op)
114
            && SYMBOL_REF_TLS_MODEL (op) == 0
115
            && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
116
 
117
  /* Everything else must have a CONST, so strip it.  */
118
  if (GET_CODE (op) != CONST)
119
    return false;
120
  op = XEXP (op, 0);
121
 
122
  /* Allow adding *even* in-range constants.  */
123
  if (GET_CODE (op) == PLUS)
124
    {
125
      if (GET_CODE (XEXP (op, 1)) != CONST_INT
126
          || (INTVAL (XEXP (op, 1)) & 1) != 0)
127
        return false;
128
      if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
129
          || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
130
        return false;
131
      op = XEXP (op, 0);
132
    }
133
 
134
  /* Labels and local symbols allowed here as well.  */
135
  if (GET_CODE (op) == LABEL_REF)
136
    return true;
137
  if (GET_CODE (op) == SYMBOL_REF)
138
    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
139
            && SYMBOL_REF_TLS_MODEL (op) == 0
140
            && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
141
 
142
  /* Now we must have a @GOTENT offset or @PLT stub
143
     or an @INDNTPOFF TLS offset.  */
144
  if (GET_CODE (op) == UNSPEC
145
      && XINT (op, 1) == UNSPEC_GOTENT)
146
    return true;
147
  if (GET_CODE (op) == UNSPEC
148
      && XINT (op, 1) == UNSPEC_PLT)
149
    return true;
150
  if (GET_CODE (op) == UNSPEC
151
      && XINT (op, 1) == UNSPEC_INDNTPOFF)
152
    return true;
153
 
154
  return false;
155
})
156
 
157
;; operators --------------------------------------------------------------
158
 
159
;; Return nonzero if OP is a valid comparison operator
160
;; for a branch condition.
161
 
162
(define_predicate "s390_comparison"
163
  (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu,
164
               uneq, unlt, ungt, unle, unge, ltgt,
165
               unordered, ordered")
166
{
167
  if (GET_CODE (XEXP (op, 0)) != REG
168
      || REGNO (XEXP (op, 0)) != CC_REGNUM
169
      || XEXP (op, 1) != const0_rtx)
170
    return false;
171
 
172
  return (s390_branch_condition_mask (op) >= 0);
173
})
174
 
175
;; Return true if op is the cc register.
176
(define_predicate "cc_reg_operand"
177
  (and (match_code "reg")
178
       (match_test "REGNO (op) == CC_REGNUM")))
179
 
180
(define_predicate "s390_signed_integer_comparison"
181
  (match_code "eq, ne, lt, gt, le, ge")
182
{
183
  return (s390_compare_and_branch_condition_mask (op) >= 0);
184
})
185
 
186
(define_predicate "s390_unsigned_integer_comparison"
187
  (match_code "eq, ne, ltu, gtu, leu, geu")
188
{
189
  return (s390_compare_and_branch_condition_mask (op) >= 0);
190
})
191
 
192
;; Return nonzero if OP is a valid comparison operator for the
193
;; cstore expanders -- respectively cstorecc4 and integer cstore.
194
(define_predicate "s390_eqne_operator"
195
  (match_code "eq, ne"))
196
 
197
(define_predicate "s390_scond_operator"
198
  (match_code "ltu, gtu, leu, geu"))
199
 
200
(define_predicate "s390_brx_operator"
201
  (match_code "le, gt"))
202
 
203
;; Return nonzero if OP is a valid comparison operator
204
;; for an ALC condition.
205
 
206
(define_predicate "s390_alc_comparison"
207
  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
208
{
209
  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
210
    op = XEXP (op, 0);
211
 
212
  if (!COMPARISON_P (op))
213
    return false;
214
 
215
  if (GET_CODE (XEXP (op, 0)) != REG
216
      || REGNO (XEXP (op, 0)) != CC_REGNUM
217
      || XEXP (op, 1) != const0_rtx)
218
    return false;
219
 
220
  switch (GET_MODE (XEXP (op, 0)))
221
    {
222
    case CCL1mode:
223
      return GET_CODE (op) == LTU;
224
 
225
    case CCL2mode:
226
      return GET_CODE (op) == LEU;
227
 
228
    case CCL3mode:
229
      return GET_CODE (op) == GEU;
230
 
231
    case CCUmode:
232
      return GET_CODE (op) == GTU;
233
 
234
    case CCURmode:
235
      return GET_CODE (op) == LTU;
236
 
237
    case CCSmode:
238
      return GET_CODE (op) == UNGT;
239
 
240
    case CCSRmode:
241
      return GET_CODE (op) == UNLT;
242
 
243
    default:
244
      return false;
245
    }
246
})
247
 
248
;; Return nonzero if OP is a valid comparison operator
249
;; for an SLB condition.
250
 
251
(define_predicate "s390_slb_comparison"
252
  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
253
{
254
  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
255
    op = XEXP (op, 0);
256
 
257
  if (!COMPARISON_P (op))
258
    return false;
259
 
260
  if (GET_CODE (XEXP (op, 0)) != REG
261
      || REGNO (XEXP (op, 0)) != CC_REGNUM
262
      || XEXP (op, 1) != const0_rtx)
263
    return false;
264
 
265
  switch (GET_MODE (XEXP (op, 0)))
266
    {
267
    case CCL1mode:
268
      return GET_CODE (op) == GEU;
269
 
270
    case CCL2mode:
271
      return GET_CODE (op) == GTU;
272
 
273
    case CCL3mode:
274
      return GET_CODE (op) == LTU;
275
 
276
    case CCUmode:
277
      return GET_CODE (op) == LEU;
278
 
279
    case CCURmode:
280
      return GET_CODE (op) == GEU;
281
 
282
    case CCSmode:
283
      return GET_CODE (op) == LE;
284
 
285
    case CCSRmode:
286
      return GET_CODE (op) == GE;
287
 
288
    default:
289
      return false;
290
    }
291
})
292
 
293
;; Return true if OP is a load multiple operation.  It is known to be a
294
;; PARALLEL and the first section will be tested.
295
 
296
(define_special_predicate "load_multiple_operation"
297
  (match_code "parallel")
298
{
299
  enum machine_mode elt_mode;
300
  int count = XVECLEN (op, 0);
301
  unsigned int dest_regno;
302
  rtx src_addr;
303
  int i, off;
304
 
305
  /* Perform a quick check so we don't blow up below.  */
306
  if (count <= 1
307
      || GET_CODE (XVECEXP (op, 0, 0)) != SET
308
      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
309
      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
310
    return false;
311
 
312
  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
313
  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
314
  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
315
 
316
  /* Check, is base, or base + displacement.  */
317
 
318
  if (GET_CODE (src_addr) == REG)
319
    off = 0;
320
  else if (GET_CODE (src_addr) == PLUS
321
           && GET_CODE (XEXP (src_addr, 0)) == REG
322
           && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
323
    {
324
      off = INTVAL (XEXP (src_addr, 1));
325
      src_addr = XEXP (src_addr, 0);
326
    }
327
  else
328
    return false;
329
 
330
  for (i = 1; i < count; i++)
331
    {
332
      rtx elt = XVECEXP (op, 0, i);
333
 
334
      if (GET_CODE (elt) != SET
335
          || GET_CODE (SET_DEST (elt)) != REG
336
          || GET_MODE (SET_DEST (elt)) != elt_mode
337
          || REGNO (SET_DEST (elt)) != dest_regno + i
338
          || GET_CODE (SET_SRC (elt)) != MEM
339
          || GET_MODE (SET_SRC (elt)) != elt_mode
340
          || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
341
          || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
342
          || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
343
          || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
344
             != off + i * GET_MODE_SIZE (elt_mode))
345
        return false;
346
    }
347
 
348
  return true;
349
})
350
 
351
;; Return true if OP is a store multiple operation.  It is known to be a
352
;; PARALLEL and the first section will be tested.
353
 
354
(define_special_predicate "store_multiple_operation"
355
  (match_code "parallel")
356
{
357
  enum machine_mode elt_mode;
358
  int count = XVECLEN (op, 0);
359
  unsigned int src_regno;
360
  rtx dest_addr;
361
  int i, off;
362
 
363
  /* Perform a quick check so we don't blow up below.  */
364
  if (count <= 1
365
      || GET_CODE (XVECEXP (op, 0, 0)) != SET
366
      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
367
      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
368
    return false;
369
 
370
  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
371
  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
372
  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
373
 
374
  /* Check, is base, or base + displacement.  */
375
 
376
  if (GET_CODE (dest_addr) == REG)
377
    off = 0;
378
  else if (GET_CODE (dest_addr) == PLUS
379
           && GET_CODE (XEXP (dest_addr, 0)) == REG
380
           && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
381
    {
382
      off = INTVAL (XEXP (dest_addr, 1));
383
      dest_addr = XEXP (dest_addr, 0);
384
    }
385
  else
386
    return false;
387
 
388
  for (i = 1; i < count; i++)
389
    {
390
      rtx elt = XVECEXP (op, 0, i);
391
 
392
      if (GET_CODE (elt) != SET
393
          || GET_CODE (SET_SRC (elt)) != REG
394
          || GET_MODE (SET_SRC (elt)) != elt_mode
395
          || REGNO (SET_SRC (elt)) != src_regno + i
396
          || GET_CODE (SET_DEST (elt)) != MEM
397
          || GET_MODE (SET_DEST (elt)) != elt_mode
398
          || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
399
          || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
400
          || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
401
          || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
402
             != off + i * GET_MODE_SIZE (elt_mode))
403
        return false;
404
    }
405
  return true;
406
})

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.