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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [rx/] [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 Renesas RX.
2
;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
3
;; Contributed by Red Hat.
4
;;
5
;; This file is part of GCC.
6
;;
7
;; GCC is free software; you can redistribute it and/or modify
8
;; it under the terms of the GNU General Public License as published by
9
;; the Free Software Foundation; either version 3, or (at your option)
10
;; any later version.
11
;;
12
;; GCC is distributed in the hope that it will be useful,
13
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
;; GNU General Public License for more details.
16
;;
17
;; You should have received a copy of the GNU General Public License
18
;; along with GCC; see the file COPYING3.  If not see
19
;; .
20
 
21
 
22
 
23
;; Check that the operand is suitable for a call insn.
24
;; Only registers and symbol refs are allowed.
25
 
26
(define_predicate "rx_call_operand"
27
  (match_code "symbol_ref,reg")
28
)
29
 
30
;; For sibcall operations we can only use a symbolic address.
31
 
32
(define_predicate "rx_symbolic_call_operand"
33
  (match_code "symbol_ref")
34
)
35
 
36
;; Check that the operand is suitable for a shift insn
37
;; Only small integers or a value in a register are permitted.
38
 
39
(define_predicate "rx_shift_operand"
40
  (ior (match_operand 0 "register_operand")
41
       (and (match_code "const_int")
42
            (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
43
)
44
 
45
(define_predicate "rx_constshift_operand"
46
  (and (match_code "const_int")
47
       (match_test "IN_RANGE (INTVAL (op), 0, 31)"))
48
)
49
 
50
(define_predicate "rx_restricted_mem_operand"
51
  (and (match_code "mem")
52
       (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)"))
53
)
54
 
55
;; Check that the operand is suitable as the source operand
56
;; for a logic or arithmeitc instruction.  Registers, integers
57
;; and a restricted subset of memory addresses are allowed.
58
 
59
(define_predicate "rx_source_operand"
60
  (ior (match_operand 0 "register_operand")
61
       (match_operand 0 "immediate_operand")
62
       (match_operand 0 "rx_restricted_mem_operand"))
63
)
64
 
65
;; Check that the operand is suitable as the source operand
66
;; for a comparison instruction.  This is the same as
67
;; rx_source_operand except that SUBREGs are allowed but
68
;; CONST_INTs are not.
69
 
70
(define_predicate "rx_compare_operand"
71
  (ior (match_operand 0 "register_operand")
72
       (match_operand 0 "rx_restricted_mem_operand"))
73
)
74
 
75
;; Check that the operand is suitable as the source operand
76
;; for a min/max instruction.  This is the same as
77
;; rx_source_operand except that CONST_INTs are allowed but
78
;; REGs and SUBREGs are not.
79
 
80
(define_predicate "rx_minmaxex_operand"
81
  (ior (match_operand 0 "immediate_operand")
82
       (match_operand 0 "rx_restricted_mem_operand"))
83
)
84
 
85
;; Return true if OP is a store multiple operation.  This looks like:
86
;;
87
;;   [(set (SP) (MINUS (SP) (INT)))
88
;;    (set (MEM (SP)) (REG))
89
;;    (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
90
;;   ]
91
 
92
(define_special_predicate "rx_store_multiple_vector"
93
  (match_code "parallel")
94
{
95
  int count = XVECLEN (op, 0);
96
  unsigned int src_regno;
97
  rtx element;
98
  int i;
99
 
100
  /* Perform a quick check so we don't blow up below.  */
101
  if (count <= 2)
102
    return false;
103
 
104
  /* Check that the first element of the vector is the stack adjust.  */
105
  element = XVECEXP (op, 0, 0);
106
  if (   ! SET_P (element)
107
      || ! REG_P (SET_DEST (element))
108
      ||   REGNO (SET_DEST (element)) != SP_REG
109
      ||   GET_CODE (SET_SRC (element)) != MINUS
110
      || ! REG_P (XEXP (SET_SRC (element), 0))
111
      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
112
      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
113
    return false;
114
 
115
  /* Check that the next element is the first push.  */
116
  element = XVECEXP (op, 0, 1);
117
  if (   ! SET_P (element)
118
      || ! REG_P (SET_SRC (element))
119
      || GET_MODE (SET_SRC (element)) != SImode
120
      || ! MEM_P (SET_DEST (element))
121
      || GET_MODE (SET_DEST (element)) != SImode
122
      || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
123
      || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
124
      ||   REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
125
      || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
126
      || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
127
        != GET_MODE_SIZE (SImode))
128
    return false;
129
 
130
  src_regno = REGNO (SET_SRC (element));
131
 
132
  /* Check that the remaining elements use SP-
133
     addressing and decreasing register numbers.  */
134
  for (i = 2; i < count; i++)
135
    {
136
      element = XVECEXP (op, 0, i);
137
 
138
      if (   ! SET_P (element)
139
          || ! REG_P (SET_SRC (element))
140
          || GET_MODE (SET_SRC (element)) != SImode
141
          || REGNO (SET_SRC (element)) != src_regno - (i - 1)
142
          || ! MEM_P (SET_DEST (element))
143
          || GET_MODE (SET_DEST (element)) != SImode
144
          || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
145
          || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
146
          ||   REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
147
          || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
148
          || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
149
             != i * GET_MODE_SIZE (SImode))
150
        return false;
151
    }
152
  return true;
153
})
154
 
155
;; Return true if OP is a load multiple operation.
156
;; This looks like:
157
;;  [(set (SP) (PLUS (SP) (INT)))
158
;;   (set (REG) (MEM (SP)))
159
;;   (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
160
;;  ]
161
 
162
(define_special_predicate "rx_load_multiple_vector"
163
  (match_code "parallel")
164
{
165
  int count = XVECLEN (op, 0);
166
  unsigned int dest_regno;
167
  rtx element;
168
  int i;
169
 
170
  /* Perform a quick check so we don't blow up below.  */
171
  if (count <= 2)
172
    return false;
173
 
174
  /* Check that the first element of the vector is the stack adjust.  */
175
  element = XVECEXP (op, 0, 0);
176
  if (   ! SET_P (element)
177
      || ! REG_P (SET_DEST (element))
178
      ||   REGNO (SET_DEST (element)) != SP_REG
179
      ||   GET_CODE (SET_SRC (element)) != PLUS
180
      || ! REG_P (XEXP (SET_SRC (element), 0))
181
      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
182
      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
183
    return false;
184
 
185
  /* Check that the next element is the first push.  */
186
  element = XVECEXP (op, 0, 1);
187
  if (   ! SET_P (element)
188
      || ! REG_P (SET_DEST (element))
189
      || ! MEM_P (SET_SRC (element))
190
      || ! REG_P (XEXP (SET_SRC (element), 0))
191
      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
192
    return false;
193
 
194
  dest_regno = REGNO (SET_DEST (element));
195
 
196
  /* Check that the remaining elements use SP+
197
     addressing and incremental register numbers.  */
198
  for (i = 2; i < count; i++)
199
    {
200
      element = XVECEXP (op, 0, i);
201
 
202
      if (   ! SET_P (element)
203
          || ! REG_P (SET_DEST (element))
204
          || GET_MODE (SET_DEST (element)) != SImode
205
          || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
206
          || ! MEM_P (SET_SRC (element))
207
          || GET_MODE (SET_SRC (element)) != SImode
208
          || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
209
          || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
210
          ||   REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
211
          || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
212
          || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
213
             != (i - 1) * GET_MODE_SIZE (SImode))
214
        return false;
215
    }
216
  return true;
217
})
218
 
219
;; Return true if OP is a pop-and-return load multiple operation.
220
;; This looks like:
221
;;  [(set (SP) (PLUS (SP) (INT)))
222
;;   (set (REG) (MEM (SP)))
223
;;   (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
224
;;   (return)
225
;;  ]
226
 
227
(define_special_predicate "rx_rtsd_vector"
228
  (match_code "parallel")
229
{
230
  int count = XVECLEN (op, 0);
231
  unsigned int dest_regno;
232
  rtx element;
233
  int i;
234
 
235
  /* Perform a quick check so we don't blow up below.  */
236
  if (count <= 2)
237
    return false;
238
 
239
  /* Check that the first element of the vector is the stack adjust.  */
240
  element = XVECEXP (op, 0, 0);
241
  if (   ! SET_P (element)
242
      || ! REG_P (SET_DEST (element))
243
      ||   REGNO (SET_DEST (element)) != SP_REG
244
      ||   GET_CODE (SET_SRC (element)) != PLUS
245
      || ! REG_P (XEXP (SET_SRC (element), 0))
246
      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
247
      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
248
    return false;
249
 
250
  /* Check that the next element is the first push.  */
251
  element = XVECEXP (op, 0, 1);
252
  if (   ! SET_P (element)
253
      || ! REG_P (SET_DEST (element))
254
      || ! MEM_P (SET_SRC (element))
255
      || ! REG_P (XEXP (SET_SRC (element), 0))
256
      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
257
    return false;
258
 
259
  dest_regno = REGNO (SET_DEST (element));
260
 
261
  /* Check that the remaining elements, if any, and except
262
     for the last one, use SP+ addressing and incremental
263
     register numbers.  */
264
  for (i = 2; i < count - 1; i++)
265
    {
266
      element = XVECEXP (op, 0, i);
267
 
268
      if (   ! SET_P (element)
269
          || ! REG_P (SET_DEST (element))
270
          || GET_MODE (SET_DEST (element)) != SImode
271
          || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
272
          || ! MEM_P (SET_SRC (element))
273
          || GET_MODE (SET_SRC (element)) != SImode
274
          || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
275
          || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
276
          ||   REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
277
          || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
278
          || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
279
             != (i - 1) * GET_MODE_SIZE (SImode))
280
        return false;
281
    }
282
 
283
  /* The last element must be a RETURN.  */
284
  element = XVECEXP (op, 0, count - 1);
285
  return GET_CODE (element) == RETURN;
286
})
287
 
288
(define_predicate "label_ref_operand"
289
  (match_code "label_ref")
290
)
291
 
292
(define_predicate "rx_z_comparison_operator"
293
  (match_code "eq,ne")
294
)
295
 
296
(define_predicate "rx_zs_comparison_operator"
297
  (match_code "eq,ne,lt,ge")
298
)
299
 
300
;; GT and LE omitted due to operand swap required.
301
(define_predicate "rx_fp_comparison_operator"
302
  (match_code "eq,ne,lt,ge,ordered,unordered")
303
)
304
 
305
(define_predicate "rshift_operator"
306
  (match_code "ashiftrt,lshiftrt")
307
)

powered by: WebSVN 2.1.0

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