1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GCC.
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.
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.
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/>. */
21 /* ------------------------------------------------------------------------ */
25 #include "coretypes.h"
32 #include "optabs.h" /* For GEN_FCN. */
35 #include "tm-constrs.h"
37 /* ------------------------------------------------------------------------ */
39 /* A subroutine that checks multiple load and store
40 using consecutive registers.
41 OP is a parallel rtx we would like to check.
42 LOAD_P indicates whether we are checking load operation.
43 PAR_INDEX is starting element of parallel rtx.
44 FIRST_ELT_REGNO is used to tell starting register number.
45 COUNT helps us to check consecutive register numbers. */
47 nds32_consecutive_registers_load_store_p (rtx op
,
59 for (i
= 0; i
< count
; i
++)
61 /* Pick up each element from parallel rtx. */
62 elt
= XVECEXP (op
, 0, i
+ par_index
);
64 /* If this element is not a 'set' rtx, return false immediately. */
65 if (GET_CODE (elt
) != SET
)
68 /* Pick up reg and mem of this element. */
69 elt_reg
= load_p
? SET_DEST (elt
) : SET_SRC (elt
);
70 elt_mem
= load_p
? SET_SRC (elt
) : SET_DEST (elt
);
72 /* If elt_reg is not a expected reg rtx, return false. */
73 if (GET_CODE (elt_reg
) != REG
|| GET_MODE (elt_reg
) != SImode
)
75 /* If elt_mem is not a expected mem rtx, return false. */
76 if (GET_CODE (elt_mem
) != MEM
|| GET_MODE (elt_mem
) != SImode
)
79 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
80 check_regno
= first_elt_regno
+ i
;
82 /* If the register number is not continuous, return false. */
83 if (REGNO (elt_reg
) != (unsigned int) check_regno
)
90 /* Function to check whether the OP is a valid load/store operation.
91 This is a helper function for the predicates:
92 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
93 in predicates.md file.
95 The OP is supposed to be a parallel rtx.
96 For each element within this parallel rtx:
97 (set (reg) (mem addr)) is the form for load operation.
98 (set (mem addr) (reg)) is the form for store operation.
99 We have to extract reg and mem of every element and
100 check if the information is valid for multiple load/store operation. */
102 nds32_valid_multiple_load_store (rtx op
, bool load_p
)
108 /* Get the counts of elements in the parallel rtx. */
109 count
= XVECLEN (op
, 0);
110 /* Pick up the first element. */
111 elt
= XVECEXP (op
, 0, 0);
113 /* Perform some quick check for the first element in the parallel rtx. */
114 if (GET_CODE (elt
) != SET
119 /* Pick up regno of first element for further detail checking.
120 Note that the form is different between load and store operation. */
123 if (GET_CODE (SET_DEST (elt
)) != REG
124 || GET_CODE (SET_SRC (elt
)) != MEM
)
127 first_elt_regno
= REGNO (SET_DEST (elt
));
131 if (GET_CODE (SET_SRC (elt
)) != REG
132 || GET_CODE (SET_DEST (elt
)) != MEM
)
135 first_elt_regno
= REGNO (SET_SRC (elt
));
138 /* Perform detail check for each element.
139 Refer to nds32-multiple.md for more information
140 about following checking.
141 The starting element of parallel rtx is index 0. */
142 if (!nds32_consecutive_registers_load_store_p (op
, load_p
, 0,
147 /* Pass all test, this is a valid rtx. */
151 /* Function to check whether the OP is a valid stack push/pop operation.
152 For a valid stack operation, it must satisfy following conditions:
153 1. Consecutive registers push/pop operations.
154 2. Valid $fp/$gp/$lp push/pop operations.
155 3. The last element must be stack adjustment rtx.
156 See the prologue/epilogue implementation for details. */
158 nds32_valid_stack_push_pop_p (rtx op
, bool push_p
)
164 int save_fp
, save_gp
, save_lp
;
170 /* Get the counts of elements in the parallel rtx. */
171 total_count
= XVECLEN (op
, 0);
173 /* Perform some quick check for that every element should be 'set'. */
174 for (index
= 0; index
< total_count
; index
++)
176 elt
= XVECEXP (op
, 0, index
);
177 if (GET_CODE (elt
) != SET
)
181 /* For push operation, the parallel rtx looks like:
182 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
184 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
187 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
189 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
191 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
193 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
195 (set (reg:SI SP_REGNUM)
196 (plus (reg:SI SP_REGNUM) (const_int -32)))])
198 For pop operation, the parallel rtx looks like:
199 (parallel [(set (reg:SI Rb)
200 (mem (reg:SI SP_REGNUM)))
202 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
205 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
206 (set (reg:SI FP_REGNUM)
207 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
208 (set (reg:SI GP_REGNUM)
209 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
210 (set (reg:SI LP_REGNUM)
211 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
212 (set (reg:SI SP_REGNUM)
213 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
215 /* 1. Consecutive registers push/pop operations.
216 We need to calculate how many registers should be consecutive.
217 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
218 and $lp push rtx are excluded. */
220 /* Detect whether we have $fp, $gp, or $lp in the parallel rtx. */
221 save_fp
= reg_mentioned_p (gen_rtx_REG (SImode
, FP_REGNUM
), op
);
222 save_gp
= reg_mentioned_p (gen_rtx_REG (SImode
, GP_REGNUM
), op
);
223 save_lp
= reg_mentioned_p (gen_rtx_REG (SImode
, LP_REGNUM
), op
);
224 /* Exclude last $sp adjustment rtx. */
225 rest_count
= total_count
- 1;
226 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
236 elt
= XVECEXP (op
, 0, 0);
237 /* Pick up register element. */
238 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
239 first_regno
= REGNO (elt_reg
);
241 /* The 'push' operation is a kind of store operation.
242 The 'pop' operation is a kind of load operation.
243 Pass corresponding false/true as second argument (bool load_p).
244 The par_index is supposed to start with index 0. */
245 if (!nds32_consecutive_registers_load_store_p (op
,
246 !push_p
? true : false,
253 /* 2. Valid $fp/$gp/$lp push/pop operations.
254 Remember to set start index for checking them. */
256 /* The rest_count is the start index for checking $fp/$gp/$lp. */
258 /* If index < 0, this parallel rtx is definitely
259 not a valid stack push/pop operation. */
263 /* Check $fp/$gp/$lp one by one.
264 We use 'push_p' to pick up reg rtx and mem rtx. */
267 elt
= XVECEXP (op
, 0, index
);
268 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
269 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
272 if (GET_CODE (elt_mem
) != MEM
273 || GET_CODE (elt_reg
) != REG
274 || REGNO (elt_reg
) != FP_REGNUM
)
279 elt
= XVECEXP (op
, 0, index
);
280 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
281 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
284 if (GET_CODE (elt_mem
) != MEM
285 || GET_CODE (elt_reg
) != REG
286 || REGNO (elt_reg
) != GP_REGNUM
)
291 elt
= XVECEXP (op
, 0, index
);
292 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
293 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
296 if (GET_CODE (elt_mem
) != MEM
297 || GET_CODE (elt_reg
) != REG
298 || REGNO (elt_reg
) != LP_REGNUM
)
302 /* 3. The last element must be stack adjustment rtx.
303 Its form of rtx should be:
304 (set (reg:SI SP_REGNUM)
305 (plus (reg:SI SP_REGNUM) (const_int X)))
306 The X could be positive or negative value. */
308 /* Pick up the last element. */
309 elt
= XVECEXP (op
, 0, total_count
- 1);
311 /* Extract its destination and source rtx. */
312 elt_reg
= SET_DEST (elt
);
313 elt_plus
= SET_SRC (elt
);
315 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
316 if (GET_CODE (elt_reg
) != REG
317 || GET_CODE (elt_plus
) != PLUS
318 || REGNO (elt_reg
) != SP_REGNUM
)
321 /* Pass all test, this is a valid rtx. */
325 /* Function to check if 'bclr' instruction can be used with IVAL. */
327 nds32_can_use_bclr_p (int ival
)
331 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
332 it means the original ival has only one 0-bit,
333 So it is ok to perform 'bclr' operation. */
335 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (~ival
));
337 /* 'bclr' is a performance extension instruction. */
338 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
341 /* Function to check if 'bset' instruction can be used with IVAL. */
343 nds32_can_use_bset_p (int ival
)
347 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
348 it is ok to perform 'bset' operation. */
350 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
352 /* 'bset' is a performance extension instruction. */
353 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
356 /* Function to check if 'btgl' instruction can be used with IVAL. */
358 nds32_can_use_btgl_p (int ival
)
362 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
363 it is ok to perform 'btgl' operation. */
365 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
367 /* 'btgl' is a performance extension instruction. */
368 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
371 /* Function to check if 'bitci' instruction can be used with IVAL. */
373 nds32_can_use_bitci_p (int ival
)
375 /* If we are using V3 ISA, we have 'bitci' instruction.
376 Try to see if we can present 'andi' semantic with
377 such 'bit-clear-immediate' operation.
378 For example, 'andi $r0,$r0,0xfffffffc' can be
379 presented with 'bitci $r0,$r0,3'. */
380 return (TARGET_ISA_V3
382 && satisfies_constraint_Iu15 (gen_int_mode (~ival
, SImode
)));
385 /* ------------------------------------------------------------------------ */