xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/pru/predicates.md (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1;; Predicate definitions for TI PRU.
2;; Copyright (C) 2014-2020 Free Software Foundation, Inc.
3;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
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(define_predicate "const_1_operand"
22  (and (match_code "const_int")
23       (match_test "INTVAL (op) == 1")))
24
25; Note: Always pass a valid mode!
26(define_predicate "const_ubyte_operand"
27  (match_code "const_int")
28{
29  gcc_assert (mode != VOIDmode);
30  return IN_RANGE (INTVAL (op) & GET_MODE_MASK (mode), 0, 0xff);
31})
32
33(define_predicate "const_uhword_operand"
34  (match_code "const_int")
35{
36  gcc_assert (mode != VOIDmode);
37  return IN_RANGE (INTVAL (op) & GET_MODE_MASK (mode), 0, 0xffff);
38})
39
40; TRUE for comparisons we support.
41(define_predicate "pru_cmp_operator"
42  (match_code "eq,ne,leu,ltu,geu,gtu"))
43
44; TRUE for signed comparisons that need special handling for PRU.
45(define_predicate "pru_signed_cmp_operator"
46  (match_code "ge,gt,le,lt"))
47
48;; FP Comparisons handled by pru_expand_pru_compare.
49(define_predicate "pru_fp_comparison_operator"
50  (match_code "eq,ne,lt,gt,le,ge"))
51
52;; Return true if OP is a constant that contains only one 1 in its
53;; binary representation.
54(define_predicate "single_one_operand"
55  (and (match_code "const_int")
56       (match_test "exact_log2 (INTVAL (op) & GET_MODE_MASK (mode)) >= 0")))
57
58;; Return true if OP is a constant that contains only one 0 in its
59;; binary representation.
60(define_predicate "single_zero_operand"
61  (and (match_code "const_int")
62       (match_test "exact_log2 (~INTVAL (op) & GET_MODE_MASK (mode)) >= 0")))
63
64(define_predicate "pru_muldst_operand"
65  (match_code "subreg,reg")
66{
67  if (register_operand (op, mode))
68    {
69      int regno;
70
71      if (REG_P (op))
72	regno = REGNO (op);
73      else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
74	regno = REGNO (SUBREG_REG (op));
75      else
76	return 0;
77
78      return REGNO_REG_CLASS (regno) == MULDST_REGS
79	     || regno >= FIRST_PSEUDO_REGISTER;
80    }
81  return 0;
82})
83
84(define_predicate "pru_mulsrc0_operand"
85  (match_code "subreg,reg")
86{
87  if (register_operand (op, mode))
88    {
89      int regno;
90
91      if (REG_P (op))
92	regno = REGNO (op);
93      else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
94	regno = REGNO (SUBREG_REG (op));
95      else
96	return 0;
97
98      return REGNO_REG_CLASS (regno) == MULSRC0_REGNUM
99	     || regno >= FIRST_PSEUDO_REGISTER;
100    }
101  return 0;
102})
103
104(define_predicate "pru_mulsrc1_operand"
105  (match_code "subreg,reg")
106{
107  if (register_operand (op, mode))
108    {
109      int regno;
110
111      if (REG_P (op))
112	regno = REGNO (op);
113      else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
114	regno = REGNO (SUBREG_REG (op));
115      else
116	return 0;
117
118      return REGNO_REG_CLASS (regno) == MULSRC1_REGNUM
119	     || regno >= FIRST_PSEUDO_REGISTER;
120    }
121  return 0;
122})
123
124(define_predicate "reg_or_const_int_operand"
125  (ior (match_operand 0 "const_int_operand")
126       (match_operand 0 "register_operand")))
127
128(define_predicate "reg_or_ubyte_operand"
129  (ior (match_operand 0 "const_ubyte_operand")
130       (match_operand 0 "register_operand")))
131
132(define_predicate "reg_or_const_1_operand"
133  (ior (match_operand 0 "const_1_operand")
134       (match_operand 0 "register_operand")))
135
136(define_predicate "const_shift_operand"
137  (and (match_code "const_int")
138       (match_test "SHIFT_INT (INTVAL (op))")))
139
140(define_predicate "shift_operand"
141  (ior (match_operand 0 "const_shift_operand")
142       (match_operand 0 "register_operand")))
143
144(define_predicate "ctable_addr_operand"
145  (and (match_code "const_int")
146       (match_test "pru_get_ctable_base_index (INTVAL (op)) >= 0")))
147
148(define_predicate "ctable_base_operand"
149  (and (match_code "const_int")
150       (match_test "pru_get_ctable_exact_base_index (INTVAL (op)) >= 0")))
151
152;; Ideally we should enforce a restriction to all text labels to fit in
153;; 16bits, as required by the PRU ISA.  But for the time being we'll rely on
154;; binutils to catch text segment overflows.
155(define_predicate "call_operand"
156  (ior (match_operand 0 "immediate_operand")
157       (match_operand 0 "register_operand")))
158
159;; Return true if OP is a text segment reference.
160;; This is needed for program memory address expressions.  Borrowed from AVR.
161(define_predicate "text_segment_operand"
162  (match_code "code_label,label_ref,symbol_ref,plus,minus")
163{
164  poly_int64 offset;
165  rtx base = strip_offset (op, &offset);
166
167  switch (GET_CODE (base))
168    {
169    case CODE_LABEL:
170      /* Why AVR lists this as a valid option?  Let's catch it.  */
171      gcc_unreachable ();
172      return false;
173    case LABEL_REF:
174      return true;
175    case SYMBOL_REF:
176      return SYMBOL_REF_FUNCTION_P (base);
177    case PLUS:
178    case MINUS:
179      /* Handle constructs like (&&label1 - &&label2).  See pr70460.c.  */
180      return text_segment_operand (XEXP (op, 0), VOIDmode);
181    default:
182      return false;
183    }
184})
185
186;; Return true if OP is a load multiple operation.  It is known to be a
187;; PARALLEL and the first section will be tested.
188
189(define_special_predicate "load_multiple_operation"
190  (match_code "parallel")
191{
192  machine_mode elt_mode;
193  int count = XVECLEN (op, 0);
194  unsigned int dest_regno;
195  rtx src_addr, base_reg;
196  poly_int64 base_offs;
197  int i;
198
199  /* Perform a quick check so we don't blow up below.  */
200  if (GET_CODE (XVECEXP (op, 0, 0)) != SET
201      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
202      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
203    return false;
204
205  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
206  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
207  elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
208
209  base_reg = strip_offset (src_addr, &base_offs);
210  if (GET_CODE (base_reg) != REG)
211    return false;
212
213  for (i = 1; i < count; i++)
214    {
215      rtx elt_reg;
216      poly_int64 elt_offs;
217      rtx elt = XVECEXP (op, 0, i);
218
219      if (GET_CODE (elt) != SET
220	  || GET_CODE (SET_DEST (elt)) != REG
221	  || GET_MODE (SET_DEST (elt)) != elt_mode
222	  || REGNO (SET_DEST (elt)) != dest_regno + i * GET_MODE_SIZE (elt_mode)
223	  || GET_CODE (SET_SRC (elt)) != MEM
224	  || GET_MODE (SET_SRC (elt)) != elt_mode)
225	return false;
226
227      elt_reg = strip_offset (XEXP (SET_SRC (elt), 0), &elt_offs);
228
229      if (GET_CODE (elt_reg) != REG
230	  || ! rtx_equal_p (elt_reg, base_reg)
231	  || elt_offs != base_offs + i * GET_MODE_SIZE (elt_mode))
232	return false;
233    }
234
235  return true;
236})
237
238;; Return true if OP is a store multiple operation.  It is known to be a
239;; PARALLEL and the first section will be tested.
240
241(define_special_predicate "store_multiple_operation"
242  (match_code "parallel")
243{
244  machine_mode elt_mode;
245  int count = XVECLEN (op, 0);
246  unsigned int src_regno;
247  rtx dest_addr, base_reg;
248  poly_int64 base_offs;
249  int i;
250
251  /* Perform a quick check so we don't blow up below.  */
252  if (GET_CODE (XVECEXP (op, 0, 0)) != SET
253      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
254      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
255    return false;
256
257  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
258  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
259  elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
260
261  base_reg = strip_offset (dest_addr, &base_offs);
262  if (GET_CODE (base_reg) != REG)
263    return false;
264
265  for (i = 1; i < count; i++)
266    {
267      rtx elt_reg;
268      poly_int64 elt_offs;
269      rtx elt = XVECEXP (op, 0, i);
270
271      if (GET_CODE (elt) != SET
272	  || GET_CODE (SET_SRC (elt)) != REG
273	  || GET_MODE (SET_SRC (elt)) != elt_mode
274	  || REGNO (SET_SRC (elt)) != src_regno + i * GET_MODE_SIZE (elt_mode)
275	  || GET_CODE (SET_DEST (elt)) != MEM
276	  || GET_MODE (SET_DEST (elt)) != elt_mode)
277	return false;
278
279      elt_reg = strip_offset (XEXP (SET_DEST (elt), 0), &elt_offs);
280
281      if (GET_CODE (elt_reg) != REG
282	  || ! rtx_equal_p (elt_reg, base_reg)
283	  || elt_offs != base_offs + i * GET_MODE_SIZE (elt_mode))
284	return false;
285    }
286  return true;
287})
288