nds32-predicates.c revision 1.1.1.2
1/* Predicate functions of Andes NDS32 cpu for GNU compiler
2   Copyright (C) 2012-2016 Free Software Foundation, Inc.
3   Contributed by Andes Technology Corporation.
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
9   by the Free Software Foundation; either version 3, or (at your
10   option) any later version.
11
12   GCC is distributed in the hope that it will be useful, but WITHOUT
13   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15   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#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "backend.h"
27#include "target.h"
28#include "rtl.h"
29#include "tree.h"
30#include "tm_p.h"
31#include "optabs.h"		/* For GEN_FCN.  */
32#include "emit-rtl.h"
33#include "recog.h"
34#include "tm-constrs.h"
35
36/* ------------------------------------------------------------------------ */
37
38/* A subroutine that checks multiple load and store
39   using consecutive registers.
40     OP is a parallel rtx we would like to check.
41     LOAD_P indicates whether we are checking load operation.
42     PAR_INDEX is starting element of parallel rtx.
43     FIRST_ELT_REGNO is used to tell starting register number.
44     COUNT helps us to check consecutive register numbers.  */
45static bool
46nds32_consecutive_registers_load_store_p (rtx op,
47					  bool load_p,
48					  int par_index,
49					  int first_elt_regno,
50					  int count)
51{
52  int i;
53  int check_regno;
54  rtx elt;
55  rtx elt_reg;
56  rtx elt_mem;
57
58  for (i = 0; i < count; i++)
59    {
60      /* Pick up each element from parallel rtx.  */
61      elt = XVECEXP (op, 0, i + par_index);
62
63      /* If this element is not a 'set' rtx, return false immediately.  */
64      if (GET_CODE (elt) != SET)
65	return false;
66
67      /* Pick up reg and mem of this element.  */
68      elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
69      elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
70
71      /* If elt_reg is not a expected reg rtx, return false.  */
72      if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
73	return false;
74      /* If elt_mem is not a expected mem rtx, return false.  */
75      if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
76	return false;
77
78      /* The consecutive registers should be in (Rb,Rb+1...Re) order.  */
79      check_regno = first_elt_regno + i;
80
81      /* If the register number is not continuous, return false.  */
82      if (REGNO (elt_reg) != (unsigned int) check_regno)
83	return false;
84    }
85
86  return true;
87}
88
89/* Function to check whether the OP is a valid load/store operation.
90   This is a helper function for the predicates:
91   'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
92   in predicates.md file.
93
94   The OP is supposed to be a parallel rtx.
95   For each element within this parallel rtx:
96     (set (reg) (mem addr)) is the form for load operation.
97     (set (mem addr) (reg)) is the form for store operation.
98   We have to extract reg and mem of every element and
99   check if the information is valid for multiple load/store operation.  */
100bool
101nds32_valid_multiple_load_store (rtx op, bool load_p)
102{
103  int count;
104  int first_elt_regno;
105  rtx elt;
106
107  /* Get the counts of elements in the parallel rtx.  */
108  count = XVECLEN (op, 0);
109  /* Pick up the first element.  */
110  elt = XVECEXP (op, 0, 0);
111
112  /* Perform some quick check for the first element in the parallel rtx.  */
113  if (GET_CODE (elt) != SET
114      || count <= 1
115      || count > 8)
116    return false;
117
118  /* Pick up regno of first element for further detail checking.
119     Note that the form is different between load and store operation.  */
120  if (load_p)
121    {
122      if (GET_CODE (SET_DEST (elt)) != REG
123	  || GET_CODE (SET_SRC (elt)) != MEM)
124	return false;
125
126      first_elt_regno = REGNO (SET_DEST (elt));
127    }
128  else
129    {
130      if (GET_CODE (SET_SRC (elt)) != REG
131	  || GET_CODE (SET_DEST (elt)) != MEM)
132	return false;
133
134      first_elt_regno = REGNO (SET_SRC (elt));
135    }
136
137  /* Perform detail check for each element.
138     Refer to nds32-multiple.md for more information
139     about following checking.
140     The starting element of parallel rtx is index 0.  */
141  if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
142						 first_elt_regno,
143						 count))
144    return false;
145
146  /* Pass all test, this is a valid rtx.  */
147  return true;
148}
149
150/* Function to check whether the OP is a valid stack push/pop operation.
151   For a valid stack operation, it must satisfy following conditions:
152     1. Consecutive registers push/pop operations.
153     2. Valid $fp/$gp/$lp push/pop operations.
154     3. The last element must be stack adjustment rtx.
155   See the prologue/epilogue implementation for details.  */
156bool
157nds32_valid_stack_push_pop_p (rtx op, bool push_p)
158{
159  int index;
160  int total_count;
161  int rest_count;
162  int first_regno;
163  int save_fp, save_gp, save_lp;
164  rtx elt;
165  rtx elt_reg;
166  rtx elt_mem;
167  rtx elt_plus;
168
169  /* Get the counts of elements in the parallel rtx.  */
170  total_count = XVECLEN (op, 0);
171
172  /* Perform some quick check for that every element should be 'set'.  */
173  for (index = 0; index < total_count; index++)
174    {
175      elt = XVECEXP (op, 0, index);
176      if (GET_CODE (elt) != SET)
177        return false;
178    }
179
180  /* For push operation, the parallel rtx looks like:
181     (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
182                     (reg:SI Rb))
183                (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
184                     (reg:SI Rb+1))
185                ...
186                (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
187                     (reg:SI Re))
188                (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
189                     (reg:SI FP_REGNUM))
190                (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
191                     (reg:SI GP_REGNUM))
192                (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
193                     (reg:SI LP_REGNUM))
194                (set (reg:SI SP_REGNUM)
195                     (plus (reg:SI SP_REGNUM) (const_int -32)))])
196
197     For pop operation, the parallel rtx looks like:
198     (parallel [(set (reg:SI Rb)
199                     (mem (reg:SI SP_REGNUM)))
200                (set (reg:SI Rb+1)
201                     (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
202                ...
203                (set (reg:SI Re)
204                     (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
205                (set (reg:SI FP_REGNUM)
206                     (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
207                (set (reg:SI GP_REGNUM)
208                     (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
209                (set (reg:SI LP_REGNUM)
210                     (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
211                (set (reg:SI SP_REGNUM)
212                     (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
213
214  /* 1. Consecutive registers push/pop operations.
215        We need to calculate how many registers should be consecutive.
216        The $sp adjustment rtx, $fp push rtx, $gp push rtx,
217        and $lp push rtx are excluded.  */
218
219  /* Detect whether we have $fp, $gp, or $lp in the parallel rtx.  */
220  save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op);
221  save_gp = reg_mentioned_p (gen_rtx_REG (SImode, GP_REGNUM), op);
222  save_lp = reg_mentioned_p (gen_rtx_REG (SImode, LP_REGNUM), op);
223  /* Exclude last $sp adjustment rtx.  */
224  rest_count = total_count - 1;
225  /* Exclude $fp, $gp, and $lp if they are in the parallel rtx.  */
226  if (save_fp)
227    rest_count--;
228  if (save_gp)
229    rest_count--;
230  if (save_lp)
231    rest_count--;
232
233  if (rest_count > 0)
234    {
235      elt = XVECEXP (op, 0, 0);
236      /* Pick up register element.  */
237      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
238      first_regno = REGNO (elt_reg);
239
240      /* The 'push' operation is a kind of store operation.
241         The 'pop' operation is a kind of load operation.
242         Pass corresponding false/true as second argument (bool load_p).
243         The par_index is supposed to start with index 0.  */
244      if (!nds32_consecutive_registers_load_store_p (op,
245						     !push_p ? true : false,
246						     0,
247						     first_regno,
248						     rest_count))
249        return false;
250    }
251
252  /* 2. Valid $fp/$gp/$lp push/pop operations.
253        Remember to set start index for checking them.  */
254
255  /* The rest_count is the start index for checking $fp/$gp/$lp.  */
256  index = rest_count;
257  /* If index < 0, this parallel rtx is definitely
258     not a valid stack push/pop operation.  */
259  if (index < 0)
260    return false;
261
262  /* Check $fp/$gp/$lp one by one.
263     We use 'push_p' to pick up reg rtx and mem rtx.  */
264  if (save_fp)
265    {
266      elt = XVECEXP (op, 0, index);
267      elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
268      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
269      index++;
270
271      if (GET_CODE (elt_mem) != MEM
272          || GET_CODE (elt_reg) != REG
273          || REGNO (elt_reg) != FP_REGNUM)
274        return false;
275    }
276  if (save_gp)
277    {
278      elt = XVECEXP (op, 0, index);
279      elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
280      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
281      index++;
282
283      if (GET_CODE (elt_mem) != MEM
284          || GET_CODE (elt_reg) != REG
285          || REGNO (elt_reg) != GP_REGNUM)
286        return false;
287    }
288  if (save_lp)
289    {
290      elt = XVECEXP (op, 0, index);
291      elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
292      elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
293      index++;
294
295      if (GET_CODE (elt_mem) != MEM
296          || GET_CODE (elt_reg) != REG
297          || REGNO (elt_reg) != LP_REGNUM)
298        return false;
299    }
300
301  /* 3. The last element must be stack adjustment rtx.
302        Its form of rtx should be:
303          (set (reg:SI SP_REGNUM)
304               (plus (reg:SI SP_REGNUM) (const_int X)))
305        The X could be positive or negative value.  */
306
307  /* Pick up the last element.  */
308  elt = XVECEXP (op, 0, total_count - 1);
309
310  /* Extract its destination and source rtx.  */
311  elt_reg  = SET_DEST (elt);
312  elt_plus = SET_SRC (elt);
313
314  /* Check this is (set (stack_reg) (plus stack_reg const)) pattern.  */
315  if (GET_CODE (elt_reg) != REG
316      || GET_CODE (elt_plus) != PLUS
317      || REGNO (elt_reg) != SP_REGNUM)
318    return false;
319
320  /* Pass all test, this is a valid rtx.  */
321  return true;
322}
323
324/* Function to check if 'bclr' instruction can be used with IVAL.  */
325int
326nds32_can_use_bclr_p (int ival)
327{
328  int one_bit_count;
329
330  /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
331     it means the original ival has only one 0-bit,
332     So it is ok to perform 'bclr' operation.  */
333
334  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
335
336  /* 'bclr' is a performance extension instruction.  */
337  return (TARGET_PERF_EXT && (one_bit_count == 1));
338}
339
340/* Function to check if 'bset' instruction can be used with IVAL.  */
341int
342nds32_can_use_bset_p (int ival)
343{
344  int one_bit_count;
345
346  /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
347     it is ok to perform 'bset' operation.  */
348
349  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
350
351  /* 'bset' is a performance extension instruction.  */
352  return (TARGET_PERF_EXT && (one_bit_count == 1));
353}
354
355/* Function to check if 'btgl' instruction can be used with IVAL.  */
356int
357nds32_can_use_btgl_p (int ival)
358{
359  int one_bit_count;
360
361  /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
362     it is ok to perform 'btgl' operation.  */
363
364  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
365
366  /* 'btgl' is a performance extension instruction.  */
367  return (TARGET_PERF_EXT && (one_bit_count == 1));
368}
369
370/* Function to check if 'bitci' instruction can be used with IVAL.  */
371int
372nds32_can_use_bitci_p (int ival)
373{
374  /* If we are using V3 ISA, we have 'bitci' instruction.
375     Try to see if we can present 'andi' semantic with
376     such 'bit-clear-immediate' operation.
377     For example, 'andi $r0,$r0,0xfffffffc' can be
378     presented with 'bitci $r0,$r0,3'.  */
379  return (TARGET_ISA_V3
380	  && (ival < 0)
381	  && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
382}
383
384/* ------------------------------------------------------------------------ */
385