File s390-address-constraints of Package gcc43

Index: gcc/config/s390/constraints.md
===================================================================
--- gcc/config/s390/constraints.md.orig	2009-11-20 13:52:23.000000000 +0100
+++ gcc/config/s390/constraints.md	2009-11-20 13:52:33.000000000 +0100
@@ -66,9 +66,14 @@
 ;;    B -- Multiple letter constraint followed by Q, R, S, or T:
 ;;         Memory reference of the type specified by second letter that
 ;;         does *not* refer to a literal pool entry.
-;;    U -- Pointer with short displacement.
-;;    W -- Pointer with long displacement.
+;;    U -- Pointer with short displacement. (deprecated - use ZQZR)
+;;    W -- Pointer with long displacement. (deprecated - use ZSZT)
 ;;    Y -- Shift count operand.
+;;    ZQ -- Pointer without index register and with short displacement.
+;;    ZR -- Pointer with index register and short displacement.
+;;    ZS -- Pointer without index register but with long displacement.
+;;    ZT -- Pointer with index register and long displacement.
+;;
 ;;
 
 
@@ -462,11 +467,26 @@ constraint."
 
 
 (define_address_constraint "U"
-  "Pointer with short displacement"
+  "Pointer with short displacement. (deprecated - use ZQZR)"
   (match_test "s390_mem_constraint (\"U\", op)"))
 
-
-
 (define_address_constraint "W"
-  "Pointer with long displacement"
+  "Pointer with long displacement. (deprecated - use ZSZT)"
   (match_test "s390_mem_constraint (\"W\", op)"))
+
+
+(define_address_constraint "ZQ"
+  "Pointer without index register and with short displacement."
+  (match_test "s390_mem_constraint (\"ZQ\", op)"))
+
+(define_address_constraint "ZR"
+  "Pointer with index register and short displacement."
+  (match_test "s390_mem_constraint (\"ZR\", op)"))
+
+(define_address_constraint "ZS"
+  "Pointer without index register but with long displacement."
+  (match_test "s390_mem_constraint (\"ZS\", op)"))
+
+(define_address_constraint "ZT"
+  "Pointer with index register and long displacement."
+  (match_test "s390_mem_constraint (\"ZT\", op)"))
Index: gcc/config/s390/s390.md
===================================================================
--- gcc/config/s390/s390.md.orig	2009-11-20 13:52:31.000000000 +0100
+++ gcc/config/s390/s390.md	2009-11-20 13:52:33.000000000 +0100
@@ -1468,7 +1468,7 @@
 
 (define_insn "*la_64"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (match_operand:QI 1 "address_operand" "U,W"))]
+        (match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))]
   "TARGET_64BIT"
   "@
    la\t%0,%a1
@@ -1651,7 +1651,7 @@
 
 (define_insn "*la_31"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (match_operand:QI 1 "address_operand" "U,W"))]
+        (match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))]
   "!TARGET_64BIT && legitimate_la_operand_p (operands[1])"
   "@
    la\t%0,%a1
@@ -1686,7 +1686,7 @@
 
 (define_insn "*la_31_and"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (and:SI (match_operand:QI 1 "address_operand" "U,W")
+        (and:SI (match_operand:QI 1 "address_operand" "ZQZR,ZSZT")
                 (const_int 2147483647)))]
   "!TARGET_64BIT"
   "@
@@ -1712,7 +1712,7 @@
 
 (define_insn "force_la_31"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
-        (match_operand:QI 1 "address_operand" "U,W"))
+        (match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))
    (use (const_int 0))]
   "!TARGET_64BIT"
   "@
@@ -7405,7 +7405,7 @@
   [(set (pc)
         (if_then_else
           (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
-          (match_operand 0 "address_operand" "U")
+          (match_operand 0 "address_operand" "ZQZR")
           (pc)))]
   ""
 {
@@ -7469,7 +7469,7 @@
         (if_then_else
           (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
           (pc)
-          (match_operand 0 "address_operand" "U")))]
+          (match_operand 0 "address_operand" "ZQZR")))]
   ""
 {
   if (get_attr_op_type (insn) == OP_TYPE_RR)
@@ -7658,7 +7658,7 @@
         (if_then_else
           (ne (match_operand:SI 1 "register_operand" "d")
               (const_int 1))
-          (match_operand 0 "address_operand" "U")
+          (match_operand 0 "address_operand" "ZQZR")
           (pc)))
    (set (match_operand:SI 2 "register_operand" "=1")
         (plus:SI (match_dup 1) (const_int -1)))
