1;; Predicate definitions for Renesas RX.
2;; Copyright (C) 2008-2015 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,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)
308