1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
2    Copyright (C) 2012-2021 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 #define IN_TARGET_CODE 1
24 
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "memmodel.h"
33 #include "tm_p.h"
34 #include "optabs.h"		/* For GEN_FCN.  */
35 #include "emit-rtl.h"
36 #include "recog.h"
37 #include "tm-constrs.h"
38 #include "insn-attr.h"
39 
40 /* ------------------------------------------------------------------------ */
41 
42 /* A subroutine that checks multiple load and store
43    using consecutive registers.
44      OP is a parallel rtx we would like to check.
45      LOAD_P indicates whether we are checking load operation.
46      PAR_INDEX is starting element of parallel rtx.
47      FIRST_ELT_REGNO is used to tell starting register number.
48      COUNT helps us to check consecutive register numbers.  */
49 static bool
nds32_consecutive_registers_load_store_p(rtx op,bool load_p,int par_index,int first_elt_regno,int count)50 nds32_consecutive_registers_load_store_p (rtx op,
51 					  bool load_p,
52 					  int par_index,
53 					  int first_elt_regno,
54 					  int count)
55 {
56   int i;
57   int check_regno;
58   rtx elt;
59   rtx elt_reg;
60   rtx elt_mem;
61 
62   for (i = 0; i < count; i++)
63     {
64       /* Pick up each element from parallel rtx.  */
65       elt = XVECEXP (op, 0, i + par_index);
66 
67       /* If this element is not a 'set' rtx, return false immediately.  */
68       if (GET_CODE (elt) != SET)
69 	return false;
70 
71       /* Pick up reg and mem of this element.  */
72       elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
73       elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
74 
75       /* If elt_reg is not a expected reg rtx, return false.  */
76       if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
77 	return false;
78       /* If elt_mem is not a expected mem rtx, return false.  */
79       if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
80 	return false;
81 
82       /* The consecutive registers should be in (Rb,Rb+1...Re) order.  */
83       check_regno = first_elt_regno + i;
84 
85       /* If the register number is not continuous, return false.  */
86       if (REGNO (elt_reg) != (unsigned int) check_regno)
87 	return false;
88     }
89 
90   return true;
91 }
92 
93 /* Function to check whether the OP is a valid load/store operation.
94    This is a helper function for the predicates:
95    'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
96    in predicates.md file.
97 
98    The OP is supposed to be a parallel rtx.
99    For each element within this parallel rtx:
100      (set (reg) (mem addr)) is the form for load operation.
101      (set (mem addr) (reg)) is the form for store operation.
102    We have to extract reg and mem of every element and
103    check if the information is valid for multiple load/store operation.  */
104 bool
nds32_valid_multiple_load_store_p(rtx op,bool load_p,bool bim_p)105 nds32_valid_multiple_load_store_p (rtx op, bool load_p, bool bim_p)
106 {
107   int count;
108   int first_elt_regno;
109   int update_base_elt_idx;
110   int offset;
111   rtx elt;
112   rtx update_base;
113 
114   /* Get the counts of elements in the parallel rtx.
115      Last one is update base register if bim_p.
116      and pick up the first element.  */
117   if (bim_p)
118     {
119       count = XVECLEN (op, 0) - 1;
120       elt = XVECEXP (op, 0, 1);
121     }
122   else
123     {
124       count = XVECLEN (op, 0);
125       elt = XVECEXP (op, 0, 0);
126     }
127 
128   /* Perform some quick check for the first element in the parallel rtx.  */
129   if (GET_CODE (elt) != SET
130       || count <= 1
131       || count > 25)
132     return false;
133 
134   /* Pick up regno of first element for further detail checking.
135      Note that the form is different between load and store operation.  */
136   if (load_p)
137     {
138       if (GET_CODE (SET_DEST (elt)) != REG
139 	  || GET_CODE (SET_SRC (elt)) != MEM)
140 	return false;
141 
142       first_elt_regno = REGNO (SET_DEST (elt));
143     }
144   else
145     {
146       if (GET_CODE (SET_SRC (elt)) != REG
147 	  || GET_CODE (SET_DEST (elt)) != MEM)
148 	return false;
149 
150       first_elt_regno = REGNO (SET_SRC (elt));
151     }
152 
153   /* Perform detail check for each element.
154      Refer to nds32-multiple.md for more information
155      about following checking.
156      The starting element of parallel rtx is index 0.  */
157   if (!nds32_consecutive_registers_load_store_p (op, load_p, bim_p ? 1 : 0,
158 						 first_elt_regno,
159 						 count))
160     return false;
161 
162   if (bim_p)
163     {
164       update_base_elt_idx = 0;
165       update_base = XVECEXP (op, 0, update_base_elt_idx);
166       if (!REG_P (SET_DEST (update_base)))
167 	return false;
168       if (GET_CODE (SET_SRC (update_base)) != PLUS)
169 	return false;
170       else
171 	{
172 	  offset = count * UNITS_PER_WORD;
173 	  elt = XEXP (SET_SRC (update_base), 1);
174 	  if (GET_CODE (elt) != CONST_INT
175 	      || (INTVAL (elt) != offset))
176 	    return false;
177 	}
178     }
179 
180   /* Pass all test, this is a valid rtx.  */
181   return true;
182 }
183 
184 /* Function to check whether the OP is a valid stack push/pop operation.
185    For a valid stack operation, it must satisfy following conditions:
186      1. Consecutive registers push/pop operations.
187      2. Valid $fp/$gp/$lp push/pop operations.
188      3. The last element must be stack adjustment rtx.
189    See the prologue/epilogue implementation for details.  */
190 bool
nds32_valid_stack_push_pop_p(rtx op,bool push_p)191 nds32_valid_stack_push_pop_p (rtx op, bool push_p)
192 {
193   int index;
194   int total_count;
195   int rest_count;
196   int first_regno;
197   int save_fp, save_gp, save_lp;
198   rtx elt;
199   rtx elt_reg;
200   rtx elt_mem;
201   rtx elt_plus;
202 
203   /* Get the counts of elements in the parallel rtx.  */
204   total_count = XVECLEN (op, 0);
205 
206   /* Perform some quick check for that every element should be 'set'.  */
207   for (index = 0; index < total_count; index++)
208     {
209       elt = XVECEXP (op, 0, index);
210       if (GET_CODE (elt) != SET)
211 	return false;
212     }
213 
214   /* For push operation, the parallel rtx looks like:
215      (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
216 		     (reg:SI Rb))
217 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
218 		     (reg:SI Rb+1))
219 		...
220 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
221 		     (reg:SI Re))
222 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
223 		     (reg:SI FP_REGNUM))
224 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
225 		     (reg:SI GP_REGNUM))
226 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
227 		     (reg:SI LP_REGNUM))
228 		(set (reg:SI SP_REGNUM)
229 		     (plus (reg:SI SP_REGNUM) (const_int -32)))])
230 
231      For pop operation, the parallel rtx looks like:
232      (parallel [(set (reg:SI Rb)
233 		     (mem (reg:SI SP_REGNUM)))
234 		(set (reg:SI Rb+1)
235 		     (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
236 		...
237 		(set (reg:SI Re)
238 		     (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
239 		(set (reg:SI FP_REGNUM)
240 		     (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
241 		(set (reg:SI GP_REGNUM)
242 		     (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
243 		(set (reg:SI LP_REGNUM)
244 		     (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
245 		(set (reg:SI SP_REGNUM)
246 		     (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
247 
248   /* 1. Consecutive registers push/pop operations.
249 	We need to calculate how many registers should be consecutive.
250 	The $sp adjustment rtx, $fp push rtx, $gp push rtx,
251 	and $lp push rtx are excluded.  */
252 
253   /* Detect whether we have $fp, $gp, or $lp in the parallel rtx.  */
254   save_fp = reg_mentioned_p (gen_rtx_REG (SImode, FP_REGNUM), op);
255   save_gp = reg_mentioned_p (gen_rtx_REG (SImode, GP_REGNUM), op);
256   save_lp = reg_mentioned_p (gen_rtx_REG (SImode, LP_REGNUM), op);
257   /* Exclude last $sp adjustment rtx.  */
258   rest_count = total_count - 1;
259   /* Exclude $fp, $gp, and $lp if they are in the parallel rtx.  */
260   if (save_fp)
261     rest_count--;
262   if (save_gp)
263     rest_count--;
264   if (save_lp)
265     rest_count--;
266 
267   if (rest_count > 0)
268     {
269       elt = XVECEXP (op, 0, 0);
270       /* Pick up register element.  */
271       elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
272       first_regno = REGNO (elt_reg);
273 
274       /* The 'push' operation is a kind of store operation.
275 	 The 'pop' operation is a kind of load operation.
276 	 Pass corresponding false/true as second argument (bool load_p).
277 	 The par_index is supposed to start with index 0.  */
278       if (!nds32_consecutive_registers_load_store_p (op,
279 						     !push_p ? true : false,
280 						     0,
281 						     first_regno,
282 						     rest_count))
283 	return false;
284     }
285 
286   /* 2. Valid $fp/$gp/$lp push/pop operations.
287 	Remember to set start index for checking them.  */
288 
289   /* The rest_count is the start index for checking $fp/$gp/$lp.  */
290   index = rest_count;
291   /* If index < 0, this parallel rtx is definitely
292      not a valid stack push/pop operation.  */
293   if (index < 0)
294     return false;
295 
296   /* Check $fp/$gp/$lp one by one.
297      We use 'push_p' to pick up reg rtx and mem rtx.  */
298   if (save_fp)
299     {
300       elt = XVECEXP (op, 0, index);
301       elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
302       elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
303       index++;
304 
305       if (GET_CODE (elt_mem) != MEM
306 	  || GET_CODE (elt_reg) != REG
307 	  || REGNO (elt_reg) != FP_REGNUM)
308 	return false;
309     }
310   if (save_gp)
311     {
312       elt = XVECEXP (op, 0, index);
313       elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
314       elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
315       index++;
316 
317       if (GET_CODE (elt_mem) != MEM
318 	  || GET_CODE (elt_reg) != REG
319 	  || REGNO (elt_reg) != GP_REGNUM)
320 	return false;
321     }
322   if (save_lp)
323     {
324       elt = XVECEXP (op, 0, index);
325       elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
326       elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
327       index++;
328 
329       if (GET_CODE (elt_mem) != MEM
330 	  || GET_CODE (elt_reg) != REG
331 	  || REGNO (elt_reg) != LP_REGNUM)
332 	return false;
333     }
334 
335   /* 3. The last element must be stack adjustment rtx.
336 	Its form of rtx should be:
337 	  (set (reg:SI SP_REGNUM)
338 	       (plus (reg:SI SP_REGNUM) (const_int X)))
339 	The X could be positive or negative value.  */
340 
341   /* Pick up the last element.  */
342   elt = XVECEXP (op, 0, total_count - 1);
343 
344   /* Extract its destination and source rtx.  */
345   elt_reg  = SET_DEST (elt);
346   elt_plus = SET_SRC (elt);
347 
348   /* Check this is (set (stack_reg) (plus stack_reg const)) pattern.  */
349   if (GET_CODE (elt_reg) != REG
350       || GET_CODE (elt_plus) != PLUS
351       || REGNO (elt_reg) != SP_REGNUM)
352     return false;
353 
354   /* Pass all test, this is a valid rtx.  */
355   return true;
356 }
357 
358 /* Function to check if 'bclr' instruction can be used with IVAL.  */
359 bool
nds32_can_use_bclr_p(HOST_WIDE_INT ival)360 nds32_can_use_bclr_p (HOST_WIDE_INT ival)
361 {
362   int one_bit_count;
363   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
364 
365   /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
366      it means the original ival has only one 0-bit,
367      So it is ok to perform 'bclr' operation.  */
368 
369   one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival) & mask);
370 
371   /* 'bclr' is a performance extension instruction.  */
372   return (TARGET_EXT_PERF && (one_bit_count == 1));
373 }
374 
375 /* Function to check if 'bset' instruction can be used with IVAL.  */
376 bool
nds32_can_use_bset_p(HOST_WIDE_INT ival)377 nds32_can_use_bset_p (HOST_WIDE_INT ival)
378 {
379   int one_bit_count;
380   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
381 
382   /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
383      it is ok to perform 'bset' operation.  */
384 
385   one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
386 
387   /* 'bset' is a performance extension instruction.  */
388   return (TARGET_EXT_PERF && (one_bit_count == 1));
389 }
390 
391 /* Function to check if 'btgl' instruction can be used with IVAL.  */
392 bool
nds32_can_use_btgl_p(HOST_WIDE_INT ival)393 nds32_can_use_btgl_p (HOST_WIDE_INT ival)
394 {
395   int one_bit_count;
396   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
397 
398   /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
399      it is ok to perform 'btgl' operation.  */
400 
401   one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
402 
403   /* 'btgl' is a performance extension instruction.  */
404   return (TARGET_EXT_PERF && (one_bit_count == 1));
405 }
406 
407 /* Function to check if 'bitci' instruction can be used with IVAL.  */
408 bool
nds32_can_use_bitci_p(HOST_WIDE_INT ival)409 nds32_can_use_bitci_p (HOST_WIDE_INT ival)
410 {
411   /* If we are using V3 ISA, we have 'bitci' instruction.
412      Try to see if we can present 'andi' semantic with
413      such 'bit-clear-immediate' operation.
414      For example, 'andi $r0,$r0,0xfffffffc' can be
415      presented with 'bitci $r0,$r0,3'.  */
416   return (TARGET_ISA_V3
417 	  && (ival < 0)
418 	  && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
419 }
420 
421 /* Return true if is load/store with SYMBOL_REF addressing mode
422    and memory mode is SImode.  */
423 bool
nds32_symbol_load_store_p(rtx_insn * insn)424 nds32_symbol_load_store_p (rtx_insn *insn)
425 {
426   rtx mem_src = NULL_RTX;
427 
428   switch (get_attr_type (insn))
429     {
430     case TYPE_LOAD:
431       mem_src = SET_SRC (PATTERN (insn));
432       break;
433     case TYPE_STORE:
434       mem_src = SET_DEST (PATTERN (insn));
435       break;
436     default:
437       break;
438     }
439 
440   /* Find load/store insn with addressing mode is SYMBOL_REF.  */
441   if (mem_src != NULL_RTX)
442     {
443       if ((GET_CODE (mem_src) == ZERO_EXTEND)
444 	  || (GET_CODE (mem_src) == SIGN_EXTEND))
445 	mem_src = XEXP (mem_src, 0);
446 
447       if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
448 	   || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
449 	return true;
450     }
451 
452   return false;
453 }
454 
455 /* Vaild memory operand for floating-point loads and stores */
456 bool
nds32_float_mem_operand_p(rtx op)457 nds32_float_mem_operand_p (rtx op)
458 {
459   machine_mode mode = GET_MODE (op);
460   rtx addr = XEXP (op, 0);
461 
462   /* Not support [symbol] [const] memory */
463   if (GET_CODE (addr) == SYMBOL_REF
464       || GET_CODE (addr) == CONST
465       || GET_CODE (addr) == LO_SUM)
466     return false;
467 
468   if (GET_CODE (addr) == PLUS)
469     {
470       if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
471 	return false;
472 
473       /* Restrict const range: (imm12s << 2) */
474       if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
475 	{
476 	  if ((mode == SImode || mode == SFmode)
477 	      && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
478 	      && !satisfies_constraint_Is14 ( XEXP(addr, 1)))
479 	    return false;
480 
481 	  if ((mode == DImode || mode == DFmode)
482 	      && NDS32_DOUBLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
483 	      && !satisfies_constraint_Is14 (XEXP (addr, 1)))
484 	    return false;
485 	}
486     }
487 
488   return true;
489 }
490 
491 int
nds32_cond_move_p(rtx cmp_rtx)492 nds32_cond_move_p (rtx cmp_rtx)
493 {
494   machine_mode cmp0_mode = GET_MODE (XEXP (cmp_rtx, 0));
495   machine_mode cmp1_mode = GET_MODE (XEXP (cmp_rtx, 1));
496   enum rtx_code cond = GET_CODE (cmp_rtx);
497 
498   if ((cmp0_mode == DFmode || cmp0_mode == SFmode)
499       && (cmp1_mode == DFmode || cmp1_mode == SFmode)
500       && (cond == ORDERED || cond == UNORDERED))
501     return true;
502   return false;
503 }
504 
505 bool
nds32_const_double_range_ok_p(rtx op,machine_mode mode,HOST_WIDE_INT lower,HOST_WIDE_INT upper)506 nds32_const_double_range_ok_p (rtx op, machine_mode mode,
507 			       HOST_WIDE_INT lower, HOST_WIDE_INT upper)
508 {
509   if (GET_CODE (op) != CONST_DOUBLE
510       || GET_MODE (op) != mode)
511     return false;
512 
513   const REAL_VALUE_TYPE *rv;
514   long val;
515 
516   rv = CONST_DOUBLE_REAL_VALUE (op);
517   REAL_VALUE_TO_TARGET_SINGLE (*rv, val);
518 
519   return val >= lower && val < upper;
520 }
521 
522 bool
nds32_const_unspec_p(rtx x)523 nds32_const_unspec_p (rtx x)
524 {
525   if (GET_CODE (x) == CONST)
526     {
527       x = XEXP (x, 0);
528 
529       if (GET_CODE (x) == PLUS)
530 	x = XEXP (x, 0);
531 
532       if (GET_CODE (x) == UNSPEC)
533 	{
534 	  switch (XINT (x, 1))
535 	    {
536 	    case UNSPEC_GOTINIT:
537 	    case UNSPEC_GOT:
538 	    case UNSPEC_GOTOFF:
539 	    case UNSPEC_PLT:
540 	    case UNSPEC_TLSGD:
541 	    case UNSPEC_TLSLD:
542 	    case UNSPEC_TLSIE:
543 	    case UNSPEC_TLSLE:
544 	      return false;
545 	    default:
546 	      return true;
547 	    }
548 	}
549     }
550 
551   if (GET_CODE (x) == SYMBOL_REF
552       && SYMBOL_REF_TLS_MODEL (x))
553     return false;
554 
555   return true;
556 }
557 
558 HOST_WIDE_INT
const_vector_to_hwint(rtx op)559 const_vector_to_hwint (rtx op)
560 {
561   HOST_WIDE_INT hwint = 0;
562   HOST_WIDE_INT mask;
563   int i;
564   int shift_adv;
565   int shift = 0;
566   int nelem;
567 
568   switch (GET_MODE (op))
569     {
570       case E_V2HImode:
571 	mask = 0xffff;
572 	shift_adv = 16;
573 	nelem = 2;
574 	break;
575       case E_V4QImode:
576 	mask = 0xff;
577 	shift_adv = 8;
578 	nelem = 4;
579 	break;
580       default:
581 	gcc_unreachable ();
582     }
583 
584   if (TARGET_BIG_ENDIAN)
585     {
586       for (i = 0; i < nelem; ++i)
587 	{
588 	  HOST_WIDE_INT val = XINT (XVECEXP (op, 0, nelem - i - 1), 0);
589 	  hwint |= (val & mask) << shift;
590 	  shift = shift + shift_adv;
591 	}
592     }
593   else
594     {
595       for (i = 0; i < nelem; ++i)
596 	{
597 	  HOST_WIDE_INT val = XINT (XVECEXP (op, 0, i), 0);
598 	  hwint |= (val & mask) << shift;
599 	  shift = shift + shift_adv;
600 	}
601     }
602 
603   return hwint;
604 }
605 
606 bool
nds32_valid_CVp5_p(rtx op)607 nds32_valid_CVp5_p (rtx op)
608 {
609   HOST_WIDE_INT ival = const_vector_to_hwint (op);
610   return (ival < ((1 << 5) + 16)) && (ival >= (0 + 16));
611 }
612 
613 bool
nds32_valid_CVs5_p(rtx op)614 nds32_valid_CVs5_p (rtx op)
615 {
616   HOST_WIDE_INT ival = const_vector_to_hwint (op);
617   return (ival < (1 << 4)) && (ival >= -(1 << 4));
618 }
619 
620 bool
nds32_valid_CVs2_p(rtx op)621 nds32_valid_CVs2_p (rtx op)
622 {
623   HOST_WIDE_INT ival = const_vector_to_hwint (op);
624   return (ival < (1 << 19)) && (ival >= -(1 << 19));
625 }
626 
627 bool
nds32_valid_CVhi_p(rtx op)628 nds32_valid_CVhi_p (rtx op)
629 {
630   HOST_WIDE_INT ival = const_vector_to_hwint (op);
631   return (ival != 0) && ((ival & 0xfff) == 0);
632 }
633 
634 /* ------------------------------------------------------------------------ */
635