@@ -7769,7 +7769,7 @@
 ;
 
 (define_insn "indirect_jump"
- [(set (pc) (match_operand 0 "address_operand" "U"))]
+ [(set (pc) (match_operand 0 "address_operand" "ZQZR"))]
   ""
 {
   if (get_attr_op_type (insn) == OP_TYPE_RR)
@@ -7788,7 +7788,7 @@
 ;
 
 (define_insn "casesi_jump"
- [(set (pc) (match_operand 0 "address_operand" "U"))
+ [(set (pc) (match_operand 0 "address_operand" "ZQZR"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
 {
@@ -8010,7 +8010,7 @@
    (set_attr "type"    "jsr")])
 
 (define_insn "*basr"
-  [(call (mem:QI (match_operand 0 "address_operand" "U"))
+  [(call (mem:QI (match_operand 0 "address_operand" "ZQZR"))
          (match_operand 1 "const_int_operand" "n"))
    (clobber (match_operand 2 "register_operand" "=r"))]
   "!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode"
@@ -8068,7 +8068,7 @@
 
 (define_insn "*basr_r"
   [(set (match_operand 0 "" "")
-        (call (mem:QI (match_operand 1 "address_operand" "U"))
+        (call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
               (match_operand 2 "const_int_operand" "n")))
    (clobber (match_operand 3 "register_operand" "=r"))]
   "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
@@ -8168,7 +8168,7 @@
 
 (define_insn "*basr_tls"
   [(set (match_operand 0 "" "")
-        (call (mem:QI (match_operand 1 "address_operand" "U"))
+        (call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
               (match_operand 2 "const_int_operand" "n")))
    (clobber (match_operand 3 "register_operand" "=r"))
    (use (match_operand 4 "" ""))]
@@ -8717,24 +8717,29 @@
 ;
 
 (define_insn "prefetch"
-  [(prefetch (match_operand 0 "address_operand" "UW,X")
-	     (match_operand:SI 1 "const_int_operand" "n,n")
-	     (match_operand:SI 2 "const_int_operand" "n,n"))]
-  "TARGET_Z10"
+  [(prefetch (match_operand 0    "address_operand"   "ZQZS,ZRZT,X")
+	     (match_operand:SI 1 "const_int_operand" "   n,   n,n")
+	     (match_operand:SI 2 "const_int_operand" "   n,   n,n"))]
+  "TARGET_ZARCH && s390_tune == PROCESSOR_2097_Z10"
 {
-  if (larl_operand (operands[0], Pmode))
-    return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
+  switch (which_alternative)
+    {
+      case 0:
+        return INTVAL (operands[1]) == 1 ? "stcmh\t2,0,%a0" : "stcmh\t1,0,%a0";
+      case 1:
+        return INTVAL (operands[1]) == 1 ? "pfd\t2,%a0" : "pfd\t1,%a0";
+      case 2:
+        if (larl_operand (operands[0], Pmode))
+	  return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
+      default:
 
-  if (s390_mem_constraint ("W", operands[0])
-      || s390_mem_constraint ("U", operands[0]))
-    return INTVAL (operands[1]) == 1 ? "pfd\t2,%a0" : "pfd\t1,%a0";
-
-  /* This point might be reached if op0 is a larl operand with an
-     uneven addend.  In this case we simply omit issuing a prefetch
-     instruction.  */
+        /* This might be reached for symbolic operands with an odd
+          addend.  We simply omit the prefetch for such rare cases.  */
 
-  return "";
+        return "";
+     }
 }
-  [(set_attr "type" "load,larl")
-   (set_attr "op_type" "RXY,RIL")
-   (set_attr "z10prop" "z10_super")])
+  [(set_attr "type" "store,load,larl")
+   (set_attr "op_type" "RSY,RXY,RIL")
+   (set_attr "z10prop" "z10_super")
+   (set_attr "cpu_facility" "*,z10,z10")])
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c.orig	2009-11-20 13:52:31.000000000 +0100
+++ gcc/config/s390/s390.c	2009-11-20 13:52:33.000000000 +0100
@@ -1681,6 +1681,11 @@ s390_short_displacement (rtx disp)
   if (!disp)
     return true;
 
+  /* Without the long displacement facility we don't need to
+     distingiush between long and short displacement.  */
+  if (!TARGET_LONG_DISPLACEMENT)
+    return true;
+
   /* Integer displacement in range.  */
   if (GET_CODE (disp) == CONST_INT)
     return INTVAL (disp) >= 0 && INTVAL (disp) < 4096;
@@ -2054,79 +2059,93 @@ s390_legitimate_address_without_index_p
 }
 
 
-/* Evaluates constraint strings described by the regular expression
-   ([A|B](Q|R|S|T))|U|W and returns 1 if OP is a valid operand for the
-   constraint given in STR, or 0 else.  */
+/* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
+   and return these parts in SYMREF and ADDEND.  You can pass NULL in
+   SYMREF and/or ADDEND if you are not interested in these values.  */
 
-int
-s390_mem_constraint (const char *str, rtx op)
+static bool
+s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
 {
-  struct s390_address addr;
-  char c = str[0];
+  HOST_WIDE_INT tmpaddend = 0;
 
-  /* Check for offsettable variants of memory constraints.  */
-  if (c == 'A')
+  if (GET_CODE (addr) == CONST)
+    addr = XEXP (addr, 0);
+
+  if (GET_CODE (addr) == PLUS)
     {
-      /* Only accept non-volatile MEMs.  */
-      if (!MEM_P (op) || MEM_VOLATILE_P (op))
-	return 0;
+      if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
+	  && CONST_INT_P (XEXP (addr, 1)))
+	{
+	  tmpaddend = INTVAL (XEXP (addr, 1));
+	  addr = XEXP (addr, 0);
+	}
+      else
+	return false;
+    }
+  else
+    if (GET_CODE (addr) != SYMBOL_REF)
+	return false;
 
-      if ((reload_completed || reload_in_progress)
-	  ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
-	return 0;
+  if (symref)
+    *symref = addr;
+  if (addend)
+    *addend = tmpaddend;
 
-      c = str[1];
-    }
+  return true;
+}
+
+
+/* Return true if the address in OP is valid for constraint letter C
+   if wrapped in a MEM rtx.  Set LIT_POOL_OK to true if it literal
+   pool MEMs should be accepted.  Only the Q, R, S, T constraint
+   letters are allowed for C.  */
 
-  /* Check for non-literal-pool variants of memory constraints.  */
-  else if (c == 'B')
+static int
+s390_check_qrst_address (char c, rtx op, bool lit_pool_ok)
+{
+  struct s390_address addr;
+  bool decomposed = false;
+
+  /* This check makes sure that no symbolic address (except literal
+     pool references) are accepted by the R or T constraints.  */
+  if (s390_symref_operand_p (op, NULL, NULL))
     {
-      if (GET_CODE (op) != MEM)
+      if (!lit_pool_ok)
 	return 0;
-      if (!s390_decompose_address (XEXP (op, 0), &addr))
+      if (!s390_decompose_address (op, &addr))
 	return 0;
-      if (addr.literal_pool)
+      if (!addr.literal_pool)
 	return 0;
-
-      c = str[1];
+      decomposed = true;
     }
 
   switch (c)
     {
-    case 'Q':
-      if (GET_CODE (op) != MEM)
-	return 0;
-      if (!s390_decompose_address (XEXP (op, 0), &addr))
+    case 'Q': /* no index short displacement */
+      if (!decomposed && !s390_decompose_address (op, &addr))
 	return 0;
       if (addr.indx)
 	return 0;
-
-      if (TARGET_LONG_DISPLACEMENT)
-	{
-	  if (!s390_short_displacement (addr.disp))
-	    return 0;
-	}
-      break;
-
-    case 'R':
-      if (GET_CODE (op) != MEM)
+      if (!s390_short_displacement (addr.disp))
 	return 0;
+      break;
 
+    case 'R': /* with index short displacement */
       if (TARGET_LONG_DISPLACEMENT)
 	{
-	  if (!s390_decompose_address (XEXP (op, 0), &addr))
+	  if (!decomposed && !s390_decompose_address (op, &addr))
 	    return 0;
 	  if (!s390_short_displacement (addr.disp))
 	    return 0;
 	}
+      /* Any invalid address here will be fixed up by reload,
+	 so accept it for the most generic constraint.  */
       break;
 
-    case 'S':
+    case 'S': /* no index long displacement */
       if (!TARGET_LONG_DISPLACEMENT)
 	return 0;
-      if (GET_CODE (op) != MEM)
-	return 0;
-      if (!s390_decompose_address (XEXP (op, 0), &addr))
+      if (!decomposed && !s390_decompose_address (op, &addr))
 	return 0;
       if (addr.indx)
 	return 0;
@@ -2134,52 +2153,74 @@ s390_mem_constraint (const char *str, rt
 	return 0;
       break;
 
-    case 'T':
+    case 'T': /* with index long displacement */
       if (!TARGET_LONG_DISPLACEMENT)
 	return 0;
-      if (GET_CODE (op) != MEM)
-	return 0;
-      if (!s390_decompose_address (XEXP (op, 0), &addr))
-	return 0;
-      if (s390_short_displacement (addr.disp))
+      /* Any invalid address here will be fixed up by reload,
+	 so accept it for the most generic constraint.  */
+      if ((decomposed || s390_decompose_address (op, &addr))
+	  && s390_short_displacement (addr.disp))
 	return 0;
       break;
+    default:
+      return 0;
+    }
+  return 1;
+}
 
-    case 'U':
-      if (TARGET_LONG_DISPLACEMENT)
-	{
-	  if (!s390_decompose_address (op, &addr))
-	    return 0;
-	  if (!s390_short_displacement (addr.disp))
-	    return 0;
-	}
-      break;
 
-    case 'W':
-      if (!TARGET_LONG_DISPLACEMENT)
+/* Evaluates constraint strings described by the regular expression
+   ([A|B|Z](Q|R|S|T))|U|W|Y and returns 1 if OP is a valid operand for
+   the constraint given in STR, or 0 else.  */
+
+int
+s390_mem_constraint (const char *str, rtx op)
+{
+  char c = str[0];
+
+  switch (c)
+    {
+    case 'A':
+      /* Check for offsettable variants of memory constraints.  */
+      if (!MEM_P (op) || MEM_VOLATILE_P (op))
 	return 0;
-      if (!s390_decompose_address (op, &addr))
+      if ((reload_completed || reload_in_progress)
+	  ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
 	return 0;
-      if (s390_short_displacement (addr.disp))
+      return s390_check_qrst_address (str[1], XEXP (op, 0), true);
+    case 'B':
+      /* Check for non-literal-pool variants of memory constraints.  */
+      if (!MEM_P (op))
 	return 0;
-      break;
-
+      return s390_check_qrst_address (str[1], XEXP (op, 0), false);
+    case 'Q':
+    case 'R':
+    case 'S':
+    case 'T':
+      if (GET_CODE (op) != MEM)
+	return 0;
+      return s390_check_qrst_address (c, XEXP (op, 0), true);
+    case 'U':
+      return (s390_check_qrst_address ('Q', op, true)
+	      || s390_check_qrst_address ('R', op, true));
+    case 'W':
+      return (s390_check_qrst_address ('S', op, true)
+	      || s390_check_qrst_address ('T', op, true));
     case 'Y':
       /* Simply check for the basic form of a shift count.  Reload will
 	 take care of making sure we have a proper base register.  */
       if (!s390_decompose_shift_count (op, NULL, NULL))
 	return 0;
       break;
-
+    case 'Z':
+      return s390_check_qrst_address (str[1], op, true);
     default:
       return 0;
     }
-
   return 1;
 }
 
 
-
 /* Evaluates constraint strings starting with letter O.  Input
    parameter C is the second letter following the "O" in the constraint
    string. Returns 1 if VALUE meets the respective constraint and 0
@@ -2796,41 +2837,6 @@ s390_preferred_reload_class (rtx op, enu
   return class;
 }
 
-/* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
-   and return these parts in SYMREF and ADDEND.  You can pass NULL in
-   SYMREF and/or ADDEND if you are not interested in these values.  */
-
-static bool
-s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
-{
-  HOST_WIDE_INT tmpaddend = 0;
-
-  if (GET_CODE (addr) == CONST)
-    addr = XEXP (addr, 0);
-
-  if (GET_CODE (addr) == PLUS)
-    {
-      if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
-	  && CONST_INT_P (XEXP (addr, 1)))
-	{
-	  tmpaddend = INTVAL (XEXP (addr, 1));
-	  addr = XEXP (addr, 0);
-	}
-      else
-	return false;
-    }
-  else
-    if (GET_CODE (addr) != SYMBOL_REF)
-	return false;
-
-  if (symref)
-    *symref = addr;
-  if (addend)
-    *addend = tmpaddend;
-
-  return true;
-}
-
 /* Return true if ADDR is SYMBOL_REF + addend with addend being a
    multiple of ALIGNMENT and the SYMBOL_REF being naturally
    aligned.  */