OSDN Git Service

7a55b8b480973ae17f79243ad4071cbf7c509a18
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / predicates.md
1 ;; Predicate definitions for Renesas / SuperH SH.
2 ;; Copyright (C) 2005, 2006 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 2, 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 COPYING.  If not, write to
18 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 ;; Boston, MA 02110-1301, USA.
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;
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 (GET_CODE (mem) != 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 (!EXTRA_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            && ! EXTRA_CONSTRAINT_Csy (tar))
50     return 0;
51   if (GET_CODE (cond) != EQ)
52     return 0;
53   and = XEXP (cond, 0);
54   return (GET_CODE (and) == AND
55           && rtx_equal_p (XEXP (and, 0), tar)
56           && GET_CODE (XEXP (and, 1)) == CONST_INT
57           && GET_CODE (XEXP (cond, 1)) == CONST_INT
58           && INTVAL (XEXP (and, 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       && GET_CODE (op) == CONST_INT
74       && CONST_OK_FOR_J16 (INTVAL (op)))
75     return 1;
76
77   return 0;
78 })
79
80 ;; Like arith_reg_dest, but this predicate is defined with
81 ;; define_special_predicate, not define_predicate.
82
83 (define_special_predicate "any_arith_reg_dest"
84   (match_code "subreg,reg")
85 {
86   return arith_reg_dest (op, mode);
87 })
88
89 ;; Like register_operand, but this predicate is defined with
90 ;; define_special_predicate, not define_predicate.
91
92 (define_special_predicate "any_register_operand"
93   (match_code "subreg,reg")
94 {
95   return register_operand (op, mode);
96 })
97
98 ;; Returns 1 if OP is a valid source operand for an arithmetic insn.
99
100 (define_predicate "arith_operand"
101   (match_code "subreg,reg,const_int,truncate")
102 {
103   if (arith_reg_operand (op, mode))
104     return 1;
105
106   if (TARGET_SHMEDIA)
107     {
108       /* FIXME: We should be checking whether the CONST_INT fits in a
109          CONST_OK_FOR_I16 here, but this causes reload_cse to crash when
110          attempting to transform a sequence of two 64-bit sets of the
111          same register from literal constants into a set and an add,
112          when the difference is too wide for an add.  */
113       if (GET_CODE (op) == CONST_INT
114           || EXTRA_CONSTRAINT_Css (op))
115         return 1;
116       else if (GET_CODE (op) == TRUNCATE
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 (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (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 (GET_CODE (op) == REG)
157         regno = REGNO (op);
158       else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
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       && GET_CODE (XEXP (op, 0)) == REG
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 (EXTRA_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 ;; TODO: Add a comment here.
220
221 (define_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 (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (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 ((mode == QImode || mode == HImode)
397       && (GET_CODE (op) == SUBREG
398           && GET_CODE (XEXP (op, 0)) == REG
399           && system_reg_operand (XEXP (op, 0), mode)))
400     return 0;
401
402   if (TARGET_SHMEDIA
403       && (GET_CODE (op) == PARALLEL || GET_CODE (op) == CONST_VECTOR)
404       && sh_rep_vec (op, mode))
405     return 1;
406   if (TARGET_SHMEDIA && 1
407       && GET_CODE (op) == SUBREG && GET_MODE (op) == mode
408       && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op))
409     /* FIXME */ abort (); /* return 1; */
410   return general_operand (op, mode);
411 })
412
413 ;; Returns 1 if OP can be a destination of a move. Same as
414 ;; general_operand, but no preinc allowed.
415
416 (define_predicate "general_movdst_operand"
417   (match_code "subreg,reg,mem")
418 {
419   /* Only pre dec allowed.  */
420   if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
421     return 0;
422   if (mode == DImode && TARGET_SHMEDIA && GET_CODE (op) == SUBREG
423       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8
424       && ! (high_life_started || reload_completed))
425     return 0;
426
427   return general_operand (op, mode);
428 })
429
430 ;; Returns 1 if OP is a MEM that can be source of a simple move operation.
431
432 (define_predicate "unaligned_load_operand"
433   (match_code "mem")
434 {
435   rtx inside;
436
437   if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
438     return 0;
439
440   inside = XEXP (op, 0);
441
442   if (GET_CODE (inside) == POST_INC)
443     inside = XEXP (inside, 0);
444
445   if (GET_CODE (inside) == REG)
446     return 1;
447
448   return 0;
449 })
450
451 ;; TODO: Add a comment here.
452
453 (define_predicate "greater_comparison_operator"
454   (match_code "gt,ge,gtu,geu"))
455
456 ;; TODO: Add a comment here.
457
458 (define_predicate "inqhi_operand"
459   (match_code "truncate")
460 {
461   if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op))
462     return 0;
463   op = XEXP (op, 0);
464   /* Can't use true_regnum here because copy_cost wants to know about
465      SECONDARY_INPUT_RELOAD_CLASS.  */
466   return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op));
467 })
468
469 ;; TODO: Add a comment here.
470
471 (define_special_predicate "int_gpr_dest"
472   (match_code "subreg,reg")
473 {
474   enum machine_mode op_mode = GET_MODE (op);
475
476   if (GET_MODE_CLASS (op_mode) != MODE_INT
477       || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD)
478     return 0;
479   if (! reload_completed)
480     return 0;
481   return true_regnum (op) <= LAST_GENERAL_REG;
482 })
483
484 ;; TODO: Add a comment here.
485
486 (define_predicate "less_comparison_operator"
487   (match_code "lt,le,ltu,leu"))
488
489 ;; Returns 1 if OP is a valid source operand for a logical operation.
490
491 (define_predicate "logical_operand"
492   (match_code "subreg,reg,const_int")
493 {
494   if (TARGET_SHMEDIA
495       && mode != DImode && GET_CODE (op) == SUBREG
496       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4)
497     return 0;
498
499   if (arith_reg_operand (op, mode))
500     return 1;
501
502   if (TARGET_SHMEDIA)
503     {
504       if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I10 (INTVAL (op)))
505         return 1;
506       else
507         return 0;
508     }
509   else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K08 (INTVAL (op)))
510     return 1;
511
512   return 0;
513 })
514
515 ;; TODO: Add a comment here.
516
517 (define_predicate "logical_operator"
518   (match_code "and,ior,xor"))
519
520 ;; Like arith_reg_operand, but for register source operands of narrow
521 ;; logical SHMEDIA operations: forbid subregs of DImode / TImode regs.
522
523 (define_predicate "logical_reg_operand"
524   (match_code "subreg,reg")
525 {
526   if (TARGET_SHMEDIA
527       && GET_CODE (op) == SUBREG
528       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4
529       && mode != DImode)
530     return 0;
531   return arith_reg_operand (op, mode);
532 })
533
534 ;; TODO: Add a comment here.
535
536 (define_predicate "mextr_bit_offset"
537   (match_code "const_int")
538 {
539   HOST_WIDE_INT i;
540
541   if (GET_CODE (op) != CONST_INT)
542     return 0;
543   i = INTVAL (op);
544   return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0;
545 })
546
547 ;; TODO: Add a comment here.
548
549 (define_predicate "minuend_operand"
550   (match_code "subreg,reg,truncate,const_int")
551 {
552   return op == constm1_rtx || extend_reg_or_0_operand (op, mode);
553 })
554
555 ;; TODO: Add a comment here.
556
557 (define_predicate "noncommutative_float_operator"
558   (and (match_code "minus,div")
559        (match_test "GET_MODE (op) == mode")))
560
561 ;; TODO: Add a comment here.
562
563 (define_predicate "sh_const_vec"
564   (match_code "const_vector")
565 {
566   int i;
567
568   if (GET_CODE (op) != CONST_VECTOR
569       || (GET_MODE (op) != mode && mode != VOIDmode))
570     return 0;
571   i = XVECLEN (op, 0) - 1;
572   for (; i >= 0; i--)
573     if (GET_CODE (XVECEXP (op, 0, i)) != CONST_INT)
574       return 0;
575   return 1;
576 })
577
578 ;; Determine if OP is a constant vector matching MODE with only one
579 ;; element that is not a sign extension.  Two byte-sized elements
580 ;; count as one.
581
582 (define_predicate "sh_1el_vec"
583   (match_code "const_vector")
584 {
585   int unit_size;
586   int i, last, least, sign_ix;
587   rtx sign;
588
589   if (GET_CODE (op) != CONST_VECTOR
590       || (GET_MODE (op) != mode && mode != VOIDmode))
591     return 0;
592   /* Determine numbers of last and of least significant elements.  */
593   last = XVECLEN (op, 0) - 1;
594   least = TARGET_LITTLE_ENDIAN ? 0 : last;
595   if (GET_CODE (XVECEXP (op, 0, least)) != CONST_INT)
596     return 0;
597   sign_ix = least;
598   if (GET_MODE_UNIT_SIZE (mode) == 1)
599     sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1;
600   if (GET_CODE (XVECEXP (op, 0, sign_ix)) != CONST_INT)
601     return 0;
602   unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op));
603   sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1)
604           ? constm1_rtx : const0_rtx);
605   i = XVECLEN (op, 0) - 1;
606   do
607     if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign)
608       return 0;
609   while (--i);
610   return 1;
611 })
612
613 ;; Like register_operand, but take into account that SHMEDIA can use
614 ;; the constant zero like a general register.
615
616 (define_predicate "sh_register_operand"
617   (match_code "reg,subreg,const_int")
618 {
619   if (op == CONST0_RTX (mode) && TARGET_SHMEDIA)
620     return 1;
621   return register_operand (op, mode);
622 })
623
624 ;; TODO: Add a comment here.
625
626 (define_predicate "sh_rep_vec"
627   (match_code "const_vector,parallel")
628 {
629   int i;
630   rtx x, y;
631
632   if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL)
633       || (GET_MODE (op) != mode && mode != VOIDmode))
634     return 0;
635   i = XVECLEN (op, 0) - 2;
636   x = XVECEXP (op, 0, i + 1);
637   if (GET_MODE_UNIT_SIZE (mode) == 1)
638     {
639       y = XVECEXP (op, 0, i);
640       for (i -= 2; i >= 0; i -= 2)
641         if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x)
642             || ! rtx_equal_p (XVECEXP (op, 0, i), y))
643           return 0;
644     }
645   else
646     for (; i >= 0; i--)
647       if (XVECEXP (op, 0, i) != x)
648         return 0;
649   return 1;
650 })
651
652 ;; TODO: Add a comment here.
653
654 (define_predicate "shift_count_operand"
655   (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend")
656 {
657   return (CONSTANT_P (op)
658           ? (GET_CODE (op) == CONST_INT
659              ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode)
660              : nonmemory_operand (op, mode))
661           : shift_count_reg_operand (op, mode));
662 })
663
664 ;; TODO: Add a comment here.
665
666 (define_predicate "shift_count_reg_operand"
667   (match_code "subreg,reg,zero_extend,sign_extend")
668 {
669   if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND
670        || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0))
671       && (mode == VOIDmode || mode == GET_MODE (op))
672       && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6
673       && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT)
674     {
675       mode = VOIDmode;
676       do
677         op = XEXP (op, 0);
678       while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND
679               || GET_CODE (op) == TRUNCATE)
680              && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6
681              && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT);
682
683     }
684   return arith_reg_operand (op, mode);
685 })
686
687 ;; TODO: Add a comment here.
688
689 (define_predicate "shift_operator"
690   (match_code "ashift,ashiftrt,lshiftrt"))
691
692 ;; TODO: Add a comment here.
693
694 (define_predicate "symbol_ref_operand"
695   (match_code "symbol_ref"))
696
697 ;; Same as target_reg_operand, except that label_refs and symbol_refs
698 ;; are accepted before reload.
699
700 (define_special_predicate "target_operand"
701   (match_code "subreg,reg,label_ref,symbol_ref,const,unspec")
702 {
703   if (mode != VOIDmode && mode != Pmode)
704     return 0;
705
706   if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode)
707       && EXTRA_CONSTRAINT_Csy (op))
708     return ! reload_completed;
709
710   return target_reg_operand (op, mode);
711 })
712
713 ;; Accept pseudos and branch target registers.
714
715 (define_special_predicate "target_reg_operand"
716   (match_code "subreg,reg")
717 {
718   if (mode == VOIDmode
719      ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode
720      : mode != GET_MODE (op))
721     return 0;
722
723   if (GET_CODE (op) == SUBREG)
724     op = XEXP (op, 0);
725
726   if (GET_CODE (op) != REG)
727     return 0;
728
729   /* We must protect ourselves from matching pseudos that are virtual
730      register, because they will eventually be replaced with hardware
731      registers that aren't branch-target registers.  */
732   if (REGNO (op) > LAST_VIRTUAL_REGISTER
733       || TARGET_REGISTER_P (REGNO (op)))
734     return 1;
735
736   return 0;
737 })
738
739 ;; TODO: Add a comment here.
740
741 (define_special_predicate "trunc_hi_operand"
742   (match_code "subreg,reg,truncate")
743 {
744   enum machine_mode op_mode = GET_MODE (op);
745
746   if (op_mode != SImode && op_mode != DImode
747       && op_mode != V4HImode && op_mode != V2SImode)
748     return 0;
749   return extend_reg_operand (op, mode);
750 })
751
752 ;; TODO: Add a comment here.
753
754 (define_predicate "ua_address_operand"
755   (match_code "subreg,reg,plus")
756 {
757   if (GET_CODE (op) == PLUS
758       && (GET_CODE (XEXP (op, 1)) != CONST_INT
759           || ! CONST_OK_FOR_I06 (INTVAL (XEXP (op, 1)))))
760     return 0;
761   return address_operand (op, QImode);
762 })
763
764 ;; TODO: Add a comment here.
765
766 (define_predicate "ua_offset"
767   (match_code "const_int")
768 {
769   return GET_CODE (op) == CONST_INT && CONST_OK_FOR_I06 (INTVAL (op));
770 })
771
772 ;; TODO: Add a comment here.
773
774 (define_predicate "unary_float_operator"
775   (and (match_code "abs,neg,sqrt")
776        (match_test "GET_MODE (op) == mode")))
777
778 ;; Return 1 if OP is a valid source operand for xor.
779
780 (define_predicate "xor_operand"
781   (match_code "subreg,reg,const_int")
782 {
783   if (GET_CODE (op) == CONST_INT)
784     return (TARGET_SHMEDIA
785             ? (CONST_OK_FOR_I06 (INTVAL (op))
786                || (no_new_pseudos && INTVAL (op) == 0xff))
787             : CONST_OK_FOR_K08 (INTVAL (op)));
788   if (TARGET_SHMEDIA
789       && mode != DImode && GET_CODE (op) == SUBREG
790       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4)
791     return 0;
792   return arith_reg_operand (op, mode);
793 })