1;; Predicates for C-SKY.
2;; Copyright (C) 2018-2021 Free Software Foundation, Inc.
3;; Contributed by C-SKY Microsystems and Mentor Graphics.
4;;
5;; This file is part of GCC.
6;;
7;; GCC is free software; you can redistribute it and/or modify it
8;; 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, but
13;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15;; 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;; Return 1 if OP is a load multiple operation.
22
23(define_predicate "csky_load_multiple_operation"
24  (match_code "parallel")
25{
26  int count = XVECLEN (op, 0);
27  int dest_regno;
28  rtx src_addr;
29  int i;
30
31  /* Perform a quick check so we don't blow up below.  */
32  if (count <= 1
33      || GET_CODE (XVECEXP (op, 0, 0)) != SET
34      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
35      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM
36      || GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG
37      || XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0) != stack_pointer_rtx)
38    return 0;
39
40  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
41  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
42
43  for (i = 1; i < count; i++)
44    {
45      rtx elt = XVECEXP (op, 0, i);
46
47      if (GET_CODE (elt) != SET
48	  || GET_CODE (SET_DEST (elt)) != REG
49	  || GET_MODE (SET_DEST (elt)) != SImode
50	  || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i)
51	  || GET_CODE (SET_SRC (elt)) != MEM
52	  || GET_MODE (SET_SRC (elt)) != SImode
53	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
54	  || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
55	  || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
56	  || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
57	return 0;
58    }
59  return 1;
60})
61
62;; Similar, for store multiple.
63
64(define_predicate "csky_store_multiple_operation"
65  (match_code "parallel")
66{
67  int count = XVECLEN (op, 0);
68  int src_regno;
69  rtx dest_addr;
70  int i;
71
72  /* Perform a quick check so we don't blow up below.  */
73  if (count <= 1
74      || GET_CODE (XVECEXP (op, 0, 0)) != SET
75      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
76      || GET_CODE (XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0)) != REG
77      || XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0) != stack_pointer_rtx
78      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
79    return 0;
80
81  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
82  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
83
84  for (i = 1; i < count; i++)
85    {
86      rtx elt = XVECEXP (op, 0, i);
87
88      if (GET_CODE (elt) != SET
89	  || GET_CODE (SET_SRC (elt)) != REG
90	  || GET_MODE (SET_SRC (elt)) != SImode
91	  || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i)
92	  || GET_CODE (SET_DEST (elt)) != MEM
93	  || GET_MODE (SET_DEST (elt)) != SImode
94	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
95	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
96	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
97	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
98	return 0;
99    }
100  return 1;
101})
102
103
104(define_predicate "csky_arith_K_operand"
105  (match_code "reg,subreg,const_int")
106  {
107    if (register_operand (op, mode))
108      return 1;
109    if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_K (INTVAL (op)))
110      return 1;
111    return 0;
112  })
113
114(define_predicate "csky_literal_K_operand"
115  (match_code "const_int")
116  {
117    if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_K (INTVAL (op)))
118      return 1;
119    return 0;
120  })
121
122(define_predicate "csky_literal_I_operand"
123  (match_code "const_int")
124  {
125    if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_I (INTVAL (op)))
126      return 1;
127    return 0;
128  })
129
130(define_predicate "csky_literal_J_operand"
131  (match_code "const_int")
132  {
133    if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_J (INTVAL (op)))
134      return 1;
135    return 0;
136  })
137
138(define_predicate "csky_literal_Uk_operand"
139  (match_code "const_int")
140  {
141    if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_Uk (INTVAL (op)))
142      return 1;
143    return 0;
144  })
145
146;; Nonzero if OP is a register or constant value of 1
147
148(define_predicate "csky_arith_int1_operand"
149  (match_code "reg,subreg,const_int")
150  {
151    if (register_operand (op, mode))
152	return 1;
153    if (op == const1_rtx)
154	return 1;
155    return 0;
156  })
157
158
159;; Nonzero if OP is legal address for function call
160
161(define_predicate "csky_call_address_operand"
162  (match_code "reg,subreg,symbol_ref")
163  {
164    if (!flag_pic && (GET_CODE (op) == SYMBOL_REF))
165      return 1;
166    if (register_operand (op, mode))
167      return 1;
168    return 0;
169  })
170
171;; Nonzero if OP is a valid source operand for a compare operation.
172
173(define_predicate "csky_compare_operand"
174  (match_code "const_int,reg,subreg")
175  {
176    if (register_operand (op, mode))
177      return 1;
178    if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
179      return 1;
180    return 0;
181  })
182
183(define_predicate "csky_literal_K_Uh_operand"
184  (match_code "const_int")
185  {
186    if (CONST_INT_P (op)
187	&& (CSKY_CONST_OK_FOR_K (INTVAL (op))
188	    || CSKY_CONST_OK_FOR_Uh (INTVAL (op))))
189	  return 1;
190    return 0;
191  })
192
193;; True if OP is a mem with an reg + optional displacement address.
194
195(define_predicate "csky_simple_mem_operand"
196  (and (match_operand 0 "memory_operand")
197       (match_test "csky_simple_addr_operand_p (XEXP (op, 0))")))
198
199(define_predicate "csky_arith_any_imm_operand"
200  (match_code "const_int,reg,subreg")
201  {
202    if (register_operand (op, mode))
203      return 1;
204    if (CONST_INT_P (op))
205      return 1;
206    return 0;
207  })
208
209(define_predicate "csky_arith_O_operand"
210  (match_code "reg,subreg,const_int")
211  {
212    if (register_operand (op, mode))
213      return 1;
214    if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_O (INTVAL (op)))
215      return 1;
216    return 0;
217  })
218
219(define_predicate "csky_unspec_operand"
220  (match_code "unspec")
221  {
222    if (op == NULL || GET_CODE(op) != UNSPEC)
223      return 0;
224    return 1;
225  }
226)
227
228(define_predicate "csky_const_float1_operand"
229  (and (match_code "const_double")
230       (match_test "(op == CONST1_RTX (mode))")))
231
232(define_predicate "csky_arith_float1_operand"
233  (ior (match_operand 0 "register_operand")
234       (match_operand 0 "csky_const_float1_operand")))
235
236(define_predicate "csky_const_float0_operand"
237  (and (match_code "const_double")
238       (match_test "(op == CONST0_RTX (mode))")))
239
240(define_predicate "csky_compare_operand_float"
241  (ior (match_operand 0 "register_operand")
242       (match_operand 0 "csky_const_float0_operand")))
243
244(define_special_predicate "registers_push"
245  (match_code "parallel")
246{
247  if ((GET_CODE (XVECEXP (op, 0, 0)) != SET)
248      || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
249      || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSHPOP_MULT))
250    return false;
251  return true;
252})
253
254(define_special_predicate "registers_pop"
255  (match_code "parallel")
256{
257  if ((GET_CODE (XVECEXP (op, 0, 1)) != SET)
258      || (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != UNSPEC)
259      || (XINT (SET_SRC (XVECEXP (op, 0, 1)), 1) != UNSPEC_PUSHPOP_MULT))
260    return false;
261  return true;
262})
263
264(define_predicate "push_memory_operand"
265  (match_code "mem")
266{
267  rtx x = XEXP (op, 0);
268  if (GET_CODE (x) != PRE_MODIFY)
269    return false;
270  if (XEXP (x, 0) != stack_pointer_rtx)
271    return false;
272  x = XEXP (x, 1);
273  if (GET_CODE (x) != PLUS)
274    return false;
275  if (XEXP (x, 0) != stack_pointer_rtx)
276    return false;
277  return CONST_INT_P (XEXP (x, 1));
278})
279
280(define_predicate "pop_memory_operand"
281  (match_code "mem")
282{
283  rtx x = XEXP (op, 0);
284  if (GET_CODE (x) != POST_MODIFY)
285    return false;
286  if (XEXP (x, 0) != stack_pointer_rtx)
287    return false;
288  x = XEXP (x, 1);
289  if (GET_CODE (x) != PLUS)
290    return false;
291  if (XEXP (x, 0) != stack_pointer_rtx)
292    return false;
293  return CONST_INT_P (XEXP (x, 1));
294})
295
296(define_special_predicate "csky_float_comparison_operator"
297  (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,
298	       unordered,ordered"))
299