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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [s390/] [predicates.md] - Blame information for rev 820

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

Line No. Rev Author Line
1 38 julius
;; Predicate definitions for S/390 and zSeries.
2
;; Copyright (C) 2005, 2007 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_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
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 nonzero if OP is a valid comparison operator
176
;; for an ALC condition.
177
 
178
(define_predicate "s390_alc_comparison"
179
  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
180
{
181
  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
182
    op = XEXP (op, 0);
183
 
184
  if (!COMPARISON_P (op))
185
    return false;
186
 
187
  if (GET_CODE (XEXP (op, 0)) != REG
188
      || REGNO (XEXP (op, 0)) != CC_REGNUM
189
      || XEXP (op, 1) != const0_rtx)
190
    return false;
191
 
192
  switch (GET_MODE (XEXP (op, 0)))
193
    {
194
    case CCL1mode:
195
      return GET_CODE (op) == LTU;
196
 
197
    case CCL2mode:
198
      return GET_CODE (op) == LEU;
199
 
200
    case CCL3mode:
201
      return GET_CODE (op) == GEU;
202
 
203
    case CCUmode:
204
      return GET_CODE (op) == GTU;
205
 
206
    case CCURmode:
207
      return GET_CODE (op) == LTU;
208
 
209
    case CCSmode:
210
      return GET_CODE (op) == UNGT;
211
 
212
    case CCSRmode:
213
      return GET_CODE (op) == UNLT;
214
 
215
    default:
216
      return false;
217
    }
218
})
219
 
220
;; Return nonzero if OP is a valid comparison operator
221
;; for an SLB condition.
222
 
223
(define_predicate "s390_slb_comparison"
224
  (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
225
{
226
  while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
227
    op = XEXP (op, 0);
228
 
229
  if (!COMPARISON_P (op))
230
    return false;
231
 
232
  if (GET_CODE (XEXP (op, 0)) != REG
233
      || REGNO (XEXP (op, 0)) != CC_REGNUM
234
      || XEXP (op, 1) != const0_rtx)
235
    return false;
236
 
237
  switch (GET_MODE (XEXP (op, 0)))
238
    {
239
    case CCL1mode:
240
      return GET_CODE (op) == GEU;
241
 
242
    case CCL2mode:
243
      return GET_CODE (op) == GTU;
244
 
245
    case CCL3mode:
246
      return GET_CODE (op) == LTU;
247
 
248
    case CCUmode:
249
      return GET_CODE (op) == LEU;
250
 
251
    case CCURmode:
252
      return GET_CODE (op) == GEU;
253
 
254
    case CCSmode:
255
      return GET_CODE (op) == LE;
256
 
257
    case CCSRmode:
258
      return GET_CODE (op) == GE;
259
 
260
    default:
261
      return false;
262
    }
263
})
264
 
265
;; Return true if OP is a load multiple operation.  It is known to be a
266
;; PARALLEL and the first section will be tested.
267
 
268
(define_special_predicate "load_multiple_operation"
269
  (match_code "parallel")
270
{
271
  enum machine_mode elt_mode;
272
  int count = XVECLEN (op, 0);
273
  unsigned int dest_regno;
274
  rtx src_addr;
275
  int i, off;
276
 
277
  /* Perform a quick check so we don't blow up below.  */
278
  if (count <= 1
279
      || GET_CODE (XVECEXP (op, 0, 0)) != SET
280
      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
281
      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
282
    return false;
283
 
284
  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
285
  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
286
  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
287
 
288
  /* Check, is base, or base + displacement.  */
289
 
290
  if (GET_CODE (src_addr) == REG)
291
    off = 0;
292
  else if (GET_CODE (src_addr) == PLUS
293
           && GET_CODE (XEXP (src_addr, 0)) == REG
294
           && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
295
    {
296
      off = INTVAL (XEXP (src_addr, 1));
297
      src_addr = XEXP (src_addr, 0);
298
    }
299
  else
300
    return false;
301
 
302
  for (i = 1; i < count; i++)
303
    {
304
      rtx elt = XVECEXP (op, 0, i);
305
 
306
      if (GET_CODE (elt) != SET
307
          || GET_CODE (SET_DEST (elt)) != REG
308
          || GET_MODE (SET_DEST (elt)) != elt_mode
309
          || REGNO (SET_DEST (elt)) != dest_regno + i
310
          || GET_CODE (SET_SRC (elt)) != MEM
311
          || GET_MODE (SET_SRC (elt)) != elt_mode
312
          || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
313
          || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
314
          || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
315
          || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
316
             != off + i * GET_MODE_SIZE (elt_mode))
317
        return false;
318
    }
319
 
320
  return true;
321
})
322
 
323
;; Return true if OP is a store multiple operation.  It is known to be a
324
;; PARALLEL and the first section will be tested.
325
 
326
(define_special_predicate "store_multiple_operation"
327
  (match_code "parallel")
328
{
329
  enum machine_mode elt_mode;
330
  int count = XVECLEN (op, 0);
331
  unsigned int src_regno;
332
  rtx dest_addr;
333
  int i, off;
334
 
335
  /* Perform a quick check so we don't blow up below.  */
336
  if (count <= 1
337
      || GET_CODE (XVECEXP (op, 0, 0)) != SET
338
      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
339
      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
340
    return false;
341
 
342
  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
343
  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
344
  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
345
 
346
  /* Check, is base, or base + displacement.  */
347
 
348
  if (GET_CODE (dest_addr) == REG)
349
    off = 0;
350
  else if (GET_CODE (dest_addr) == PLUS
351
           && GET_CODE (XEXP (dest_addr, 0)) == REG
352
           && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
353
    {
354
      off = INTVAL (XEXP (dest_addr, 1));
355
      dest_addr = XEXP (dest_addr, 0);
356
    }
357
  else
358
    return false;
359
 
360
  for (i = 1; i < count; i++)
361
    {
362
      rtx elt = XVECEXP (op, 0, i);
363
 
364
      if (GET_CODE (elt) != SET
365
          || GET_CODE (SET_SRC (elt)) != REG
366
          || GET_MODE (SET_SRC (elt)) != elt_mode
367
          || REGNO (SET_SRC (elt)) != src_regno + i
368
          || GET_CODE (SET_DEST (elt)) != MEM
369
          || GET_MODE (SET_DEST (elt)) != elt_mode
370
          || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
371
          || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
372
          || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
373
          || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
374
             != off + i * GET_MODE_SIZE (elt_mode))
375
        return false;
376
    }
377
  return true;
378
})

powered by: WebSVN 2.1.0

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