111
|
1 /* Predicate functions of Andes NDS32 cpu for GNU compiler
|
131
|
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
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
|
131
|
23 #define IN_TARGET_CODE 1
|
|
24
|
111
|
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"
|
131
|
38 #include "insn-attr.h"
|
111
|
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
|
|
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
|
131
|
105 nds32_valid_multiple_load_store_p (rtx op, bool load_p, bool bim_p)
|
111
|
106 {
|
|
107 int count;
|
|
108 int first_elt_regno;
|
131
|
109 int update_base_elt_idx;
|
|
110 int offset;
|
111
|
111 rtx elt;
|
131
|
112 rtx update_base;
|
111
|
113
|
131
|
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 }
|
111
|
127
|
|
128 /* Perform some quick check for the first element in the parallel rtx. */
|
|
129 if (GET_CODE (elt) != SET
|
|
130 || count <= 1
|
131
|
131 || count > 25)
|
111
|
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. */
|
131
|
157 if (!nds32_consecutive_registers_load_store_p (op, load_p, bim_p ? 1 : 0,
|
111
|
158 first_elt_regno,
|
|
159 count))
|
|
160 return false;
|
|
161
|
131
|
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
|
111
|
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
|
|
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. */
|
131
|
359 bool
|
|
360 nds32_can_use_bclr_p (HOST_WIDE_INT ival)
|
111
|
361 {
|
|
362 int one_bit_count;
|
131
|
363 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
|
111
|
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
|
131
|
369 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival) & mask);
|
111
|
370
|
|
371 /* 'bclr' is a performance extension instruction. */
|
131
|
372 return (TARGET_EXT_PERF && (one_bit_count == 1));
|
111
|
373 }
|
|
374
|
|
375 /* Function to check if 'bset' instruction can be used with IVAL. */
|
131
|
376 bool
|
|
377 nds32_can_use_bset_p (HOST_WIDE_INT ival)
|
111
|
378 {
|
|
379 int one_bit_count;
|
131
|
380 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
|
111
|
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
|
131
|
385 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
|
111
|
386
|
|
387 /* 'bset' is a performance extension instruction. */
|
131
|
388 return (TARGET_EXT_PERF && (one_bit_count == 1));
|
111
|
389 }
|
|
390
|
|
391 /* Function to check if 'btgl' instruction can be used with IVAL. */
|
131
|
392 bool
|
|
393 nds32_can_use_btgl_p (HOST_WIDE_INT ival)
|
111
|
394 {
|
|
395 int one_bit_count;
|
131
|
396 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);
|
111
|
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
|
131
|
401 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);
|
111
|
402
|
|
403 /* 'btgl' is a performance extension instruction. */
|
131
|
404 return (TARGET_EXT_PERF && (one_bit_count == 1));
|
111
|
405 }
|
|
406
|
|
407 /* Function to check if 'bitci' instruction can be used with IVAL. */
|
131
|
408 bool
|
|
409 nds32_can_use_bitci_p (HOST_WIDE_INT ival)
|
111
|
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
|
131
|
421 /* Return true if is load/store with SYMBOL_REF addressing mode
|
|
422 and memory mode is SImode. */
|
|
423 bool
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
111
|
634 /* ------------------------------------------------------------------------ */
|