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