1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2019 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