OSDN Git Service

sparc: Use match_code in zero_or_v7_operand.
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / predicates.md
index 059ed47..308fbd6 100644 (file)
@@ -1,11 +1,11 @@
 ;; Predicate definitions for SPARC.
-;; Copyright (C) 2005 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007, 2008, 2010, 2012 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
 ;;
 ;; GCC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 ;;
 ;; GCC is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@
 ;; GNU General Public License for more details.
 ;;
 ;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
 
 ;; Predicates for numerical constants.
 
   (and (match_code "const_int,const_double,const_vector")
        (match_test "op == CONST0_RTX (mode)")))
 
-;; Return true if OP is the one constant for MODE.
-(define_predicate "const_one_operand"
-  (and (match_code "const_int,const_double,const_vector")
-       (match_test "op == CONST1_RTX (mode)")))
+;; Return true if the integer representation of OP is
+;; all-ones.
+(define_predicate "const_all_ones_operand"
+  (match_code "const_int,const_double,const_vector")
+{
+  if (GET_CODE (op) == CONST_INT && INTVAL (op) == -1)
+    return true;
+#if HOST_BITS_PER_WIDE_INT == 32
+  if (GET_CODE (op) == CONST_DOUBLE
+      && GET_MODE (op) == VOIDmode
+      && CONST_DOUBLE_HIGH (op) == ~(HOST_WIDE_INT)0
+      && CONST_DOUBLE_LOW (op) == ~(HOST_WIDE_INT)0)
+    return true;
+#endif
+  if (GET_CODE (op) == CONST_VECTOR)
+    {
+      int i, num_elem = CONST_VECTOR_NUNITS (op);
+
+      for (i = 0; i < num_elem; i++)
+        {
+          rtx n = CONST_VECTOR_ELT (op, i);
+          if (! const_all_ones_operand (n, mode))
+            return false;
+        }
+      return true;
+    }
+  return false;
+})
 
 ;; Return true if OP is the integer constant 4096.
 (define_predicate "const_4096_operand"
 ;; The first test avoids emitting sethi to load zero for example.
 (define_predicate "const_high_operand"
   (and (match_code "const_int")
-       (and (match_test "INTVAL (op) & ~(HOST_WIDE_INT)0x3ff")
+       (and (not (match_operand 0 "small_int_operand"))
             (match_test "SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))"))))
 
+;; Return true if OP is a constant whose 1's complement can be loaded by the
+;; sethi instruction.
+(define_predicate "const_compl_high_operand"
+  (and (match_code "const_int")
+       (and (not (match_operand 0 "small_int_operand"))
+            (match_test "SPARC_SETHI_P (~INTVAL (op) & GET_MODE_MASK (mode))"))))
+
+;; Return true if OP is a FP constant that needs to be loaded by the sethi/losum
+;; pair of instructions.
+(define_predicate "fp_const_high_losum_operand"
+  (match_operand 0 "const_double_operand")
+{
+  gcc_assert (mode == SFmode);
+  return fp_high_losum_p (op);
+})
+
+;; Return true if OP is a const_double or const_vector.
+(define_predicate "const_double_or_vector_operand"
+  (match_code "const_double,const_vector"))
+
+;; Return true if OP is Zero, or if the target is V7.
+(define_predicate "zero_or_v7_operand"
+  (and (match_code "const_int")
+       (ior (match_test "INTVAL (op) == 0")
+           (match_test "!TARGET_V8 && !TARGET_V9"))))
 
 ;; Predicates for symbolic constants.
 
 ;; Return true if OP is a symbolic operand for the TLS Global Dynamic model.
 (define_predicate "tgd_symbolic_operand"
   (and (match_code "symbol_ref")
-       (match_test "tls_symbolic_operand (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
+       (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
 
 ;; Return true if OP is a symbolic operand for the TLS Local Dynamic model.
 (define_predicate "tld_symbolic_operand"
   (and (match_code "symbol_ref")
-       (match_test "tls_symbolic_operand (op) == TLS_MODEL_LOCAL_DYNAMIC")))
+       (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
 
 ;; Return true if OP is a symbolic operand for the TLS Initial Exec model.
 (define_predicate "tie_symbolic_operand"
   (and (match_code "symbol_ref")
-       (match_test "tls_symbolic_operand (op) == TLS_MODEL_INITIAL_EXEC")))
+       (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC")))
 
 ;; Return true if OP is a symbolic operand for the TLS Local Exec model.
 (define_predicate "tle_symbolic_operand"
   (and (match_code "symbol_ref")
-       (match_test "tls_symbolic_operand (op) == TLS_MODEL_LOCAL_EXEC")))
+       (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC")))
 
 ;; Return true if the operand is an argument used in generating PIC references
 ;; in either the medium/low or embedded medium/anywhere code models on V9.
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "const_zero_operand")))
 
+(define_predicate "register_or_v9_zero_operand"
+  (ior (match_operand 0 "register_operand")
+       (and (match_test "TARGET_V9")
+           (match_operand 0 "const_zero_operand"))))
+
+;; Return true if OP is either the zero constant, the all-ones
+;; constant, or a register.
+(define_predicate "register_or_zero_or_all_ones_operand"
+  (ior (match_operand 0 "register_or_zero_operand")
+       (match_operand 0 "const_all_ones_operand")))
+
 ;; Return true if OP is a register operand in a floating point register.
 (define_predicate "fp_register_operand"
   (match_operand 0 "register_operand")
 #else
   if (GET_CODE (op) != CONST_INT)
     return false;
-  m1 = INTVAL (op) & 0xffffffff;
-  m2 = INTVAL (op) >> 32;
+  m1 = trunc_int_for_mode (INTVAL (op), SImode);
+  m2 = trunc_int_for_mode (INTVAL (op) >> 32, SImode);
 #endif
 
   return SPARC_SIMM13_P (m1) && SPARC_SIMM13_P (m2);
        (match_operand 0 "uns_small_int_operand")))
 
 
-;; Predicates for miscellanous instructions.
+;; Predicates for miscellaneous instructions.
 
 ;; Return true if OP is valid for the lhs of a comparison insn.
 (define_predicate "compare_operand"
-  (match_code "reg, subreg, zero_extract")
+  (match_code "reg,subreg,zero_extract")
 {
   if (GET_CODE (op) == ZERO_EXTRACT)
     return (register_operand (XEXP (op, 0), mode)
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return false;
 
+  mclass = GET_MODE_CLASS (mode);
+
   /* Allow any 1-instruction integer constant.  */
-  if (GET_MODE_CLASS (mode) == MODE_INT
+  if (mclass == MODE_INT
       && (small_int_operand (op, mode) || const_high_operand (op, mode)))
     return true;
 
       && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
     return true;
 
-  if (register_operand (op, mode))
+  if (mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)
     return true;
 
-  mclass = GET_MODE_CLASS (mode);
-  if ((mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)
-      || (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR))
+  if (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR
+      && (const_zero_operand (op, mode)
+          || const_all_ones_operand (op, mode)))
     return true;
 
-  /* If this is a SUBREG, look inside so that we handle
-     paradoxical ones.  */
+  if (register_operand (op, mode))
+    return true;
+
+  /* If this is a SUBREG, look inside so that we handle paradoxical ones.  */
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
 
        (match_test "call_address_operand (XEXP (op, 0), mode)")))
 
 
+(define_predicate "mem_noofs_operand"
+  (and (match_code "mem")
+       (match_code "reg" "0")))
+
 ;; Predicates for operators.
 
 ;; Return true if OP is a comparison operator.  This allows the use of