0
|
1 ;; Predicate definitions for Renesas / SuperH SH.
|
|
2 ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
|
3 ;;
|
|
4 ;; This file is part of GCC.
|
|
5 ;;
|
|
6 ;; GCC is free software; you can redistribute it and/or modify
|
|
7 ;; it under the terms of the GNU General Public License as published by
|
|
8 ;; the Free Software Foundation; either version 3, or (at your option)
|
|
9 ;; any later version.
|
|
10 ;;
|
|
11 ;; GCC is distributed in the hope that it will be useful,
|
|
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 ;; GNU General Public License for more details.
|
|
15 ;;
|
|
16 ;; You should have received a copy of the GNU General Public License
|
|
17 ;; along with GCC; see the file COPYING3. If not see
|
|
18 ;; <http://www.gnu.org/licenses/>.
|
|
19
|
|
20 ;; TODO: Add a comment here.
|
|
21
|
|
22 (define_predicate "trapping_target_operand"
|
|
23 (match_code "if_then_else")
|
|
24 {
|
|
25 rtx cond, mem, res, tar, and;
|
|
26
|
|
27 if (GET_MODE (op) != PDImode)
|
|
28 return 0;
|
|
29 cond = XEXP (op, 0);
|
|
30 mem = XEXP (op, 1);
|
|
31 res = XEXP (op, 2);
|
|
32 if (GET_CODE (mem) != MEM
|
|
33 || (GET_CODE (res) != SIGN_EXTEND && GET_CODE (res) != TRUNCATE))
|
|
34 return 0;
|
|
35 tar = XEXP (res, 0);
|
|
36 if (!rtx_equal_p (XEXP (mem, 0), tar)
|
|
37 || GET_MODE (tar) != Pmode)
|
|
38 return 0;
|
|
39 if (GET_CODE (cond) == CONST)
|
|
40 {
|
|
41 cond = XEXP (cond, 0);
|
|
42 if (!satisfies_constraint_Csy (tar))
|
|
43 return 0;
|
|
44 if (GET_CODE (tar) == CONST)
|
|
45 tar = XEXP (tar, 0);
|
|
46 }
|
|
47 else if (!arith_reg_operand (tar, VOIDmode)
|
|
48 && ! satisfies_constraint_Csy (tar))
|
|
49 return 0;
|
|
50 if (GET_CODE (cond) != EQ)
|
|
51 return 0;
|
|
52 and = XEXP (cond, 0);
|
|
53 return (GET_CODE (and) == AND
|
|
54 && rtx_equal_p (XEXP (and, 0), tar)
|
|
55 && GET_CODE (XEXP (and, 1)) == CONST_INT
|
|
56 && GET_CODE (XEXP (cond, 1)) == CONST_INT
|
|
57 && INTVAL (XEXP (and, 1)) == 3
|
|
58 && INTVAL (XEXP (cond, 1)) == 3);
|
|
59 })
|
|
60
|
|
61 ;; TODO: Add a comment here.
|
|
62
|
|
63 (define_predicate "and_operand"
|
|
64 (match_code "subreg,reg,const_int")
|
|
65 {
|
|
66 if (logical_operand (op, mode))
|
|
67 return 1;
|
|
68
|
|
69 /* Check mshflo.l / mshflhi.l opportunities. */
|
|
70 if (TARGET_SHMEDIA
|
|
71 && mode == DImode
|
|
72 && satisfies_constraint_J16 (op))
|
|
73 return 1;
|
|
74
|
|
75 return 0;
|
|
76 })
|
|
77
|
|
78 ;; Like arith_reg_dest, but this predicate is defined with
|
|
79 ;; define_special_predicate, not define_predicate.
|
|
80
|
|
81 (define_special_predicate "any_arith_reg_dest"
|
|
82 (match_code "subreg,reg")
|
|
83 {
|
|
84 return arith_reg_dest (op, mode);
|
|
85 })
|
|
86
|
|
87 ;; Like register_operand, but this predicate is defined with
|
|
88 ;; define_special_predicate, not define_predicate.
|
|
89
|
|
90 (define_special_predicate "any_register_operand"
|
|
91 (match_code "subreg,reg")
|
|
92 {
|
|
93 return register_operand (op, mode);
|
|
94 })
|
|
95
|
|
96 ;; Returns 1 if OP is a valid source operand for an arithmetic insn.
|
|
97
|
|
98 (define_predicate "arith_operand"
|
|
99 (match_code "subreg,reg,const_int,truncate")
|
|
100 {
|
|
101 if (arith_reg_operand (op, mode))
|
|
102 return 1;
|
|
103
|
|
104 if (TARGET_SHMEDIA)
|
|
105 {
|
|
106 /* FIXME: We should be checking whether the CONST_INT fits in a
|
|
107 signed 16-bit here, but this causes reload_cse to crash when
|
|
108 attempting to transform a sequence of two 64-bit sets of the
|
|
109 same register from literal constants into a set and an add,
|
|
110 when the difference is too wide for an add. */
|
|
111 if (GET_CODE (op) == CONST_INT
|
|
112 || satisfies_constraint_Css (op))
|
|
113 return 1;
|
|
114 else if (GET_CODE (op) == TRUNCATE
|
|
115 && GET_CODE (XEXP (op, 0)) == REG
|
|
116 && ! system_reg_operand (XEXP (op, 0), VOIDmode)
|
|
117 && (mode == VOIDmode || mode == GET_MODE (op))
|
|
118 && (GET_MODE_SIZE (GET_MODE (op))
|
|
119 < GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
|
|
120 && (! FP_REGISTER_P (REGNO (XEXP (op, 0)))
|
|
121 || GET_MODE_SIZE (GET_MODE (op)) == 4))
|
|
122 return register_operand (XEXP (op, 0), VOIDmode);
|
|
123 else
|
|
124 return 0;
|
|
125 }
|
|
126 else if (satisfies_constraint_I08 (op))
|
|
127 return 1;
|
|
128
|
|
129 return 0;
|
|
130 })
|
|
131
|
|
132 ;; Like above, but for DImode destinations: forbid paradoxical DImode
|
|
133 ;; subregs, because this would lead to missing sign extensions when
|
|
134 ;; truncating from DImode to SImode.
|
|
135
|
|
136 (define_predicate "arith_reg_dest"
|
|
137 (match_code "subreg,reg")
|
|
138 {
|
|
139 if (mode == DImode && GET_CODE (op) == SUBREG
|
|
140 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8
|
|
141 && TARGET_SHMEDIA)
|
|
142 return 0;
|
|
143 return arith_reg_operand (op, mode);
|
|
144 })
|
|
145
|
|
146 ;; Returns 1 if OP is a normal arithmetic register.
|
|
147
|
|
148 (define_predicate "arith_reg_operand"
|
|
149 (match_code "subreg,reg,sign_extend")
|
|
150 {
|
|
151 if (register_operand (op, mode))
|
|
152 {
|
|
153 int regno;
|
|
154
|
|
155 if (GET_CODE (op) == REG)
|
|
156 regno = REGNO (op);
|
|
157 else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
|
|
158 regno = REGNO (SUBREG_REG (op));
|
|
159 else
|
|
160 return 1;
|
|
161
|
|
162 return (regno != T_REG && regno != PR_REG
|
|
163 && ! TARGET_REGISTER_P (regno)
|
|
164 && (regno != FPUL_REG || TARGET_SH4)
|
|
165 && regno != MACH_REG && regno != MACL_REG);
|
|
166 }
|
|
167 /* Allow a no-op sign extension - compare LOAD_EXTEND_OP.
|
|
168 We allow SImode here, as not using an FP register is just a matter of
|
|
169 proper register allocation. */
|
|
170 if (TARGET_SHMEDIA
|
|
171 && GET_MODE (op) == DImode && GET_CODE (op) == SIGN_EXTEND
|
|
172 && GET_MODE (XEXP (op, 0)) == SImode
|
|
173 && GET_CODE (XEXP (op, 0)) != SUBREG)
|
|
174 return register_operand (XEXP (op, 0), VOIDmode);
|
|
175 #if 0 /* Can't do this because of PROMOTE_MODE for unsigned vars. */
|
|
176 if (GET_MODE (op) == SImode && GET_CODE (op) == SIGN_EXTEND
|
|
177 && GET_MODE (XEXP (op, 0)) == HImode
|
|
178 && GET_CODE (XEXP (op, 0)) == REG
|
|
179 && REGNO (XEXP (op, 0)) <= LAST_GENERAL_REG)
|
|
180 return register_operand (XEXP (op, 0), VOIDmode);
|
|
181 #endif
|
|
182 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_INT
|
|
183 && GET_CODE (op) == SUBREG
|
|
184 && GET_MODE (SUBREG_REG (op)) == DImode
|
|
185 && GET_CODE (SUBREG_REG (op)) == SIGN_EXTEND
|
|
186 && GET_MODE (XEXP (SUBREG_REG (op), 0)) == SImode
|
|
187 && GET_CODE (XEXP (SUBREG_REG (op), 0)) != SUBREG)
|
|
188 return register_operand (XEXP (SUBREG_REG (op), 0), VOIDmode);
|
|
189 return 0;
|
|
190 })
|
|
191
|
|
192 ;; Returns 1 if OP is a valid source operand for a compare insn.
|
|
193
|
|
194 (define_predicate "arith_reg_or_0_operand"
|
|
195 (match_code "subreg,reg,const_int,const_vector")
|
|
196 {
|
|
197 if (arith_reg_operand (op, mode))
|
|
198 return 1;
|
|
199
|
|
200 if (satisfies_constraint_Z (op))
|
|
201 return 1;
|
|
202
|
|
203 return 0;
|
|
204 })
|
|
205
|
|
206 ;; TODO: Add a comment here.
|
|
207
|
|
208 (define_predicate "binary_float_operator"
|
|
209 (and (match_code "plus,minus,mult,div")
|
|
210 (match_test "GET_MODE (op) == mode")))
|
|
211
|
|
212 ;; TODO: Add a comment here.
|
|
213
|
|
214 (define_predicate "binary_logical_operator"
|
|
215 (and (match_code "and,ior,xor")
|
|
216 (match_test "GET_MODE (op) == mode")))
|
|
217
|
|
218 ;; Return 1 of OP is an address suitable for a cache manipulation operation.
|
|
219 ;; MODE has the meaning as in address_operand.
|
|
220
|
|
221 (define_special_predicate "cache_address_operand"
|
|
222 (match_code "plus,reg")
|
|
223 {
|
|
224 if (GET_CODE (op) == PLUS)
|
|
225 {
|
|
226 if (GET_CODE (XEXP (op, 0)) != REG)
|
|
227 return 0;
|
|
228 if (GET_CODE (XEXP (op, 1)) != CONST_INT
|
|
229 || (INTVAL (XEXP (op, 1)) & 31))
|
|
230 return 0;
|
|
231 }
|
|
232 else if (GET_CODE (op) != REG)
|
|
233 return 0;
|
|
234 return address_operand (op, mode);
|
|
235 })
|
|
236
|
|
237 ;; Return 1 if OP is a valid source operand for shmedia cmpgt / cmpgtu.
|
|
238
|
|
239 (define_predicate "cmp_operand"
|
|
240 (match_code "subreg,reg,const_int")
|
|
241 {
|
|
242 if (satisfies_constraint_N (op))
|
|
243 return 1;
|
|
244 if (TARGET_SHMEDIA
|
|
245 && mode != DImode && GET_CODE (op) == SUBREG
|
|
246 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4)
|
|
247 return 0;
|
|
248 return arith_reg_operand (op, mode);
|
|
249 })
|
|
250
|
|
251 ;; TODO: Add a comment here.
|
|
252
|
|
253 (define_predicate "cmpsi_operand"
|
|
254 (match_code "subreg,reg,const_int")
|
|
255 {
|
|
256 if (GET_CODE (op) == REG && REGNO (op) == T_REG
|
|
257 && GET_MODE (op) == SImode
|
|
258 && TARGET_SH1)
|
|
259 return 1;
|
|
260 return arith_operand (op, mode);
|
|
261 })
|
|
262
|
|
263 ;; TODO: Add a comment here.
|
|
264
|
|
265 (define_predicate "commutative_float_operator"
|
|
266 (and (match_code "plus,mult")
|
|
267 (match_test "GET_MODE (op) == mode")))
|
|
268
|
|
269 ;; TODO: Add a comment here.
|
|
270
|
|
271 (define_predicate "equality_comparison_operator"
|
|
272 (match_code "eq,ne"))
|
|
273
|
|
274 ;; TODO: Add a comment here.
|
|
275
|
|
276 (define_predicate "extend_reg_operand"
|
|
277 (match_code "subreg,reg,truncate")
|
|
278 {
|
|
279 return (GET_CODE (op) == TRUNCATE
|
|
280 ? arith_operand
|
|
281 : arith_reg_operand) (op, mode);
|
|
282 })
|
|
283
|
|
284 ;; TODO: Add a comment here.
|
|
285
|
|
286 (define_predicate "extend_reg_or_0_operand"
|
|
287 (match_code "subreg,reg,truncate,const_int")
|
|
288 {
|
|
289 return (GET_CODE (op) == TRUNCATE
|
|
290 ? arith_operand
|
|
291 : arith_reg_or_0_operand) (op, mode);
|
|
292 })
|
|
293
|
|
294 ;; Like arith_reg_operand, but this predicate does not accept SIGN_EXTEND.
|
|
295
|
|
296 (define_predicate "ext_dest_operand"
|
|
297 (match_code "subreg,reg")
|
|
298 {
|
|
299 return arith_reg_operand (op, mode);
|
|
300 })
|
|
301
|
|
302 ;; TODO: Add a comment here.
|
|
303
|
|
304 (define_predicate "fp_arith_reg_dest"
|
|
305 (match_code "subreg,reg")
|
|
306 {
|
|
307 if (mode == DImode && GET_CODE (op) == SUBREG
|
|
308 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8)
|
|
309 return 0;
|
|
310 return fp_arith_reg_operand (op, mode);
|
|
311 })
|
|
312
|
|
313 ;; TODO: Add a comment here.
|
|
314
|
|
315 (define_predicate "fp_arith_reg_operand"
|
|
316 (match_code "subreg,reg")
|
|
317 {
|
|
318 if (register_operand (op, mode))
|
|
319 {
|
|
320 int regno;
|
|
321
|
|
322 if (GET_CODE (op) == REG)
|
|
323 regno = REGNO (op);
|
|
324 else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
|
|
325 regno = REGNO (SUBREG_REG (op));
|
|
326 else
|
|
327 return 1;
|
|
328
|
|
329 return (regno >= FIRST_PSEUDO_REGISTER
|
|
330 || FP_REGISTER_P (regno));
|
|
331 }
|
|
332 return 0;
|
|
333 })
|
|
334
|
|
335 ;; TODO: Add a comment here.
|
|
336
|
|
337 (define_predicate "fpscr_operand"
|
|
338 (match_code "reg")
|
|
339 {
|
|
340 return (GET_CODE (op) == REG
|
|
341 && (REGNO (op) == FPSCR_REG
|
|
342 || (REGNO (op) >= FIRST_PSEUDO_REGISTER
|
|
343 && !(reload_in_progress || reload_completed)))
|
|
344 && GET_MODE (op) == PSImode);
|
|
345 })
|
|
346
|
|
347 ;; TODO: Add a comment here.
|
|
348
|
|
349 (define_predicate "fpul_operand"
|
|
350 (match_code "reg")
|
|
351 {
|
|
352 if (TARGET_SHMEDIA)
|
|
353 return fp_arith_reg_operand (op, mode);
|
|
354
|
|
355 return (GET_CODE (op) == REG
|
|
356 && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER)
|
|
357 && GET_MODE (op) == mode);
|
|
358 })
|
|
359
|
|
360 ;; TODO: Add a comment here.
|
|
361
|
|
362 (define_predicate "general_extend_operand"
|
|
363 (match_code "subreg,reg,mem,truncate")
|
|
364 {
|
|
365 return (GET_CODE (op) == TRUNCATE
|
|
366 ? arith_operand
|
|
367 : nonimmediate_operand) (op, mode);
|
|
368 })
|
|
369
|
|
370 ;; Returns 1 if OP can be source of a simple move operation. Same as
|
|
371 ;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as
|
|
372 ;; are subregs of system registers.
|
|
373
|
|
374 (define_predicate "general_movsrc_operand"
|
|
375 (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,label_ref,const,const_vector")
|
|
376 {
|
|
377 if (GET_CODE (op) == MEM)
|
|
378 {
|
|
379 rtx inside = XEXP (op, 0);
|
|
380 if (GET_CODE (inside) == CONST)
|
|
381 inside = XEXP (inside, 0);
|
|
382
|
|
383 if (GET_CODE (inside) == LABEL_REF)
|
|
384 return 1;
|
|
385
|
|
386 if (GET_CODE (inside) == PLUS
|
|
387 && GET_CODE (XEXP (inside, 0)) == LABEL_REF
|
|
388 && GET_CODE (XEXP (inside, 1)) == CONST_INT)
|
|
389 return 1;
|
|
390
|
|
391 /* Only post inc allowed. */
|
|
392 if (GET_CODE (inside) == PRE_DEC)
|
|
393 return 0;
|
|
394 }
|
|
395
|
|
396 if (TARGET_SHMEDIA
|
|
397 && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR)
|
|
398 && sh_rep_vec (op, mode))
|
|
399 return 1;
|
|
400 if (TARGET_SHMEDIA && 1
|
|
401 && GET_CODE (op) == SUBREG && GET_MODE (op) == mode
|
|
402 && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op))
|
|
403 /* FIXME */ abort (); /* return 1; */
|
|
404 return general_operand (op, mode);
|
|
405 })
|
|
406
|
|
407 ;; Returns 1 if OP can be a destination of a move. Same as
|
|
408 ;; general_operand, but no preinc allowed.
|
|
409
|
|
410 (define_predicate "general_movdst_operand"
|
|
411 (match_code "subreg,reg,mem")
|
|
412 {
|
|
413 /* Only pre dec allowed. */
|
|
414 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
|
|
415 return 0;
|
|
416 if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG
|
|
417 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8
|
|
418 && ! (high_life_started || reload_completed))
|
|
419 return 0;
|
|
420
|
|
421 return general_operand (op, mode);
|
|
422 })
|
|
423
|
|
424 ;; Returns 1 if OP is a MEM that can be source of a simple move operation.
|
|
425
|
|
426 (define_predicate "unaligned_load_operand"
|
|
427 (match_code "mem")
|
|
428 {
|
|
429 rtx inside;
|
|
430
|
|
431 if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
|
|
432 return 0;
|
|
433
|
|
434 inside = XEXP (op, 0);
|
|
435
|
|
436 if (GET_CODE (inside) == POST_INC)
|
|
437 inside = XEXP (inside, 0);
|
|
438
|
|
439 if (GET_CODE (inside) == REG)
|
|
440 return 1;
|
|
441
|
|
442 return 0;
|
|
443 })
|
|
444
|
|
445 ;; TODO: Add a comment here.
|
|
446
|
|
447 (define_predicate "greater_comparison_operator"
|
|
448 (match_code "gt,ge,gtu,geu"))
|
|
449
|
|
450 ;; TODO: Add a comment here.
|
|
451
|
|
452 (define_predicate "inqhi_operand"
|
|
453 (match_code "truncate")
|
|
454 {
|
|
455 if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op))
|
|
456 return 0;
|
|
457 op = XEXP (op, 0);
|
|
458 /* Can't use true_regnum here because copy_cost wants to know about
|
|
459 SECONDARY_INPUT_RELOAD_CLASS. */
|
|
460 return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op));
|
|
461 })
|
|
462
|
|
463 ;; TODO: Add a comment here.
|
|
464
|
|
465 (define_special_predicate "int_gpr_dest"
|
|
466 (match_code "subreg,reg")
|
|
467 {
|
|
468 enum machine_mode op_mode = GET_MODE (op);
|
|
469
|
|
470 if (GET_MODE_CLASS (op_mode) != MODE_INT
|
|
471 || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD)
|
|
472 return 0;
|
|
473 if (! reload_completed)
|
|
474 return 0;
|
|
475 return true_regnum (op) <= LAST_GENERAL_REG;
|
|
476 })
|
|
477
|
|
478 ;; TODO: Add a comment here.
|
|
479
|
|
480 (define_predicate "less_comparison_operator"
|
|
481 (match_code "lt,le,ltu,leu"))
|
|
482
|
|
483 ;; Returns 1 if OP is a valid source operand for a logical operation.
|
|
484
|
|
485 (define_predicate "logical_operand"
|
|
486 (match_code "subreg,reg,const_int")
|
|
487 {
|
|
488 if (TARGET_SHMEDIA
|
|
489 && mode != DImode && GET_CODE (op) == SUBREG
|
|
490 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4)
|
|
491 return 0;
|
|
492
|
|
493 if (arith_reg_operand (op, mode))
|
|
494 return 1;
|
|
495
|
|
496 if (TARGET_SHMEDIA)
|
|
497 {
|
|
498 if (satisfies_constraint_I10 (op))
|
|
499 return 1;
|
|
500 else
|
|
501 return 0;
|
|
502 }
|
|
503 else if (satisfies_constraint_K08 (op))
|
|
504 return 1;
|
|
505
|
|
506 return 0;
|
|
507 })
|
|
508
|
|
509 ;; TODO: Add a comment here.
|
|
510
|
|
511 (define_predicate "logical_operator"
|
|
512 (match_code "and,ior,xor"))
|
|
513
|
|
514 ;; Like arith_reg_operand, but for register source operands of narrow
|
|
515 ;; logical SHMEDIA operations: forbid subregs of DImode / TImode regs.
|
|
516
|
|
517 (define_predicate "logical_reg_operand"
|
|
518 (match_code "subreg,reg")
|
|
519 {
|
|
520 if (TARGET_SHMEDIA
|
|
521 && GET_CODE (op) == SUBREG
|
|
522 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4
|
|
523 && mode != DImode)
|
|
524 return 0;
|
|
525 return arith_reg_operand (op, mode);
|
|
526 })
|
|
527
|
|
528 ;; TODO: Add a comment here.
|
|
529
|
|
530 (define_predicate "mextr_bit_offset"
|
|
531 (match_code "const_int")
|
|
532 {
|
|
533 HOST_WIDE_INT i;
|
|
534
|
|
535 if (GET_CODE (op) != CONST_INT)
|
|
536 return 0;
|
|
537 i = INTVAL (op);
|
|
538 return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0;
|
|
539 })
|
|
540
|
|
541 ;; TODO: Add a comment here.
|
|
542
|
|
543 (define_predicate "minuend_operand"
|
|
544 (match_code "subreg,reg,truncate,const_int")
|
|
545 {
|
|
546 return op == constm1_rtx || extend_reg_or_0_operand (op, mode);
|
|
547 })
|
|
548
|
|
549 ;; TODO: Add a comment here.
|
|
550
|
|
551 (define_predicate "noncommutative_float_operator"
|
|
552 (and (match_code "minus,div")
|
|
553 (match_test "GET_MODE (op) == mode")))
|
|
554
|
|
555 ;; TODO: Add a comment here.
|
|
556
|
|
557 (define_predicate "sh_const_vec"
|
|
558 (match_code "const_vector")
|
|
559 {
|
|
560 int i;
|
|
561
|
|
562 if (GET_CODE (op) != CONST_VECTOR
|
|
563 || (GET_MODE (op) != mode && mode != VOIDmode))
|
|
564 return 0;
|
|
565 i = XVECLEN (op, 0) - 1;
|
|
566 for (; i >= 0; i--)
|
|
567 if (GET_CODE (XVECEXP (op, 0, i)) != CONST_INT)
|
|
568 return 0;
|
|
569 return 1;
|
|
570 })
|
|
571
|
|
572 ;; Determine if OP is a constant vector matching MODE with only one
|
|
573 ;; element that is not a sign extension. Two byte-sized elements
|
|
574 ;; count as one.
|
|
575
|
|
576 (define_predicate "sh_1el_vec"
|
|
577 (match_code "const_vector")
|
|
578 {
|
|
579 int unit_size;
|
|
580 int i, last, least, sign_ix;
|
|
581 rtx sign;
|
|
582
|
|
583 if (GET_CODE (op) != CONST_VECTOR
|
|
584 || (GET_MODE (op) != mode && mode != VOIDmode))
|
|
585 return 0;
|
|
586 /* Determine numbers of last and of least significant elements. */
|
|
587 last = XVECLEN (op, 0) - 1;
|
|
588 least = TARGET_LITTLE_ENDIAN ? 0 : last;
|
|
589 if (GET_CODE (XVECEXP (op, 0, least)) != CONST_INT)
|
|
590 return 0;
|
|
591 sign_ix = least;
|
|
592 if (GET_MODE_UNIT_SIZE (mode) == 1)
|
|
593 sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1;
|
|
594 if (GET_CODE (XVECEXP (op, 0, sign_ix)) != CONST_INT)
|
|
595 return 0;
|
|
596 unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op));
|
|
597 sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1)
|
|
598 ? constm1_rtx : const0_rtx);
|
|
599 i = XVECLEN (op, 0) - 1;
|
|
600 do
|
|
601 if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign)
|
|
602 return 0;
|
|
603 while (--i);
|
|
604 return 1;
|
|
605 })
|
|
606
|
|
607 ;; Like register_operand, but take into account that SHMEDIA can use
|
|
608 ;; the constant zero like a general register.
|
|
609
|
|
610 (define_predicate "sh_register_operand"
|
|
611 (match_code "reg,subreg,const_int,const_double")
|
|
612 {
|
|
613 if (op == CONST0_RTX (mode) && TARGET_SHMEDIA)
|
|
614 return 1;
|
|
615 return register_operand (op, mode);
|
|
616 })
|
|
617
|
|
618 ;; TODO: Add a comment here.
|
|
619
|
|
620 (define_predicate "sh_rep_vec"
|
|
621 (match_code "const_vector,parallel")
|
|
622 {
|
|
623 int i;
|
|
624 rtx x, y;
|
|
625
|
|
626 if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL)
|
|
627 || (GET_MODE (op) != mode && mode != VOIDmode))
|
|
628 return 0;
|
|
629 i = XVECLEN (op, 0) - 2;
|
|
630 x = XVECEXP (op, 0, i + 1);
|
|
631 if (GET_MODE_UNIT_SIZE (mode) == 1)
|
|
632 {
|
|
633 y = XVECEXP (op, 0, i);
|
|
634 for (i -= 2; i >= 0; i -= 2)
|
|
635 if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x)
|
|
636 || ! rtx_equal_p (XVECEXP (op, 0, i), y))
|
|
637 return 0;
|
|
638 }
|
|
639 else
|
|
640 for (; i >= 0; i--)
|
|
641 if (XVECEXP (op, 0, i) != x)
|
|
642 return 0;
|
|
643 return 1;
|
|
644 })
|
|
645
|
|
646 ;; TODO: Add a comment here.
|
|
647
|
|
648 (define_predicate "shift_count_operand"
|
|
649 (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend")
|
|
650 {
|
|
651 return (CONSTANT_P (op)
|
|
652 ? (GET_CODE (op) == CONST_INT
|
|
653 ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode)
|
|
654 : nonmemory_operand (op, mode))
|
|
655 : shift_count_reg_operand (op, mode));
|
|
656 })
|
|
657
|
|
658 ;; TODO: Add a comment here.
|
|
659
|
|
660 (define_predicate "shift_count_reg_operand"
|
|
661 (match_code "subreg,reg,zero_extend,sign_extend")
|
|
662 {
|
|
663 if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND
|
|
664 || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0))
|
|
665 && (mode == VOIDmode || mode == GET_MODE (op))
|
|
666 && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6
|
|
667 && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT)
|
|
668 {
|
|
669 mode = VOIDmode;
|
|
670 do
|
|
671 op = XEXP (op, 0);
|
|
672 while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND
|
|
673 || GET_CODE (op) == TRUNCATE)
|
|
674 && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6
|
|
675 && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT);
|
|
676
|
|
677 }
|
|
678 return arith_reg_operand (op, mode);
|
|
679 })
|
|
680
|
|
681 ;; TODO: Add a comment here.
|
|
682
|
|
683 (define_predicate "shift_operator"
|
|
684 (match_code "ashift,ashiftrt,lshiftrt"))
|
|
685
|
|
686 ;; TODO: Add a comment here.
|
|
687
|
|
688 (define_predicate "symbol_ref_operand"
|
|
689 (match_code "symbol_ref"))
|
|
690
|
|
691 ;; Same as target_reg_operand, except that label_refs and symbol_refs
|
|
692 ;; are accepted before reload.
|
|
693
|
|
694 (define_special_predicate "target_operand"
|
|
695 (match_code "subreg,reg,label_ref,symbol_ref,const,unspec")
|
|
696 {
|
|
697 if (mode != VOIDmode && mode != Pmode)
|
|
698 return 0;
|
|
699
|
|
700 if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode)
|
|
701 && satisfies_constraint_Csy (op))
|
|
702 return ! reload_completed;
|
|
703
|
|
704 return target_reg_operand (op, mode);
|
|
705 })
|
|
706
|
|
707 ;; Accept pseudos and branch target registers.
|
|
708
|
|
709 (define_special_predicate "target_reg_operand"
|
|
710 (match_code "subreg,reg")
|
|
711 {
|
|
712 if (mode == VOIDmode
|
|
713 ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode
|
|
714 : mode != GET_MODE (op))
|
|
715 return 0;
|
|
716
|
|
717 if (GET_CODE (op) == SUBREG)
|
|
718 op = XEXP (op, 0);
|
|
719
|
|
720 if (GET_CODE (op) != REG)
|
|
721 return 0;
|
|
722
|
|
723 /* We must protect ourselves from matching pseudos that are virtual
|
|
724 register, because they will eventually be replaced with hardware
|
|
725 registers that aren't branch-target registers. */
|
|
726 if (REGNO (op) > LAST_VIRTUAL_REGISTER
|
|
727 || TARGET_REGISTER_P (REGNO (op)))
|
|
728 return 1;
|
|
729
|
|
730 return 0;
|
|
731 })
|
|
732
|
|
733 ;; TODO: Add a comment here.
|
|
734
|
|
735 (define_special_predicate "trunc_hi_operand"
|
|
736 (match_code "subreg,reg,truncate")
|
|
737 {
|
|
738 enum machine_mode op_mode = GET_MODE (op);
|
|
739
|
|
740 if (op_mode != SImode && op_mode != DImode
|
|
741 && op_mode != V4HImode && op_mode != V2SImode)
|
|
742 return 0;
|
|
743 return extend_reg_operand (op, mode);
|
|
744 })
|
|
745
|
|
746 ;; Return 1 of OP is an address suitable for an unaligned access instruction.
|
|
747
|
|
748 (define_special_predicate "ua_address_operand"
|
|
749 (match_code "subreg,reg,plus")
|
|
750 {
|
|
751 if (GET_CODE (op) == PLUS
|
|
752 && (! satisfies_constraint_I06 (XEXP (op, 1))))
|
|
753 return 0;
|
|
754 return address_operand (op, QImode);
|
|
755 })
|
|
756
|
|
757 ;; TODO: Add a comment here.
|
|
758
|
|
759 (define_predicate "ua_offset"
|
|
760 (match_code "const_int")
|
|
761 {
|
|
762 return satisfies_constraint_I06 (op);
|
|
763 })
|
|
764
|
|
765 ;; TODO: Add a comment here.
|
|
766
|
|
767 (define_predicate "unary_float_operator"
|
|
768 (and (match_code "abs,neg,sqrt")
|
|
769 (match_test "GET_MODE (op) == mode")))
|
|
770
|
|
771 ;; Return 1 if OP is a valid source operand for xor.
|
|
772
|
|
773 (define_predicate "xor_operand"
|
|
774 (match_code "subreg,reg,const_int")
|
|
775 {
|
|
776 if (GET_CODE (op) == CONST_INT)
|
|
777 return (TARGET_SHMEDIA
|
|
778 ? (satisfies_constraint_I06 (op)
|
|
779 || (!can_create_pseudo_p () && INTVAL (op) == 0xff))
|
|
780 : satisfies_constraint_K08 (op));
|
|
781 if (TARGET_SHMEDIA
|
|
782 && mode != DImode && GET_CODE (op) == SUBREG
|
|
783 && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4)
|
|
784 return 0;
|
|
785 return arith_reg_operand (op, mode);
|
|
786 })
|
|
787
|
|
788 (define_predicate "bitwise_memory_operand"
|
|
789 (match_code "mem")
|
|
790 {
|
|
791 if (GET_CODE (op) == MEM)
|
|
792 {
|
|
793 if (REG_P (XEXP (op, 0)))
|
|
794 return 1;
|
|
795
|
|
796 if (GET_CODE (XEXP (op, 0)) == PLUS
|
|
797 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
|
|
798 && satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1)))
|
|
799 return 1;
|
|
800 }
|
|
801 return 0;
|
|
802 })
|