xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/rx/predicates.md (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1;; Predicate definitions for Renesas RX.
2;; Copyright (C) 2008, 2009, 2011 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;; Return true if OP is a store multiple operation.  This looks like:
76;;
77;;   [(set (SP) (MINUS (SP) (INT)))
78;;    (set (MEM (SP)) (REG))
79;;    (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
80;;   ]
81
82(define_special_predicate "rx_store_multiple_vector"
83  (match_code "parallel")
84{
85  int count = XVECLEN (op, 0);
86  unsigned int src_regno;
87  rtx element;
88  int i;
89
90  /* Perform a quick check so we don't blow up below.  */
91  if (count <= 2)
92    return false;
93
94  /* Check that the first element of the vector is the stack adjust.  */
95  element = XVECEXP (op, 0, 0);
96  if (   ! SET_P (element)
97      || ! REG_P (SET_DEST (element))
98      ||   REGNO (SET_DEST (element)) != SP_REG
99      ||   GET_CODE (SET_SRC (element)) != MINUS
100      || ! REG_P (XEXP (SET_SRC (element), 0))
101      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
102      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
103    return false;
104
105  /* Check that the next element is the first push.  */
106  element = XVECEXP (op, 0, 1);
107  if (   ! SET_P (element)
108      || ! REG_P (SET_SRC (element))
109      || GET_MODE (SET_SRC (element)) != SImode
110      || ! MEM_P (SET_DEST (element))
111      || GET_MODE (SET_DEST (element)) != SImode
112      || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
113      || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
114      ||   REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
115      || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
116      || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
117        != GET_MODE_SIZE (SImode))
118    return false;
119
120  src_regno = REGNO (SET_SRC (element));
121
122  /* Check that the remaining elements use SP-<disp>
123     addressing and decreasing register numbers.  */
124  for (i = 2; i < count; i++)
125    {
126      element = XVECEXP (op, 0, i);
127
128      if (   ! SET_P (element)
129	  || ! REG_P (SET_SRC (element))
130	  || GET_MODE (SET_SRC (element)) != SImode
131	  || REGNO (SET_SRC (element)) != src_regno - (i - 1)
132	  || ! MEM_P (SET_DEST (element))
133	  || GET_MODE (SET_DEST (element)) != SImode
134	  || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
135          || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
136          ||   REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
137	  || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
138	  || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
139	     != i * GET_MODE_SIZE (SImode))
140	return false;
141    }
142  return true;
143})
144
145;; Return true if OP is a load multiple operation.
146;; This looks like:
147;;  [(set (SP) (PLUS (SP) (INT)))
148;;   (set (REG) (MEM (SP)))
149;;   (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
150;;  ]
151
152(define_special_predicate "rx_load_multiple_vector"
153  (match_code "parallel")
154{
155  int count = XVECLEN (op, 0);
156  unsigned int dest_regno;
157  rtx element;
158  int i;
159
160  /* Perform a quick check so we don't blow up below.  */
161  if (count <= 2)
162    return false;
163
164  /* Check that the first element of the vector is the stack adjust.  */
165  element = XVECEXP (op, 0, 0);
166  if (   ! SET_P (element)
167      || ! REG_P (SET_DEST (element))
168      ||   REGNO (SET_DEST (element)) != SP_REG
169      ||   GET_CODE (SET_SRC (element)) != PLUS
170      || ! REG_P (XEXP (SET_SRC (element), 0))
171      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
172      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
173    return false;
174
175  /* Check that the next element is the first push.  */
176  element = XVECEXP (op, 0, 1);
177  if (   ! SET_P (element)
178      || ! REG_P (SET_DEST (element))
179      || ! MEM_P (SET_SRC (element))
180      || ! REG_P (XEXP (SET_SRC (element), 0))
181      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
182    return false;
183
184  dest_regno = REGNO (SET_DEST (element));
185
186  /* Check that the remaining elements use SP+<disp>
187     addressing and incremental register numbers.  */
188  for (i = 2; i < count; i++)
189    {
190      element = XVECEXP (op, 0, i);
191
192      if (   ! SET_P (element)
193	  || ! REG_P (SET_DEST (element))
194	  || GET_MODE (SET_DEST (element)) != SImode
195	  || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
196	  || ! MEM_P (SET_SRC (element))
197	  || GET_MODE (SET_SRC (element)) != SImode
198	  || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
199          || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
200          ||   REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
201	  || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
202	  || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
203	     != (i - 1) * GET_MODE_SIZE (SImode))
204	return false;
205    }
206  return true;
207})
208
209;; Return true if OP is a pop-and-return load multiple operation.
210;; This looks like:
211;;  [(set (SP) (PLUS (SP) (INT)))
212;;   (set (REG) (MEM (SP)))
213;;   (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
214;;   (return)
215;;  ]
216
217(define_special_predicate "rx_rtsd_vector"
218  (match_code "parallel")
219{
220  int count = XVECLEN (op, 0);
221  unsigned int dest_regno;
222  rtx element;
223  int i;
224
225  /* Perform a quick check so we don't blow up below.  */
226  if (count <= 2)
227    return false;
228
229  /* Check that the first element of the vector is the stack adjust.  */
230  element = XVECEXP (op, 0, 0);
231  if (   ! SET_P (element)
232      || ! REG_P (SET_DEST (element))
233      ||   REGNO (SET_DEST (element)) != SP_REG
234      ||   GET_CODE (SET_SRC (element)) != PLUS
235      || ! REG_P (XEXP (SET_SRC (element), 0))
236      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
237      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
238    return false;
239
240  /* Check that the next element is the first push.  */
241  element = XVECEXP (op, 0, 1);
242  if (   ! SET_P (element)
243      || ! REG_P (SET_DEST (element))
244      || ! MEM_P (SET_SRC (element))
245      || ! REG_P (XEXP (SET_SRC (element), 0))
246      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
247    return false;
248
249  dest_regno = REGNO (SET_DEST (element));
250
251  /* Check that the remaining elements, if any, and except
252     for the last one, use SP+<disp> addressing and incremental
253     register numbers.  */
254  for (i = 2; i < count - 1; i++)
255    {
256      element = XVECEXP (op, 0, i);
257
258      if (   ! SET_P (element)
259	  || ! REG_P (SET_DEST (element))
260	  || GET_MODE (SET_DEST (element)) != SImode
261	  || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
262	  || ! MEM_P (SET_SRC (element))
263	  || GET_MODE (SET_SRC (element)) != SImode
264	  || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
265          || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
266          ||   REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
267	  || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
268	  || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
269	     != (i - 1) * GET_MODE_SIZE (SImode))
270	return false;
271    }
272
273  /* The last element must be a RETURN.  */
274  element = XVECEXP (op, 0, count - 1);
275  return GET_CODE (element) == RETURN;
276})
277
278(define_predicate "label_ref_operand"
279  (match_code "label_ref")
280)
281
282(define_predicate "rx_z_comparison_operator"
283  (match_code "eq,ne")
284)
285
286(define_predicate "rx_zs_comparison_operator"
287  (match_code "eq,ne")
288)
289
290;; GT and LE omitted due to operand swap required.
291(define_predicate "rx_fp_comparison_operator"
292  (match_code "eq,ne,lt,ge,ordered,unordered")
293)
294
295(define_predicate "rshift_operator"
296  (match_code "ashiftrt,lshiftrt")
297)
298