OSDN Git Service

Merge remote-tracking branch 'gnu/gcc-4_7-branch' into rework
[pf3gnuchains/gcc-fork.git] / gcc / config / rx / predicates.md
1 ;; 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 ;; <http://www.gnu.org/licenses/>.
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-<disp>
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+<disp>
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+<disp> 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")
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 )