xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/sh/predicates.md (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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_expr;
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 (!MEM_P (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_expr = XEXP (cond, 0);
53  return (GET_CODE (and_expr) == AND
54	  && rtx_equal_p (XEXP (and_expr, 0), tar)
55	  && CONST_INT_P (XEXP (and_expr, 1))
56	  && CONST_INT_P (XEXP (cond, 1))
57	  && INTVAL (XEXP (and_expr, 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 (CONST_INT_P (op)
112	  || satisfies_constraint_Css (op))
113	return 1;
114      else if (GET_CODE (op) == TRUNCATE
115	       && REG_P (XEXP (op, 0))
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 (REG_P (op))
156	regno = REGNO (op);
157      else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
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      && REG_P (XEXP (op, 0))
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 (!REG_P (XEXP (op, 0)))
227	return 0;
228      if (!CONST_INT_P (XEXP (op, 1))
229	  || (INTVAL (XEXP (op, 1)) & 31))
230	return 0;
231    }
232  else if (!REG_P (op))
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 (REG_P (op) && 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 (REG_P (op))
323	regno = REGNO (op);
324      else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
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 (REG_P (op)
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 (REG_P (op)
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 (MEM_P (op))
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	  && CONST_INT_P (XEXP (inside, 1)))
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 (MEM_P (op) && 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 (!MEM_P (op) || 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 (REG_P (inside))
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 REG_P (op) && 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 (!CONST_INT_P (op))
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;; UNORDERED is only supported on SHMEDIA.
556
557(define_predicate "sh_float_comparison_operator"
558  (ior (match_operand 0 "ordered_comparison_operator")
559       (and (match_test "TARGET_SHMEDIA")
560	    (match_code "unordered"))))
561
562(define_predicate "shmedia_cbranch_comparison_operator"
563  (ior (match_operand 0 "equality_comparison_operator")
564       (match_operand 0 "greater_comparison_operator")))
565
566;; TODO: Add a comment here.
567
568(define_predicate "sh_const_vec"
569  (match_code "const_vector")
570{
571  int i;
572
573  if (GET_CODE (op) != CONST_VECTOR
574      || (GET_MODE (op) != mode && mode != VOIDmode))
575    return 0;
576  i = XVECLEN (op, 0) - 1;
577  for (; i >= 0; i--)
578    if (!CONST_INT_P (XVECEXP (op, 0, i)))
579      return 0;
580  return 1;
581})
582
583;; Determine if OP is a constant vector matching MODE with only one
584;; element that is not a sign extension.  Two byte-sized elements
585;; count as one.
586
587(define_predicate "sh_1el_vec"
588  (match_code "const_vector")
589{
590  int unit_size;
591  int i, last, least, sign_ix;
592  rtx sign;
593
594  if (GET_CODE (op) != CONST_VECTOR
595      || (GET_MODE (op) != mode && mode != VOIDmode))
596    return 0;
597  /* Determine numbers of last and of least significant elements.  */
598  last = XVECLEN (op, 0) - 1;
599  least = TARGET_LITTLE_ENDIAN ? 0 : last;
600  if (!CONST_INT_P (XVECEXP (op, 0, least)))
601    return 0;
602  sign_ix = least;
603  if (GET_MODE_UNIT_SIZE (mode) == 1)
604    sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1;
605  if (!CONST_INT_P (XVECEXP (op, 0, sign_ix)))
606    return 0;
607  unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op));
608  sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1)
609	  ? constm1_rtx : const0_rtx);
610  i = XVECLEN (op, 0) - 1;
611  do
612    if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign)
613      return 0;
614  while (--i);
615  return 1;
616})
617
618;; Like register_operand, but take into account that SHMEDIA can use
619;; the constant zero like a general register.
620
621(define_predicate "sh_register_operand"
622  (match_code "reg,subreg,const_int,const_double")
623{
624  if (op == CONST0_RTX (mode) && TARGET_SHMEDIA)
625    return 1;
626  return register_operand (op, mode);
627})
628
629;; TODO: Add a comment here.
630
631(define_predicate "sh_rep_vec"
632  (match_code "const_vector,parallel")
633{
634  int i;
635  rtx x, y;
636
637  if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL)
638      || (GET_MODE (op) != mode && mode != VOIDmode))
639    return 0;
640  i = XVECLEN (op, 0) - 2;
641  x = XVECEXP (op, 0, i + 1);
642  if (GET_MODE_UNIT_SIZE (mode) == 1)
643    {
644      y = XVECEXP (op, 0, i);
645      for (i -= 2; i >= 0; i -= 2)
646	if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x)
647	    || ! rtx_equal_p (XVECEXP (op, 0, i), y))
648	  return 0;
649    }
650  else
651    for (; i >= 0; i--)
652      if (XVECEXP (op, 0, i) != x)
653	return 0;
654  return 1;
655})
656
657;; TODO: Add a comment here.
658
659(define_predicate "shift_count_operand"
660  (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,zero_extend,sign_extend")
661{
662  return (CONSTANT_P (op)
663	  ? (CONST_INT_P (op)
664	     ? (unsigned) INTVAL (op) < GET_MODE_BITSIZE (mode)
665	     : nonmemory_operand (op, mode))
666	  : shift_count_reg_operand (op, mode));
667})
668
669;; TODO: Add a comment here.
670
671(define_predicate "shift_count_reg_operand"
672  (match_code "subreg,reg,zero_extend,sign_extend")
673{
674  if ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND
675       || (GET_CODE (op) == SUBREG && SUBREG_BYTE (op) == 0))
676      && (mode == VOIDmode || mode == GET_MODE (op))
677      && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6
678      && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT)
679    {
680      mode = VOIDmode;
681      do
682	op = XEXP (op, 0);
683      while ((GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND
684	      || GET_CODE (op) == TRUNCATE)
685	     && GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))) >= 6
686	     && GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_INT);
687
688    }
689  return arith_reg_operand (op, mode);
690})
691
692;; TODO: Add a comment here.
693
694(define_predicate "shift_operator"
695  (match_code "ashift,ashiftrt,lshiftrt"))
696
697;; TODO: Add a comment here.
698
699(define_predicate "symbol_ref_operand"
700  (match_code "symbol_ref"))
701
702;; Same as target_reg_operand, except that label_refs and symbol_refs
703;; are accepted before reload.
704
705(define_special_predicate "target_operand"
706  (match_code "subreg,reg,label_ref,symbol_ref,const,unspec")
707{
708  if (mode != VOIDmode && mode != Pmode)
709    return 0;
710
711  if ((GET_MODE (op) == Pmode || GET_MODE (op) == VOIDmode)
712      && satisfies_constraint_Csy (op))
713    return ! reload_completed;
714
715  return target_reg_operand (op, mode);
716})
717
718;; Accept pseudos and branch target registers.
719
720(define_special_predicate "target_reg_operand"
721  (match_code "subreg,reg")
722{
723  if (mode == VOIDmode
724     ? GET_MODE (op) != Pmode && GET_MODE (op) != PDImode
725     : mode != GET_MODE (op))
726    return 0;
727
728  if (GET_CODE (op) == SUBREG)
729    op = XEXP (op, 0);
730
731  if (!REG_P (op))
732    return 0;
733
734  /* We must protect ourselves from matching pseudos that are virtual
735     register, because they will eventually be replaced with hardware
736     registers that aren't branch-target registers.  */
737  if (REGNO (op) > LAST_VIRTUAL_REGISTER
738      || TARGET_REGISTER_P (REGNO (op)))
739    return 1;
740
741  return 0;
742})
743
744;; TODO: Add a comment here.
745
746(define_special_predicate "trunc_hi_operand"
747  (match_code "subreg,reg,truncate")
748{
749  enum machine_mode op_mode = GET_MODE (op);
750
751  if (op_mode != SImode && op_mode != DImode
752      && op_mode != V4HImode && op_mode != V2SImode)
753    return 0;
754  return extend_reg_operand (op, mode);
755})
756
757;; Return 1 of OP is an address suitable for an unaligned access instruction.
758
759(define_special_predicate "ua_address_operand"
760  (match_code "subreg,reg,plus")
761{
762  if (GET_CODE (op) == PLUS
763      && (! satisfies_constraint_I06 (XEXP (op, 1))))
764    return 0;
765  return address_operand (op, QImode);
766})
767
768;; TODO: Add a comment here.
769
770(define_predicate "ua_offset"
771  (match_code "const_int")
772{
773  return satisfies_constraint_I06 (op);
774})
775
776;; TODO: Add a comment here.
777
778(define_predicate "unary_float_operator"
779  (and (match_code "abs,neg,sqrt")
780       (match_test "GET_MODE (op) == mode")))
781
782;; Return 1 if OP is a valid source operand for xor.
783
784(define_predicate "xor_operand"
785  (match_code "subreg,reg,const_int")
786{
787  if (CONST_INT_P (op))
788    return (TARGET_SHMEDIA
789	    ? (satisfies_constraint_I06 (op)
790	       || (!can_create_pseudo_p () && INTVAL (op) == 0xff))
791	    : satisfies_constraint_K08 (op));
792  if (TARGET_SHMEDIA
793      && mode != DImode && GET_CODE (op) == SUBREG
794      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) > 4)
795    return 0;
796  return arith_reg_operand (op, mode);
797})
798
799(define_predicate "bitwise_memory_operand"
800  (match_code "mem")
801{
802  if (MEM_P (op))
803    {
804      if (REG_P (XEXP (op, 0)))
805	return 1;
806
807      if (GET_CODE (XEXP (op, 0)) == PLUS
808	  && REG_P (XEXP (XEXP (op, 0), 0))
809	  && satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1)))
810        return 1;
811    }
812  return 0;
813})
814