constraints.md ('b', [...]): New constraint letters defined.
authorAndreas Krebbel <krebbel1@de.ibm.com>
Wed, 28 May 2008 14:11:19 +0000 (14:11 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 28 May 2008 14:11:19 +0000 (14:11 +0000)
2008-05-28  Andreas Krebbel  <krebbel1@de.ibm.com>

* config/s390/constraints.md ('b', 'C', 'D', 'e'): New constraint
letters defined.

* config/s390/s390.c (s390_compare_and_branch_condition_mask,
s390_contiguous_bitmask_p, s390_symref_operand_p,
s390_check_symref_alignment, s390_reload_larl_operand,
s390_reload_symref_address): New functions.
(s390_branch_condition_mnemonic): Support compare and branch
instructions.
(s390_mem_constraint): Avoid symrefs to accepted by the 'T'
and 'W' constraints.
(s390_secondary_reload): Add secondary reloads for unaligned
symbol refs or symbol refs to floating point or QI/TI mode
integer values.
(legitimate_address_p): Accept symbol references as addresses.
(s390_expand_insv): Use rotate and insert selected bits
instruction for insv when building for z10.
(print_operand_address): Handle symbol ref addresses.
(print_operand): Output modifier 'c' added for signed byte
values.
(s390_encode_section_info): Mark symbol refs with
SYMBOL_FLAG_NOT_NATURALLY_ALIGNED if appropriate.

* config/s390/s390.md (SIL,RRS,RIS): New instruction formats added.
(length attribute): RRF, RRR have 4 byte length.
(FPALL, INTALL): New mode iterators added.
(*tstdi_sign, *cmpdi_ccs_sign, *cmpsi_ccs_sign,
*cmp<mode>_ccs, *cmpdi_ccu_zero, *cmpdi_ccu, *cmpsi_ccu, *cmphi_ccu,
*movdi_64, *movsi_zarch, *movhi, movmem<mode>, *movmem_short,
*extendsidi2, *extendhidi2_extimm, *extendhisi2_extimm,
*zero_extendsidi2, adddi3, *adddi3_31z, *adddi3_31, addsi3,
*add<mode>3, *add<mode>3_carry1_cc, *add<mode>3_carry2_cc,
*add<mode>3_cc, *add<mode>3_imm_cc, *muldi3_sign, muldi3,
*mulsi3_sign, mulsi3, mulsidi3): Patterns enhanced with z10
instructions.
(*cmphi_ccs_z10, *cmpdi_ccs_signhi_rl, *cmpsi_ccu_zerohi_rlsi,
*cmp<GPR:mode>_ccu_zerohi_rldi, *cmp_and_br_signed_<mode>,
*cmp_and_br_unsigned_<mode>, reload<INTALL:mode><P:mode>_tomem_z10,
reload<INTALL:mode><P:mode>_toreg_z10,
reload<FPALL:mode><P:mode>_tomem_z10,
reload<FPALL:mode><P:mode>_toreg_z10,
reload<P:mode>_larl_odd_addend_z10, *execute_rl, *insv<mode>_z10,
*insv<mode>_z10_noshift, *insv<mode>_or_z10_noshift,
*zero_extendhi<mode>2_z10, *cmp_and_trap_signed_int<mode>,
*cmp_and_trap_unsigned_int<mode>, prefetch): New pattern or expander
definition.
(movmem, clrmem, cmpmem): New splitters added.

* config/s390/predicates.md (larl_operand): Use
SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1 replaced with
SYMBOL_REF_ALIGN1_P.
(s390_signed_integer_comparison,
s390_unsigned_integer_comparison): New predicates.

* config/s390/s390-protos.h (s390_check_symref_alignment,
s390_contiguous_bitmask_p, s390_reload_larl_operand,
s390_reload_symref_address,
s390_compare_and_branch_condition_mask): Prototypes added.

* config/s390/s390.h (TARGET_MEM_CONSTRAINT,
SYMBOL_REF_ALIGN1_P, SYMBOL_FLAG_NOT_NATURALLY_ALIGNED,
SYMBOL_REF_NOT_NATURALLY_ALIGNED_P): Macro definition added.

From-SVN: r136098

gcc/ChangeLog
gcc/config/s390/constraints.md
gcc/config/s390/predicates.md
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md

index a538ccde6688e865fc401b3c0900f76ee324c97b..a64b0b01185418faea66adc3869fd649010703a7 100644 (file)
@@ -1,3 +1,68 @@
+2008-05-28  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * config/s390/constraints.md ('b', 'C', 'D', 'e'): New constraint
+       letters defined.
+
+       * config/s390/s390.c (s390_compare_and_branch_condition_mask,
+       s390_contiguous_bitmask_p, s390_symref_operand_p,
+       s390_check_symref_alignment, s390_reload_larl_operand,
+       s390_reload_symref_address): New functions.
+       (s390_branch_condition_mnemonic): Support compare and branch
+       instructions.
+       (s390_mem_constraint): Avoid symrefs to accepted by the 'T'
+       and 'W' constraints.
+       (s390_secondary_reload): Add secondary reloads for unaligned
+       symbol refs or symbol refs to floating point or QI/TI mode
+       integer values.
+       (legitimate_address_p): Accept symbol references as addresses.
+       (s390_expand_insv): Use rotate and insert selected bits
+       instruction for insv when building for z10.
+       (print_operand_address): Handle symbol ref addresses.
+       (print_operand): Output modifier 'c' added for signed byte
+       values.
+       (s390_encode_section_info): Mark symbol refs with
+       SYMBOL_FLAG_NOT_NATURALLY_ALIGNED if appropriate.
+
+       * config/s390/s390.md (SIL,RRS,RIS): New instruction formats added.
+       (length attribute): RRF, RRR have 4 byte length.
+       (FPALL, INTALL): New mode iterators added.
+       (*tstdi_sign, *cmpdi_ccs_sign, *cmpsi_ccs_sign,
+       *cmp<mode>_ccs, *cmpdi_ccu_zero, *cmpdi_ccu, *cmpsi_ccu, *cmphi_ccu,
+       *movdi_64, *movsi_zarch, *movhi, movmem<mode>, *movmem_short,
+       *extendsidi2, *extendhidi2_extimm, *extendhisi2_extimm,
+       *zero_extendsidi2, adddi3, *adddi3_31z, *adddi3_31, addsi3,
+       *add<mode>3, *add<mode>3_carry1_cc, *add<mode>3_carry2_cc,
+       *add<mode>3_cc, *add<mode>3_imm_cc, *muldi3_sign, muldi3,
+       *mulsi3_sign, mulsi3, mulsidi3): Patterns enhanced with z10
+       instructions.
+       (*cmphi_ccs_z10, *cmpdi_ccs_signhi_rl, *cmpsi_ccu_zerohi_rlsi,
+       *cmp<GPR:mode>_ccu_zerohi_rldi, *cmp_and_br_signed_<mode>,
+       *cmp_and_br_unsigned_<mode>, reload<INTALL:mode><P:mode>_tomem_z10,
+       reload<INTALL:mode><P:mode>_toreg_z10,
+       reload<FPALL:mode><P:mode>_tomem_z10,
+       reload<FPALL:mode><P:mode>_toreg_z10,
+       reload<P:mode>_larl_odd_addend_z10, *execute_rl, *insv<mode>_z10,
+       *insv<mode>_z10_noshift, *insv<mode>_or_z10_noshift,
+       *zero_extendhi<mode>2_z10, *cmp_and_trap_signed_int<mode>,
+       *cmp_and_trap_unsigned_int<mode>, prefetch): New pattern or expander
+       definition.
+       (movmem, clrmem, cmpmem): New splitters added.
+
+       * config/s390/predicates.md (larl_operand): Use
+       SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1 replaced with
+       SYMBOL_REF_ALIGN1_P.
+       (s390_signed_integer_comparison,
+       s390_unsigned_integer_comparison): New predicates.
+
+       * config/s390/s390-protos.h (s390_check_symref_alignment,
+       s390_contiguous_bitmask_p, s390_reload_larl_operand,
+       s390_reload_symref_address,
+       s390_compare_and_branch_condition_mask): Prototypes added.
+
+       * config/s390/s390.h (TARGET_MEM_CONSTRAINT,
+       SYMBOL_REF_ALIGN1_P, SYMBOL_FLAG_NOT_NATURALLY_ALIGNED,
+       SYMBOL_REF_NOT_NATURALLY_ALIGNED_P): Macro definition added.
+
 2008-05-28  Andreas Krebbel  <krebbel1@de.ibm.com>
 
        * config/s390/s390.c (z10_cost): New cost function for z10.
index 92fd3254ca5ab3d52c1f7dcf858b14d4f95951ce..ad953080ff138ea7628c91987955138b70217995 100644 (file)
@@ -1,5 +1,5 @@
 ;; Constraints definitions belonging to the gcc backend for IBM S/390.
-;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
 ;; Written by Wolfgang Gellerich, using code and information found in
 ;; files s390.md, s390.h, and s390.c.
 ;;
 ;; Special constraints for s/390 machine description:
 ;;
 ;;    a -- Any address register from 1 to 15.
+;;    b -- Memory operand whose address is a symbol reference or a symbol
+;;         reference + constant which can be proven to be naturally aligned.
 ;;    c -- Condition code register 33.
 ;;    d -- Any register from 0 to 15.
 ;;    f -- Floating point registers.
 ;;    t -- Access registers 36 and 37.
+;;    C -- A signed 8-bit constant (-128..127)
+;;    D -- An unsigned 16-bit constant (0..65535)
 ;;    G -- Const double zero operand
 ;;    I -- An 8-bit constant (0..255).
 ;;    J -- A 12-bit constant (0..4095).
 ;;  General constraints for constants.
 ;;
 
+(define_constraint "C"
+  "@internal
+   An 8-bit signed immediate constant (-128..127)"
+  (and (match_code "const_int")
+       (match_test "ival >= -128 && ival <= 127")))
+
+
+(define_constraint "D"
+  "An unsigned 16-bit constant (0..65535)"
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 65535")))
+
+
 (define_constraint "G"
   "@internal
    Const double zero operand"
        (match_test "ival >= -32768 && ival <= 32767")))
 
 
-
 (define_constraint "L"
   "Value appropriate as displacement.
       (0..4095) for short displacement
   (match_test "s390_mem_constraint (\"Q\", op)"))
 
 
-
 (define_memory_constraint "R"
   "Memory reference with index register and short displacement"
   (match_test "s390_mem_constraint (\"R\", op)"))
   (match_test "s390_mem_constraint (\"T\", op)"))
 
 
+(define_memory_constraint "b"
+  "Memory reference whose address is a naturally aligned symbol reference."
+  (match_test "MEM_P (op)
+               && s390_check_symref_alignment (XEXP (op, 0),
+                                               GET_MODE_SIZE (GET_MODE (op)))"))
+
+(define_memory_constraint "e"
+  "Matches all memory references available on the current architecture
+level.  This constraint will never be used and using it in an inline
+assembly is *always* a bug since there is no instruction accepting all
+those addresses.  It just serves as a placeholder for a generic memory
+constraint."
+  (match_test "legitimate_address_p (GET_MODE (op), op, 1)"))
+
+; This defines 'm' as normal memory constraint.  This is only possible
+; since the standard memory constraint is re-defined in s390.h using
+; the TARGET_MEM_CONSTRAINT macro.
+(define_memory_constraint "m"
+  "Matches the most general memory address for pre-z10 machines."
+  (match_test "s390_mem_constraint (\"R\", op)
+               || s390_mem_constraint (\"T\", op)"))
 
 (define_memory_constraint "AQ"
   "@internal 
   (match_test "s390_mem_constraint (\"BT\", op)"))
 
 
-
 (define_address_constraint "U"
   "Pointer with short displacement"
   (match_test "s390_mem_constraint (\"U\", op)"))
index 50bf0c1eda995d483b88cfd3b4e879c6ff04449f..ca5d17556a5f9cbee064a3c1a7a03a15e07336df 100644 (file)
@@ -1,5 +1,5 @@
 ;; Predicate definitions for S/390 and zSeries.
-;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
 ;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
 ;;                Ulrich Weigand (uweigand@de.ibm.com).
 ;;
   if (GET_CODE (op) == LABEL_REF)
     return true;
   if (GET_CODE (op) == SYMBOL_REF)
-    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+    return (!SYMBOL_REF_ALIGN1_P (op)
            && SYMBOL_REF_TLS_MODEL (op) == 0
            && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
 
   return (s390_branch_condition_mask (op) >= 0);
 })
 
+(define_predicate "s390_signed_integer_comparison"
+  (match_code "eq, ne, lt, gt, le, ge")
+{
+  return (s390_compare_and_branch_condition_mask (op) >= 0);
+})
+
+(define_predicate "s390_unsigned_integer_comparison"
+  (match_code "eq, ne, ltu, gtu, leu, geu")
+{
+  return (s390_compare_and_branch_condition_mask (op) >= 0);
+})
+
 ;; Return nonzero if OP is a valid comparison operator
 ;; for an ALC condition.
 
index 7e329f2a5656a31d965ced7daafb00e0bd3498b0..76f73f9dd2c0b18ae28f4ebda9ac050acaad07f4 100644 (file)
@@ -1,5 +1,7 @@
 /* Definitions of target machine for GNU compiler, for IBM S/390.
-   Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free
+   Software Foundation, Inc.
+
    Contributed by Hartmut Penner (hpenner@de.ibm.com)
 
 This file is part of GCC.
@@ -27,7 +29,7 @@ extern int s390_mem_constraint (const char *str, rtx op);
 extern int s390_O_constraint_str (const char c, HOST_WIDE_INT value);
 extern int s390_N_constraint_str (const char *str, HOST_WIDE_INT value);
 extern int s390_float_const_zero_p (rtx value);
-
+extern bool s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment);
 
 
 /* Declare functions in s390.c.  */
@@ -51,6 +53,7 @@ extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
 extern int s390_const_double_ok_for_constraint_p (rtx, int, const char *);
 extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
 extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
+extern bool s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT, int, int *, int *);
 extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
 extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT);
 extern bool s390_offset_p (rtx, rtx, rtx);
@@ -80,6 +83,8 @@ extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
 extern enum reg_class s390_secondary_output_reload_class (enum reg_class,
                                                          enum machine_mode,
                                                          rtx);
+extern void s390_reload_larl_operand (rtx , rtx , rtx);
+extern void s390_reload_symref_address (rtx , rtx , rtx , bool);
 extern void s390_expand_plus_operand (rtx, rtx, rtx);
 extern void emit_symbolic_move (rtx *);
 extern void s390_load_address (rtx, rtx);
@@ -113,6 +118,7 @@ extern void s390_emit_tpf_eh_return (rtx);
 extern bool s390_legitimate_address_without_index_p (rtx);
 extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
 extern int s390_branch_condition_mask (rtx);
+extern int s390_compare_and_branch_condition_mask (rtx);
 
 #endif /* RTX_CODE */
 
index 37660a258720a1e387efd2daa792e99096d22542..5ffbcaef338dacd558fc88c7804ffc5f5d9e6e54 100644 (file)
@@ -1,8 +1,9 @@
 /* Subroutines used for code generation on IBM S/390 and zSeries
    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2007 Free Software Foundation, Inc.
+   2007, 2008 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-                  Ulrich Weigand (uweigand@de.ibm.com).
+                  Ulrich Weigand (uweigand@de.ibm.com) and
+                  Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
 
 This file is part of GCC.
 
@@ -1061,6 +1062,41 @@ s390_branch_condition_mask (rtx code)
     }
 }
 
+
+/* Return branch condition mask to implement a compare and branch
+   specified by CODE.  Return -1 for invalid comparisons.  */
+
+int
+s390_compare_and_branch_condition_mask (rtx code)
+{
+  const int CC0 = 1 << 3;
+  const int CC1 = 1 << 2;
+  const int CC2 = 1 << 1;
+
+  switch (GET_CODE (code))
+    {
+    case EQ:
+      return CC0;
+    case NE:
+      return CC1 | CC2;
+    case LT:
+    case LTU:
+      return CC1;
+    case GT:
+    case GTU:
+      return CC2;
+    case LE:
+    case LEU:
+      return CC0 | CC1;
+    case GE:
+    case GEU:
+      return CC0 | CC2;
+    default:
+      gcc_unreachable ();
+    }
+  return -1;
+}
+
 /* If INV is false, return assembler mnemonic string to implement
    a branch specified by CODE.  If INV is true, return mnemonic
    for the corresponding inverted branch.  */
@@ -1068,6 +1104,8 @@ s390_branch_condition_mask (rtx code)
 static const char *
 s390_branch_condition_mnemonic (rtx code, int inv)
 {
+  int mask;
+
   static const char *const mnemonic[16] =
     {
       NULL, "o", "h", "nle",
@@ -1076,7 +1114,13 @@ s390_branch_condition_mnemonic (rtx code, int inv)
       "le", "nh", "no", NULL
     };
 
-  int mask = s390_branch_condition_mask (code);
+  if (GET_CODE (XEXP (code, 0)) == REG
+      && REGNO (XEXP (code, 0)) == CC_REGNUM
+      && XEXP (code, 1) == const0_rtx)
+    mask = s390_branch_condition_mask (code);
+  else
+    mask = s390_compare_and_branch_condition_mask (code);
+
   gcc_assert (mask >= 0);
 
   if (inv)
@@ -1153,6 +1197,67 @@ s390_single_part (rtx op,
   return part == -1 ? -1 : n_parts - 1 - part;
 }
 
+/* Return true if IN contains a contiguous bitfield in the lower SIZE
+   bits and no other bits are set in IN.  POS and LENGTH can be used
+   to obtain the start position and the length of the bitfield.
+
+   POS gives the position of the first bit of the bitfield counting
+   from the lowest order bit starting with zero.  In order to use this
+   value for S/390 instructions this has to be converted to "bits big
+   endian" style.  */
+
+bool
+s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size,
+                          int *pos, int *length)
+{
+  int tmp_pos = 0;
+  int tmp_length = 0;
+  int i;
+  unsigned HOST_WIDE_INT mask = 1ULL;
+  bool contiguous = false;
+
+  for (i = 0; i < size; mask <<= 1, i++)
+    {
+      if (contiguous)
+       {
+         if (mask & in)
+           tmp_length++;
+         else
+           break;
+       }
+      else
+       {
+         if (mask & in)
+           {
+             contiguous = true;
+             tmp_length++;
+           }
+         else
+           tmp_pos++;
+       }
+    }
+
+  if (!tmp_length)
+    return false;
+
+  /* Calculate a mask for all bits beyond the contiguous bits.  */
+  mask = (-1LL & ~(((1ULL << (tmp_length + tmp_pos - 1)) << 1) - 1));
+
+  if (mask & in)
+    return false;
+
+  if (tmp_length + tmp_pos - 1 > size)
+    return false;
+
+  if (length)
+    *length = tmp_length;
+
+  if (pos)
+    *pos = tmp_pos;
+
+  return true;
+}
+
 /* Check whether we can (and want to) split a double-word
    move in mode MODE from SRC to DST into two single-word
    moves, moving the subword FIRST_SUBWORD first.  */
@@ -2034,10 +2139,9 @@ s390_mem_constraint (const char *str, rtx op)
        return 0;
       if (GET_CODE (op) != MEM)
        return 0;
-      /* Any invalid address here will be fixed up by reload,
-        so accept it for the most generic constraint.  */
-      if (s390_decompose_address (XEXP (op, 0), &addr)
-         && s390_short_displacement (addr.disp))
+      if (!s390_decompose_address (XEXP (op, 0), &addr))
+       return 0;
+      if (s390_short_displacement (addr.disp))
        return 0;
       break;
 
@@ -2054,10 +2158,9 @@ s390_mem_constraint (const char *str, rtx op)
     case 'W':
       if (!TARGET_LONG_DISPLACEMENT)
        return 0;
-      /* Any invalid address here will be fixed up by reload,
-        so accept it for the most generic constraint.  */
-      if (s390_decompose_address (op, &addr)
-         && s390_short_displacement (addr.disp))
+      if (!s390_decompose_address (op, &addr))
+       return 0;
+      if (s390_short_displacement (addr.disp))
        return 0;
       break;
 
@@ -2693,6 +2796,132 @@ s390_preferred_reload_class (rtx op, enum reg_class class)
   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.  */
+
+bool
+s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment)
+{
+  HOST_WIDE_INT addend;
+  rtx symref;
+
+  if (!s390_symref_operand_p (addr, &symref, &addend))
+    return false;
+
+  return (!SYMBOL_REF_NOT_NATURALLY_ALIGNED_P (symref)
+         && !(addend & (alignment - 1)));
+}
+
+/* ADDR is moved into REG using larl.  If ADDR isn't a valid larl
+   operand SCRATCH is used to reload the even part of the address and
+   adding one.  */
+
+void
+s390_reload_larl_operand (rtx reg, rtx addr, rtx scratch)
+{
+  HOST_WIDE_INT addend;
+  rtx symref;
+
+  if (!s390_symref_operand_p (addr, &symref, &addend))
+    gcc_unreachable ();
+
+  if (!(addend & 1))
+    /* Easy case.  The addend is even so larl will do fine.  */
+    emit_move_insn (reg, addr);
+  else
+    {
+      /* We can leave the scratch register untouched if the target
+        register is a valid base register.  */
+      if (REGNO (reg) < FIRST_PSEUDO_REGISTER
+         && REGNO_REG_CLASS (REGNO (reg)) == ADDR_REGS)
+       scratch = reg;
+
+      gcc_assert (REGNO (scratch) < FIRST_PSEUDO_REGISTER);
+      gcc_assert (REGNO_REG_CLASS (REGNO (scratch)) == ADDR_REGS);
+
+      if (addend != 1)
+       emit_move_insn (scratch,
+                       gen_rtx_CONST (Pmode,
+                                      gen_rtx_PLUS (Pmode, symref,
+                                                    GEN_INT (addend - 1))));
+      else
+       emit_move_insn (scratch, symref);
+
+      /* Increment the address using la in order to avoid clobbering cc.  */
+      emit_move_insn (reg, gen_rtx_PLUS (Pmode, scratch, const1_rtx));
+    }
+}
+
+/* Generate what is necessary to move between REG and MEM using
+   SCRATCH.  The direction is given by TOMEM.  */
+
+void
+s390_reload_symref_address (rtx reg, rtx mem, rtx scratch, bool tomem)
+{
+  /* Reload might have pulled a constant out of the literal pool.
+     Force it back in.  */
+  if (CONST_INT_P (mem) || GET_CODE (mem) == CONST_DOUBLE
+      || GET_CODE (mem) == CONST)
+    mem = force_const_mem (GET_MODE (reg), mem);
+
+  gcc_assert (MEM_P (mem));
+
+  /* For a load from memory we can leave the scratch register
+     untouched if the target register is a valid base register.  */
+  if (!tomem
+      && REGNO (reg) < FIRST_PSEUDO_REGISTER
+      && REGNO_REG_CLASS (REGNO (reg)) == ADDR_REGS
+      && GET_MODE (reg) == GET_MODE (scratch))
+    scratch = reg;
+
+  /* Load address into scratch register.  Since we can't have a
+     secondary reload for a secondary reload we have to cover the case
+     where larl would need a secondary reload here as well.  */
+  s390_reload_larl_operand (scratch, XEXP (mem, 0), scratch);
+
+  /* Now we can use a standard load/store to do the move.  */
+  if (tomem)
+    emit_move_insn (replace_equiv_address (mem, scratch), reg);
+  else
+    emit_move_insn (reg, replace_equiv_address (mem, scratch));
+}
+
 /* Inform reload about cases where moving X with a mode MODE to a register in
    CLASS requires an extra scratch or immediate register.  Return the class
    needed for the immediate register.  */
@@ -2705,6 +2934,60 @@ s390_secondary_reload (bool in_p, rtx x, enum reg_class class,
   if (reg_classes_intersect_p (CC_REGS, class))
     return GENERAL_REGS;
 
+  if (TARGET_Z10)
+    {
+      /* On z10 several optimizer steps may generate larl operands with
+        an odd addend.  */
+      if (in_p
+         && s390_symref_operand_p (x, NULL, NULL)
+         && mode == Pmode
+         && !s390_check_symref_alignment (x, 2))
+       sri->icode = ((mode == DImode) ? CODE_FOR_reloaddi_larl_odd_addend_z10
+                     : CODE_FOR_reloadsi_larl_odd_addend_z10);
+
+      /* On z10 we need a scratch register when moving QI, TI or floating
+        point mode values from or to a memory location with a SYMBOL_REF
+        or if the symref addend of a SI or DI move is not aligned to the
+        width of the access.  */
+      if (MEM_P (x)
+         && s390_symref_operand_p (XEXP (x, 0), NULL, NULL)
+         && (mode == QImode || mode == TImode || FLOAT_MODE_P (mode)
+             || (!TARGET_64BIT && mode == DImode)
+             || ((mode == HImode || mode == SImode || mode == DImode)
+                 && (!s390_check_symref_alignment (XEXP (x, 0),
+                                                   GET_MODE_SIZE (mode))))))
+       {
+#define __SECONDARY_RELOAD_CASE(M,m)                                   \
+         case M##mode:                                                 \
+           if (TARGET_64BIT)                                           \
+             sri->icode = in_p ? CODE_FOR_reload##m##di_toreg_z10 :    \
+                                  CODE_FOR_reload##m##di_tomem_z10;    \
+           else                                                        \
+             sri->icode = in_p ? CODE_FOR_reload##m##si_toreg_z10 :    \
+                                  CODE_FOR_reload##m##si_tomem_z10;    \
+         break;
+
+         switch (GET_MODE (x))
+           {
+             __SECONDARY_RELOAD_CASE (QI, qi);
+             __SECONDARY_RELOAD_CASE (HI, hi);
+             __SECONDARY_RELOAD_CASE (SI, si);
+             __SECONDARY_RELOAD_CASE (DI, di);
+             __SECONDARY_RELOAD_CASE (TI, ti);
+             __SECONDARY_RELOAD_CASE (SF, sf);
+             __SECONDARY_RELOAD_CASE (DF, df);
+             __SECONDARY_RELOAD_CASE (TF, tf);
+             __SECONDARY_RELOAD_CASE (SD, sd);
+             __SECONDARY_RELOAD_CASE (DD, dd);
+             __SECONDARY_RELOAD_CASE (TD, td);
+
+           default:
+             gcc_unreachable ();
+           }
+#undef __SECONDARY_RELOAD_CASE
+       }
+    }
+
   /* We need a scratch register when loading a PLUS expression which
      is not a legitimate operand of the LOAD ADDRESS instruction.  */
   if (in_p && s390_plus_operand (x, mode))
@@ -2811,10 +3094,16 @@ s390_expand_plus_operand (rtx target, rtx src,
    STRICT specifies whether strict register checking applies.  */
 
 bool
-legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
-                     rtx addr, int strict)
+legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
 {
   struct s390_address ad;
+
+  if (TARGET_Z10
+      && larl_operand (addr, VOIDmode)
+      && (mode == VOIDmode
+         || s390_check_symref_alignment (addr, GET_MODE_SIZE (mode))))
+    return true;
+
   if (!s390_decompose_address (addr, &ad))
     return false;
 
@@ -4052,14 +4341,31 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
   return false;
 }
 
-/* Expand code for the insv template. Return true if successful, false else.  */
+/* Expand code for the insv template. Return true if successful.  */
 
-bool 
+bool
 s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
 {
   int bitsize = INTVAL (op1);
   int bitpos = INTVAL (op2);
 
+  /* On z10 we can use the risbg instruction to implement insv.  */
+  if (TARGET_Z10
+      && ((GET_MODE (dest) == DImode && GET_MODE (src) == DImode)
+         || (GET_MODE (dest) == SImode && GET_MODE (src) == SImode)))
+    {
+      rtx op;
+      rtx clobber;
+
+      op = gen_rtx_SET (GET_MODE(src),
+                       gen_rtx_ZERO_EXTRACT (GET_MODE (dest), dest, op1, op2),
+                       src);
+      clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
+      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clobber)));
+
+      return true;
+    }
+
   /* We need byte alignment.  */
   if (bitsize % BITS_PER_UNIT)
     return false;
@@ -4596,6 +4902,13 @@ print_operand_address (FILE *file, rtx addr)
 {
   struct s390_address ad;
 
+  if (s390_symref_operand_p (addr, NULL, NULL))
+    {
+      gcc_assert (TARGET_Z10);
+      output_addr_const (file, addr);
+      return;
+    }
+
   if (!s390_decompose_address (addr, &ad)
       || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
       || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
@@ -4629,6 +4942,7 @@ print_operand_address (FILE *file, rtx addr)
     'Y': print shift count operand.
 
     'b': print integer X as if it's an unsigned byte.
+    'c': print integer X as if it's an signed byte.
     'x': print integer X as if it's an unsigned halfword.
     'h': print integer X as if it's a signed halfword.
     'i': print the first nonzero HImode part of X.
@@ -4774,6 +5088,8 @@ print_operand (FILE *file, rtx x, int code)
     case CONST_INT:
       if (code == 'b')
         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
+      else if (code == 'c')
+        fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xff) ^ 0x80) - 0x80);
       else if (code == 'x')
         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
       else if (code == 'h')
@@ -8563,11 +8879,30 @@ s390_encode_section_info (tree decl, rtx rtl, int first)
 {
   default_encode_section_info (decl, rtl, first);
 
-  /* If a variable has a forced alignment to < 2 bytes, mark it with
-     SYMBOL_FLAG_ALIGN1 to prevent it from being used as LARL operand.  */
-  if (TREE_CODE (decl) == VAR_DECL
-      && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16)
-    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
+  if (TREE_CODE (decl) == VAR_DECL)
+    {
+      /* If a variable has a forced alignment to < 2 bytes, mark it
+        with SYMBOL_FLAG_ALIGN1 to prevent it from being used as LARL
+        operand.  */
+      if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16)
+       SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
+      if (!DECL_SIZE (decl)
+         || !DECL_ALIGN (decl)
+         || !host_integerp (DECL_SIZE (decl), 0)
+         || (DECL_ALIGN (decl) <= 64
+             && DECL_ALIGN (decl) != tree_low_cst (DECL_SIZE (decl), 0)))
+       SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED;
+    }
+
+  /* Literal pool references don't have a decl so they are handled
+     differently here.  We rely on the information in the MEM_ALIGN
+     entry to decide upon natural alignment.  */
+  if (MEM_P (rtl)
+      && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
+      && TREE_CONSTANT_POOL_ADDRESS_P (XEXP (rtl, 0))
+      && (MEM_ALIGN (rtl) == 0
+         || MEM_ALIGN (rtl) < GET_MODE_BITSIZE (GET_MODE (rtl))))
+    SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED;
 }
 
 /* Output thunk to FILE that implements a C++ virtual function call (with
index 819154feef1a0f95958e844e72c8b194d6129487..79286d5a9bc86af0bb03bc29883d83004750a356 100644 (file)
@@ -1,8 +1,9 @@
 /* Definitions of target machine for GNU compiler, for IBM S/390
    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-   2007 Free Software Foundation, Inc.
+   2007, 2008 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
                   Ulrich Weigand (uweigand@de.ibm.com).
+                  Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
 
 This file is part of GCC.
 
@@ -62,6 +63,10 @@ extern enum processor_flags s390_tune_flags;
 extern enum processor_type s390_arch;
 extern enum processor_flags s390_arch_flags;
 
+/* These flags indicate that the generated code should run on a cpu
+   providing the respective hardware facility regardless of the
+   current cpu mode (ESA or z/Architecture).  */
+
 #define TARGET_CPU_IEEE_FLOAT \
        (s390_arch_flags & PF_IEEE_FLOAT)
 #define TARGET_CPU_ZARCH \
@@ -75,6 +80,10 @@ extern enum processor_flags s390_arch_flags;
 #define TARGET_CPU_Z10 \
        (s390_arch_flags & PF_Z10)
 
+/* These flags indicate that the generated code should run on a cpu
+   providing the respective hardware facility when run in
+   z/Architecture mode.  */
+
 #define TARGET_LONG_DISPLACEMENT \
        (TARGET_ZARCH && TARGET_CPU_LONG_DISPLACEMENT)
 #define TARGET_EXTIMM \
@@ -491,11 +500,14 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
 #define PREFERRED_RELOAD_CLASS(X, CLASS)       \
   s390_preferred_reload_class ((X), (CLASS))
 
-/* We need secondary memory to move data between GPRs and FPRs.  */
+/* We need secondary memory to move data between GPRs and FPRs.  With
+   DFP the ldgr lgdr instructions are available.  But these
+   instructions do not handle GPR pairs so it is not possible for 31
+   bit.  */
 #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
  ((CLASS1) != (CLASS2)                                \
   && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS)     \
-  && (!TARGET_DFP || GET_MODE_SIZE (MODE) != 8))
+  && (!TARGET_DFP || !TARGET_64BIT || GET_MODE_SIZE (MODE) != 8))
 
 /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
    because the movsi and movsf patterns don't handle r/f moves.  */
@@ -693,6 +705,13 @@ CUMULATIVE_ARGS;
 /* Maximum number of registers that can appear in a valid memory address.  */
 #define MAX_REGS_PER_ADDRESS 2
 
+/* This definition replaces the formerly used 'm' constraint with a
+different constraint letter in order to avoid changing semantics of
+the 'm' constraint when accepting new address formats in
+legitimate_address_p.  The constraint letter defined here must not be
+used in insn definitions or inline assemblies.  */
+#define TARGET_MEM_CONSTRAINT 'e'
+
 /* S/390 has no mode dependent addresses.  */
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
 
@@ -959,7 +978,12 @@ do {                                                                       \
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1)
 
 /* Machine-specific symbol_ref flags.  */
-#define SYMBOL_FLAG_ALIGN1     (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_FLAG_ALIGN1               (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_REF_ALIGN1_P(X)         \
+  ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_ALIGN1))
+#define SYMBOL_FLAG_NOT_NATURALLY_ALIGNED (SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_REF_NOT_NATURALLY_ALIGNED_P(X) \
+  ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_NOT_NATURALLY_ALIGNED))
 
 /* Check whether integer displacement is in range.  */
 #define DISP_IN_RANGE(d) \
index 54f4e0e9a87fd51ab997e92f973ef62ca911f101..f97e756518f876a39dbce5449ec9bfcef6df0ae6 100644 (file)
@@ -1,8 +1,9 @@
 ;;- Machine description for GNU compiler -- S/390 / zSeries version.
-;;  Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;  Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
 ;;  Free Software Foundation, Inc.
 ;;  Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;;                 Ulrich Weigand (uweigand@de.ibm.com).
+;;                 Ulrich Weigand (uweigand@de.ibm.com) and
+;;                 Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
 
 ;; This file is part of GCC.
 
@@ -38,6 +39,7 @@
 ;;     %Y: print shift count operand.
 ;;  
 ;;     %b: print integer X as if it's an unsigned byte.
+;;     %c: print integer X as if it's an signed byte.
 ;;     %x: print integer X as if it's an unsigned halfword.
 ;;     %h: print integer X as if it's a signed halfword.
 ;;     %i: print the first nonzero HImode part of X.
 ;; Used to determine defaults for length and other attribute values.
 
 (define_attr "op_type"
-  "NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE,RXY,RSY,SIY,RRF,RRR"
+  "NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE,RXY,RSY,SIY,RRF,RRR,SIL,RRS,RIS"
   (const_string "NN"))
 
 ;; Instruction type attribute used for scheduling.
 ;; Length in bytes.
 
 (define_attr "length" ""
-  (cond [(eq_attr "op_type" "E,RR")                  (const_int 2)
-         (eq_attr "op_type" "RX,RI,RRE,RS,RSI,S,SI")  (const_int 4)]
+  (cond [(eq_attr "op_type" "E,RR")                          (const_int 2)
+         (eq_attr "op_type" "RX,RI,RRE,RS,RSI,S,SI,RRF,RRR")  (const_int 4)]
     (const_int 6)))
 
 
 (define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP") 
                               (SD "TARGET_HARD_DFP")])
 (define_mode_iterator FP [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
+(define_mode_iterator FPALL [TF DF SF TD DD SD])
 (define_mode_iterator BFP [TF DF SF])
 (define_mode_iterator DFP [TD DD])
 (define_mode_iterator DFP_ALL [TD DD SD])
 ;; This mode iterator allows the integer patterns to be defined from the
 ;; same template.
 (define_mode_iterator INT [(DI "TARGET_64BIT") SI HI QI])
+(define_mode_iterator INTALL [TI DI SI HI QI])
 
 ;; This iterator allows to unify all 'bCOND' expander patterns.
 (define_code_iterator COMPARE [eq ne gt gtu lt ltu ge geu le leu unordered 
 ;; Maximum unsigned integer that fits in MODE.
 (define_mode_attr max_uint [(HI "65535") (QI "255")])
 
-
 ;;
 ;;- Compare instructions.
 ;;
 
 (define_insn "*tstdi_sign"
   [(set (reg CC_REGNUM)
-        (compare (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 0 "register_operand" "d") 0)
-                                        (const_int 32)) (const_int 32))
-                 (match_operand:DI 1 "const0_operand" "")))
-   (set (match_operand:DI 2 "register_operand" "=d")
+        (compare
+          (ashiftrt:DI
+            (ashift:DI
+              (subreg:DI (match_operand:SI 0 "nonimmediate_operand" "d,RT") 0)
+             (const_int 32)) (const_int 32))
+         (match_operand:DI 1 "const0_operand" "")))
+   (set (match_operand:DI 2 "register_operand" "=d,d")
         (sign_extend:DI (match_dup 0)))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
-  "ltgfr\t%2,%0"
-  [(set_attr "op_type" "RRE")])
+  "ltgfr\t%2,%0
+   ltgf\t%2,%0"
+  [(set_attr "op_type"      "RRE,RXY")
+   (set_attr "cpu_facility" "*,z10")])
 
 ; ltr, lt, ltgr, ltg
 (define_insn "*tst<mode>_extimm"
 
 (define_insn "*cmpdi_ccs_sign"
   [(set (reg CC_REGNUM)
-        (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT"))
-                 (match_operand:DI 0 "register_operand" "d,d")))]
+        (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand"
+                                                    "d,RT,b"))
+                 (match_operand:DI 0 "register_operand" "d, d,d")))]
   "s390_match_ccmode(insn, CCSRmode) && TARGET_64BIT"
   "@
    cgfr\t%0,%1
-   cgf\t%0,%1"
-  [(set_attr "op_type" "RRE,RXY")])
+   cgf\t%0,%1
+   cgfrl\t%0,%1"
+  [(set_attr "op_type"      "RRE,RXY,RIL")
+   (set_attr "cpu_facility" "*,*,z10")
+   (set_attr "type"         "*,*,larl")])
 
 (define_insn "*cmpsi_ccs_sign"
   [(set (reg CC_REGNUM)
-        (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T"))
-                 (match_operand:SI 0 "register_operand" "d,d")))]
+        (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T,b"))
+                 (match_operand:SI 0 "register_operand" "d,d,d")))]
   "s390_match_ccmode(insn, CCSRmode)"
   "@
    ch\t%0,%1
-   chy\t%0,%1"
-  [(set_attr "op_type" "RX,RXY")])
+   chy\t%0,%1
+   chrl\t%0,%1"
+  [(set_attr "op_type"      "RX,RXY,RIL")
+   (set_attr "cpu_facility" "*,*,z10")
+   (set_attr "type"         "*,*,larl")])
+
+(define_insn "*cmphi_ccs_z10"
+  [(set (reg CC_REGNUM)
+        (compare (match_operand:HI 0 "s_operand"         "Q")
+                 (match_operand:HI 1 "immediate_operand" "K")))]
+  "s390_match_ccmode(insn, CCSmode) && TARGET_Z10"
+  "chhsi\t%0,%1"
+  [(set_attr "op_type" "SIL")])
+
+(define_insn "*cmpdi_ccs_signhi_rl"
+  [(set (reg CC_REGNUM)
+       (compare (sign_extend:DI (match_operand:HI 1 "memory_operand" "RT,b"))
+                (match_operand:GPR 0 "register_operand"  "d,d")))]
+  "s390_match_ccmode(insn, CCSRmode) && TARGET_Z10"
+  "@
+   cgh\t%0,%1
+   cghrl\t%0,%1"
+  [(set_attr "op_type" "RXY,RIL")
+   (set_attr "type"    "*,larl")])
 
-; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg
+; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg, chsi, cghsi, crl, cgrl
 (define_insn "*cmp<mode>_ccs"
   [(set (reg CC_REGNUM)
-        (compare (match_operand:GPR 0 "register_operand" "d,d,d,d,d")
-                 (match_operand:GPR 1 "general_operand" "d,K,Os,R,T")))]
+        (compare (match_operand:GPR 0 "nonimmediate_operand"
+                                      "d,d,Q, d,d,d,d")
+                 (match_operand:GPR 1 "general_operand"
+                                      "d,K,K,Os,R,T,b")))]
   "s390_match_ccmode(insn, CCSmode)"
   "@
    c<g>r\t%0,%1
    c<g>hi\t%0,%h1
+   c<g>hsi\t%0,%h1
    c<g>fi\t%0,%1
    c<g>\t%0,%1
-   c<y>\t%0,%1"
-  [(set_attr "op_type" "RR<E>,RI,RIL,RX<Y>,RXY")])
+   c<y>\t%0,%1
+   c<g>rl\t%0,%1"
+  [(set_attr "op_type" "RR<E>,RI,SIL,RIL,RX<Y>,RXY,RIL")
+   (set_attr "cpu_facility" "*,*,z10,extimm,*,*,z10")
+   (set_attr "type" "*,*,*,*,*,*,larl")])
 
 
 ; Compare (unsigned) instructions
 
+(define_insn "*cmpsi_ccu_zerohi_rlsi"
+  [(set (reg CC_REGNUM)
+       (compare (zero_extend:SI (mem:HI (match_operand:SI 1
+                                         "larl_operand" "X")))
+                (match_operand:SI 0 "register_operand" "d")))]
+  "s390_match_ccmode(insn, CCURmode) && TARGET_Z10"
+  "clhrl\t%0,%1"
+  [(set_attr "op_type" "RIL")
+   (set_attr "type"    "larl")])
+
+; clhrl, clghrl
+(define_insn "*cmp<GPR:mode>_ccu_zerohi_rldi"
+  [(set (reg CC_REGNUM)
+       (compare (zero_extend:GPR (mem:HI (match_operand:DI 1
+                                         "larl_operand" "X")))
+                (match_operand:GPR 0 "register_operand" "d")))]
+  "s390_match_ccmode(insn, CCURmode) && TARGET_Z10"
+  "cl<g>hrl\t%0,%1"
+  [(set_attr "op_type" "RIL")
+   (set_attr "type"    "larl")])
+
 (define_insn "*cmpdi_ccu_zero"
   [(set (reg CC_REGNUM)
-        (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT"))
-                 (match_operand:DI 0 "register_operand" "d,d")))]
+        (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand"
+                                                        "d,RT,b"))
+                 (match_operand:DI 0 "register_operand" "d, d,d")))]
   "s390_match_ccmode (insn, CCURmode) && TARGET_64BIT"
   "@
    clgfr\t%0,%1
-   clgf\t%0,%1"
-  [(set_attr "op_type" "RRE,RXY")])
+   clgf\t%0,%1
+   clgfrl\t%0,%1"
+  [(set_attr "op_type"      "RRE,RXY,RIL")
+   (set_attr "cpu_facility" "*,*,z10")
+   (set_attr "type"         "*,*,larl")])
 
 (define_insn "*cmpdi_ccu"
   [(set (reg CC_REGNUM)
-        (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,d,Q,BQ")
-                 (match_operand:DI 1 "general_operand" "d,Op,RT,BQ,Q")))]
+        (compare (match_operand:DI 0 "nonimmediate_operand"
+                                     "d, d,d,Q, d, Q,BQ")
+                 (match_operand:DI 1 "general_operand"
+                                     "d,Op,b,D,RT,BQ,Q")))]
   "s390_match_ccmode (insn, CCUmode) && TARGET_64BIT"
   "@
    clgr\t%0,%1
    clgfi\t%0,%1
+   clgrl\t%0,%1
+   clghsi\t%0,%x1
    clg\t%0,%1
    #
    #"
-  [(set_attr "op_type" "RRE,RIL,RXY,SS,SS")])
+  [(set_attr "op_type" "RRE,RIL,RIL,SIL,RXY,SS,SS")
+   (set_attr "cpu_facility" "*,extimm,z10,z10,*,*,*")
+   (set_attr "type"         "*,*,larl,*,*,*,*")])
 
 (define_insn "*cmpsi_ccu"
   [(set (reg CC_REGNUM)
-        (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,d,Q,BQ")
-                 (match_operand:SI 1 "general_operand" "d,Os,R,T,BQ,Q")))]
+        (compare (match_operand:SI 0 "nonimmediate_operand" "d, d,d,Q,d,d, Q,BQ")
+                 (match_operand:SI 1 "general_operand"      "d,Os,b,D,R,T,BQ, Q")))]
   "s390_match_ccmode (insn, CCUmode)"
   "@
    clr\t%0,%1
    clfi\t%0,%o1
+   clrl\t%0,%1
+   clfhsi\t%0,%x1
    cl\t%0,%1
    cly\t%0,%1
    #
    #"
-  [(set_attr "op_type" "RR,RIL,RX,RXY,SS,SS")])
+  [(set_attr "op_type" "RR,RIL,RIL,SIL,RX,RXY,SS,SS")
+   (set_attr "cpu_facility" "*,extimm,z10,z10,*,*,*,*")
+   (set_attr "type"         "*,*,larl,*,*,*,*,*")])
 
 (define_insn "*cmphi_ccu"
   [(set (reg CC_REGNUM)
-        (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,BQ")
-                 (match_operand:HI 1 "general_operand" "Q,S,BQ,Q")))]
+        (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,Q,BQ")
+                 (match_operand:HI 1 "general_operand"      "Q,S,D,BQ,Q")))]
   "s390_match_ccmode (insn, CCUmode)
    && !register_operand (operands[1], HImode)"
   "@
    clm\t%0,3,%S1
    clmy\t%0,3,%S1
+   clhhsi\t%0,%1
    #
    #"
-  [(set_attr "op_type" "RS,RSY,SS,SS")])
+  [(set_attr "op_type" "RS,RSY,SIL,SS,SS")
+   (set_attr "cpu_facility" "*,*,z10,*,*")])
 
 (define_insn "*cmpqi_ccu"
   [(set (reg CC_REGNUM)
    [(set_attr "op_type" "RRE,RXE")
     (set_attr "type"  "fsimp<bfp>")])
 
+
+; Compare and Branch instructions
+
+; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
+(define_insn "*cmp_and_br_signed_<mode>"
+  [(set (pc)
+       (if_then_else (match_operator 0 "s390_signed_integer_comparison"
+                       [(match_operand:GPR 1 "register_operand"  "d,d")
+                        (match_operand:GPR 2 "nonmemory_operand" "d,C")])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_Z10"
+{
+  if (get_attr_length (insn) == 6)
+    return which_alternative ?
+      "c<g>ij%C0\t%1,%c2,%l3" : "c<g>rj%C0\t%1,%2,%l3";
+  else
+    return which_alternative ?
+      "c<g>fi\t%1,%c2\;jg%C0\t%l3" : "c<g>r\t%1,%2\;jg%C0\t%l3";
+}
+  [(set_attr "op_type" "RIE")
+   (set_attr "type"    "branch")
+   (set (attr "length")
+        (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
+                      (const_int 6) (const_int 12)))]) ; 8 byte for cr/jg
+                                                       ; 10 byte for cgr/jg
+
+; clij, clgij, clrj, clgrj, clfi, clgfi, clr, clgr
+(define_insn "*cmp_and_br_unsigned_<mode>"
+  [(set (pc)
+       (if_then_else (match_operator 0 "s390_unsigned_integer_comparison"
+                       [(match_operand:GPR 1 "register_operand"  "d,d")
+                        (match_operand:GPR 2 "nonmemory_operand" "d,I")])
+                     (label_ref (match_operand 3 "" ""))
+                     (pc)))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_Z10"
+{
+  if (get_attr_length (insn) == 6)
+    return which_alternative ?
+      "cl<g>ij%C0\t%1,%b2,%l3" : "cl<g>rj%C0\t%1,%2,%l3";
+  else
+    return which_alternative ?
+      "cl<g>fi\t%1,%b2\;jg%C0\t%l3" : "cl<g>r\t%1,%2\;jg%C0\t%l3";
+}
+  [(set_attr "op_type" "RIE")
+   (set_attr "type"    "branch")
+   (set (attr "length")
+        (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
+                      (const_int 6) (const_int 12)))]) ; 8 byte for clr/jg
+                                                       ; 10 byte for clgr/jg
+
 ;;
 ;;- Move instructions.
 ;;
 ; Patterns used for secondary reloads
 ;
 
+; z10 provides move instructions accepting larl memory operands.
+; Unfortunately there is no such variant for QI, TI and FP mode moves.
+; These patterns are also used for unaligned SI and DI accesses.
+
+(define_expand "reload<INTALL:mode><P:mode>_tomem_z10"
+  [(parallel [(match_operand:INTALL 0 "memory_operand"   "")
+             (match_operand:INTALL 1 "register_operand" "=d")
+             (match_operand:P 2 "register_operand" "=&a")])]
+  "TARGET_Z10"
+{
+  s390_reload_symref_address (operands[1], operands[0], operands[2], 1);
+  DONE;
+})
+
+(define_expand "reload<INTALL:mode><P:mode>_toreg_z10"
+  [(parallel [(match_operand:INTALL 0 "register_operand" "=d")
+             (match_operand:INTALL 1 "memory_operand"   "")
+             (match_operand:P 2 "register_operand" "=a")])]
+  "TARGET_Z10"
+{
+  s390_reload_symref_address (operands[0], operands[1], operands[2], 0);
+  DONE;
+})
+
+(define_expand "reload<FPALL:mode><P:mode>_tomem_z10"
+  [(parallel [(match_operand:FPALL 0 "memory_operand"   "")
+             (match_operand:FPALL 1 "register_operand" "=d")
+             (match_operand:P 2 "register_operand" "=&a")])]
+  "TARGET_Z10"
+{
+  s390_reload_symref_address (operands[1], operands[0], operands[2], 1);
+  DONE;
+})
+
+(define_expand "reload<FPALL:mode><P:mode>_toreg_z10"
+  [(parallel [(match_operand:FPALL 0 "register_operand" "=d")
+             (match_operand:FPALL 1 "memory_operand"   "")
+             (match_operand:P 2 "register_operand" "=a")])]
+  "TARGET_Z10"
+{
+  s390_reload_symref_address (operands[0], operands[1], operands[2], 0);
+  DONE;
+})
+
+(define_expand "reload<P:mode>_larl_odd_addend_z10"
+  [(parallel [(match_operand:P 0 "register_operand" "=d")
+             (match_operand:P 1 "larl_operand"     "")
+             (match_operand:P 2 "register_operand" "=a")])]
+  "TARGET_Z10"
+{
+  s390_reload_larl_operand (operands[0], operands[1], operands[2]);
+  DONE;
+})
+
 ; Handles loading a PLUS (load address) expression
 
 (define_expand "reload<mode>_plus"
 
 (define_insn "*movdi_64"
   [(set (match_operand:DI 0 "nonimmediate_operand"
-                            "=d,d,d,d,d,d,d,d,f,d,d,d,d,
-                             RT,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+                            "=d,d,d,d,d,d,d,d,f,d,d,d,d,d,
+                             RT,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t,?Q")
         (match_operand:DI 1 "general_operand"
-                            "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,d,RT,
-                             d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
+                            "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,b,d,RT,
+                             d,*f,R,T,*f,*f,d,K,t,d,t,Q,?Q"))]
   "TARGET_64BIT"
   "@
    lghi\t%0,%h1
    ldgr\t%0,%1
    lgdr\t%0,%1
    lay\t%0,%a1
+   lgrl\t%0,%1
    lgr\t%0,%1
    lg\t%0,%1
    stg\t%1,%0
    ldy\t%0,%1
    std\t%1,%0
    stdy\t%1,%0
+   stgrl\t%1,%0
+   mvghi\t%0,%1
    #
    #
    stam\t%1,%N1,%S0
    lam\t%0,%N0,%S1
    #"
-  [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RRE,RXY,RXY,
-                        RR,RX,RXY,RX,RXY,*,*,RS,RS,SS")
-   (set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,lr,load,store,
-                     floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*,*,*,*")
+  [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RIL,RRE,RXY,
+                        RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS,SS")
+   (set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,larl,lr,load,store,
+                     floaddf,floaddf,floaddf,fstoredf,fstoredf,larl,*,*,*,
+                     *,*,*")
    (set_attr "cpu_facility" "*,*,*,*,*,extimm,extimm,extimm,dfp,dfp,longdisp,
-                             *,*,*,*,*,longdisp,*,longdisp,*,*,*,*,*")])
+                             z10,*,*,*,*,*,longdisp,*,longdisp,
+                             z10,z10,*,*,*,*,*")])
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
    s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
 
 (define_insn "*movdi_31"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,Q,S,d,o,!*f,!*f,!*f,!R,!T,Q")
-        (match_operand:DI 1 "general_operand" "Q,S,d,d,dPRT,d,*f,R,T,*f,*f,Q"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand"
+                            "=d,d,Q,S,d   ,o,!*f,!*f,!*f,!R,!T,Q,d")
+        (match_operand:DI 1 "general_operand"
+                            " Q,S,d,d,dPRT,d, *f,  R,  T,*f,*f,Q,b"))]
   "!TARGET_64BIT"
   "@
    lm\t%0,%N0,%S1
    ldy\t%0,%1
    std\t%1,%0
    stdy\t%1,%0
+   #
    #"
-  [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,SS")
-   (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*")])
+  [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,SS,*")
+   (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*")
+   (set_attr "cpu_facility" "*,*,*,*,*,*,*,*,*,*,*,*,z10")])
+
+; For a load from a symbol ref we can use one of the target registers
+; together with larl to load the address.
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+        (match_operand:DI 1 "memory_operand" ""))]
+  "!TARGET_64BIT && reload_completed && TARGET_Z10
+   && larl_operand (XEXP (operands[1], 0), SImode)"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 0) (match_dup 1))]
+{
+  operands[2] = operand_subword (operands[0], 1, 0, DImode);
+  operands[3] = XEXP (operands[1], 0);
+  operands[1] = replace_equiv_address (operands[1], operands[2]);
+})
 
 (define_split
   [(set (match_operand:DI 0 "nonimmediate_operand" "")
 
 (define_insn "*movsi_zarch"
   [(set (match_operand:SI 0 "nonimmediate_operand"
-                           "=d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+                           "=d,d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,b,Q,t,?Q")
         (match_operand:SI 1 "general_operand"
-                           "K,N0HS0,N1HS0,Os,L,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
+                           "K,N0HS0,N1HS0,Os,L,b,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,d,K,Q,?Q"))]
   "TARGET_ZARCH"
   "@
    lhi\t%0,%h1
    llill\t%0,%i1
    iilf\t%0,%o1
    lay\t%0,%a1
+   lrl\t%0,%1
    lr\t%0,%1
    l\t%0,%1
    ly\t%0,%1
    ear\t%0,%1
    sar\t%0,%1
    stam\t%1,%1,%S0
+   strl\t%1,%0
+   mvhi\t%0,%1
    lam\t%0,%0,%S1
    #"
-  [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RR,RX,RXY,RX,RXY,
-                        RR,RX,RXY,RX,RXY,RRE,RRE,RS,RS,SS")
-   (set_attr "type" "*,*,*,*,la,lr,load,load,store,store,
-                     floadsf,floadsf,floadsf,fstoresf,fstoresf,*,*,*,*,*")])
+  [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RIL,RR,RX,RXY,RX,RXY,
+                        RR,RX,RXY,RX,RXY,RRE,RRE,RS,RIL,SIL,RS,SS")
+   (set_attr "type" "*,*,*,*,la,larl,lr,load,load,store,store,
+                     floadsf,floadsf,floadsf,fstoresf,fstoresf,*,*,*,larl,*,*,*")
+   (set_attr "cpu_facility" "*,*,*,extimm,longdisp,z10,*,*,longdisp,*,longdisp,
+                             *,*,longdisp,*,longdisp,*,*,*,z10,z10,*,*")])
 
 (define_insn "*movsi_esa"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t,?Q")
 })
 
 (define_insn "*movhi"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,T,?Q")
-        (match_operand:HI 1 "general_operand" "d,n,R,T,d,d,?Q"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,d,R,T,b,Q,?Q")
+        (match_operand:HI 1 "general_operand"      " d,n,R,T,b,d,d,d,K,?Q"))]
   ""
   "@
    lr\t%0,%1
    lhi\t%0,%h1
    lh\t%0,%1
    lhy\t%0,%1
+   lhrl\t%0,%1
    sth\t%1,%0
    sthy\t%1,%0
+   sthrl\t%1,%0
+   mvhhi\t%0,%1
    #"
-  [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")
-   (set_attr "type" "lr,*,*,*,store,store,*")])
+  [(set_attr "op_type"      "RR,RI,RX,RXY,RIL,RX,RXY,RIL,SIL,SS")
+   (set_attr "type"         "lr,*,*,*,larl,store,store,store,*,*")
+   (set_attr "cpu_facility" "*,*,*,*,z10,*,*,z10,z10,*")])
 
 (define_peephole2
   [(set (match_operand:HI 0 "register_operand" "")
 ;; String instructions.
 ;;
 
+(define_insn "*execute_rl"
+  [(match_parallel 0 ""
+    [(unspec [(match_operand 1    "register_operand" "a")
+             (match_operand 2    "" "")
+              (match_operand:SI 3 "larl_operand" "X")] UNSPEC_EXECUTE)])]
+  "TARGET_Z10 && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
+   && GET_MODE_SIZE (GET_MODE (operands[1])) <= UNITS_PER_WORD"
+  "exrl\t%1,%3"
+  [(set_attr "op_type" "RIL")
+   (set_attr "type"    "cs")])
+
 (define_insn "*execute"
   [(match_parallel 0 ""
     [(unspec [(match_operand 1 "register_operand" "a")
 ;
 
 (define_expand "movmem<mode>"
-  [(set (match_operand:BLK 0 "memory_operand" "")
-        (match_operand:BLK 1 "memory_operand" ""))
-   (use (match_operand:GPR 2 "general_operand" ""))
+  [(set (match_operand:BLK 0 "memory_operand" "")   ; destination
+        (match_operand:BLK 1 "memory_operand" ""))  ; source
+   (use (match_operand:GPR 2 "general_operand" "")) ; count
    (match_operand 3 "" "")]
   ""
   "s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;")
   "operands[3] = gen_rtx_SCRATCH (Pmode);")
 
 (define_insn "*movmem_short"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
-        (match_operand:BLK 1 "memory_operand" "Q,Q,Q"))
-   (use (match_operand 2 "nonmemory_operand" "n,a,a"))
-   (use (match_operand 3 "immediate_operand" "X,R,X"))
-   (clobber (match_scratch 4 "=X,X,&a"))]
+  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
+        (match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q"))
+   (use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
+   (use (match_operand 3 "immediate_operand" "X,R,X,X"))
+   (clobber (match_scratch 4 "=X,X,X,&a"))]
   "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
    && GET_MODE (operands[4]) == Pmode"
   "#"
-  [(set_attr "type" "cs")])
+  [(set_attr "type"         "cs")
+   (set_attr "cpu_facility" "*,*,z10,*")])
 
 (define_split
   [(set (match_operand:BLK 0 "memory_operand" "")
      (use (const_int 1))])]
   "")
 
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (match_operand:BLK 1 "memory_operand" ""))
+   (use (match_operand 2 "register_operand" ""))
+   (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+   (clobber (scratch))]
+  "TARGET_Z10 && reload_completed"
+  [(parallel
+    [(unspec [(match_dup 2) (const_int 0)
+              (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+     (set (match_dup 0) (match_dup 1))
+     (use (const_int 1))])]
+  "operands[3] = gen_label_rtx ();")
+
 (define_split
   [(set (match_operand:BLK 0 "memory_operand" "")
         (match_operand:BLK 1 "memory_operand" ""))
   "operands[2] = gen_rtx_SCRATCH (Pmode);")
 
 (define_insn "*clrmem_short"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
         (const_int 0))
-   (use (match_operand 1 "nonmemory_operand" "n,a,a"))
-   (use (match_operand 2 "immediate_operand" "X,R,X"))
-   (clobber (match_scratch 3 "=X,X,&a"))
+   (use (match_operand 1 "nonmemory_operand" "n,a,a,a"))
+   (use (match_operand 2 "immediate_operand" "X,R,X,X"))
+   (clobber (match_scratch 3 "=X,X,X,&a"))
    (clobber (reg:CC CC_REGNUM))]
   "(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
    && GET_MODE (operands[3]) == Pmode"
   "#"
-  [(set_attr "type" "cs")])
+  [(set_attr "type" "cs")
+   (set_attr "cpu_facility" "*,*,z10,*")])
 
 (define_split
   [(set (match_operand:BLK 0 "memory_operand" "")
      (clobber (reg:CC CC_REGNUM))])]
   "")
 
+(define_split
+  [(set (match_operand:BLK 0 "memory_operand" "")
+        (const_int 0))
+   (use (match_operand 1 "register_operand" ""))
+   (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+   (clobber (scratch))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_Z10 && reload_completed"
+  [(parallel
+    [(unspec [(match_dup 1) (const_int 0)
+              (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+     (set (match_dup 0) (const_int 0))
+     (use (const_int 1))
+     (clobber (reg:CC CC_REGNUM))])]
+  "operands[3] = gen_label_rtx ();")
+
 (define_split
   [(set (match_operand:BLK 0 "memory_operand" "")
         (const_int 0))
 
 (define_insn "*cmpmem_short"
   [(set (reg:CCU CC_REGNUM)
-        (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q")
-                     (match_operand:BLK 1 "memory_operand" "Q,Q,Q")))
-   (use (match_operand 2 "nonmemory_operand" "n,a,a"))
-   (use (match_operand 3 "immediate_operand" "X,R,X"))
-   (clobber (match_scratch 4 "=X,X,&a"))]
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q,Q")
+                     (match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q")))
+   (use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
+   (use (match_operand 3 "immediate_operand" "X,R,X,X"))
+   (clobber (match_scratch 4 "=X,X,X,&a"))]
   "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
    && GET_MODE (operands[4]) == Pmode"
   "#"
-  [(set_attr "type" "cs")])
+  [(set_attr "type" "cs")
+   (set_attr "cpu_facility" "*,*,z10,*")])
 
 (define_split
   [(set (reg:CCU CC_REGNUM)
      (use (const_int 1))])]
   "")
 
+(define_split
+  [(set (reg:CCU CC_REGNUM)
+        (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+                     (match_operand:BLK 1 "memory_operand" "")))
+   (use (match_operand 2 "register_operand" ""))
+   (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+   (clobber (scratch))]
+  "TARGET_Z10 && reload_completed"
+  [(parallel
+    [(unspec [(match_dup 2) (const_int 0)
+              (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+     (set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
+     (use (const_int 1))])]
+  "operands[4] = gen_label_rtx ();")
+
 (define_split
   [(set (reg:CCU CC_REGNUM)
         (compare:CCU (match_operand:BLK 0 "memory_operand" "")
   FAIL;
 })
 
+(define_insn "*insv<mode>_z10"
+  [(set (zero_extract:GPR (match_operand:GPR 0 "nonimmediate_operand" "+d")
+                         (match_operand 1 "const_int_operand"    "I")
+                         (match_operand 2 "const_int_operand"    "I"))
+       (match_operand:GPR 3 "nonimmediate_operand" "d"))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_Z10
+   && (INTVAL (operands[1]) + INTVAL (operands[2])) <=
+      GET_MODE_BITSIZE (<MODE>mode)"
+{
+  int start = INTVAL (operands[2]);
+  int size = INTVAL (operands[1]);
+  int offset = 64 - GET_MODE_BITSIZE (<MODE>mode);
+
+  operands[2] = GEN_INT (offset + start);              /* start bit position */
+  operands[1] = GEN_INT (offset + start + size - 1);   /* end bit position */
+  operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
+                        start - size);       /* left shift count */
+
+  return "risbg\t%0,%3,%b2,%b1,%b4";
+}
+  [(set_attr "op_type" "RIE")])
+
+; and op1 with a mask being 1 for the selected bits and 0 for the rest
+; and op3=op0 with a mask being 0 for the selected bits and 1 for the rest
+(define_insn "*insv<mode>_z10_noshift"
+  [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
+       (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d")
+                         (match_operand 2 "const_int_operand" "n"))
+                (and:GPR (match_operand:GPR 3 "nonimmediate_operand" "0")
+                         (match_operand 4 "const_int_operand" "n"))))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_Z10
+   && s390_contiguous_bitmask_p (INTVAL (operands[2]),
+                                 GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)
+   && INTVAL (operands[2]) == ~(INTVAL (operands[4]))"
+
+{
+  int start;
+  int size;
+
+  s390_contiguous_bitmask_p (INTVAL (operands[2]),
+                             GET_MODE_BITSIZE (<MODE>mode), &start, &size);
+
+  operands[5] = GEN_INT (64 - start - size); /* start bit position */
+  operands[6] = GEN_INT (64 - 1 - start);    /* end bit position */
+  operands[7] = const0_rtx;                  /* left shift count */
+
+  return "risbg\t%0,%1,%b5,%b6,%b7";
+}
+  [(set_attr "op_type" "RIE")])
+
+; and op1 with a mask being 1 for the selected bits and 0 for the rest
+(define_insn "*insv<mode>_or_z10_noshift"
+  [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
+       (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d")
+                         (match_operand 2 "const_int_operand" "n"))
+               (match_operand:GPR 3 "nonimmediate_operand" "0")))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_Z10
+   && s390_contiguous_bitmask_p (INTVAL (operands[2]),
+                                 GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)"
+{
+  int start;
+  int size;
+
+  s390_contiguous_bitmask_p (INTVAL (operands[2]),
+                             GET_MODE_BITSIZE (<MODE>mode), &start, &size);
+
+  operands[4] = GEN_INT (64 - start - size); /* start bit position */
+  operands[5] = GEN_INT (64 - 1 - start);    /* end bit position */
+  operands[6] = const0_rtx;                  /* left shift count */
+
+  return "rosbg\t%0,%1,%b4,%b5,%b6";
+}
+  [(set_attr "op_type" "RIE")])
+
 (define_insn "*insv<mode>_mem_reg"
   [(set (zero_extract:P (match_operand:QI 0 "memory_operand" "+Q,S")
                        (match_operand 1 "const_int_operand" "n,n")
 })
 
 (define_insn "*extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT")))]
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT,b")))]
   "TARGET_64BIT"
   "@
    lgfr\t%0,%1
-   lgf\t%0,%1"
-  [(set_attr "op_type" "RRE,RXY")])
+   lgf\t%0,%1
+   lgfrl\t%0,%1"
+  [(set_attr "op_type"      "RRE,RXY,RIL")
+   (set_attr "type"         "*,*,larl")
+   (set_attr "cpu_facility" "*,*,z10")])
 
 ;
 ; extend(hi|qi)(si|di)2 instruction pattern(s).
 ;
 
 (define_insn "*extendhidi2_extimm"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,RT")))]
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+        (sign_extend:DI (match_operand:HI 1 "general_operand" "d,RT,b")))]
   "TARGET_64BIT && TARGET_EXTIMM"
   "@
    lghr\t%0,%1
-   lgh\t%0,%1"
-  [(set_attr "op_type" "RRE,RXY")])
+   lgh\t%0,%1
+   lghrl\t%0,%1"
+  [(set_attr "op_type"      "RRE,RXY,RIL")
+   (set_attr "type"         "*,*,larl")
+   (set_attr "cpu_facility" "extimm,extimm,z10")])
 
 (define_insn "*extendhidi2"
   [(set (match_operand:DI 0 "register_operand" "=d")
 ;
 
 (define_insn "*extendhisi2_extimm"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,T")))]
+  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" " d,R,T,b")))]
   "TARGET_EXTIMM"
   "@
    lhr\t%0,%1
    lh\t%0,%1
-   lhy\t%0,%1"
-  [(set_attr "op_type" "RRE,RX,RXY")])
+   lhy\t%0,%1
+   lhrl\t%0,%1"
+  [(set_attr "op_type"      "RRE,RX,RXY,RIL")
+   (set_attr "type"         "*,*,*,larl")
+   (set_attr "cpu_facility" "extimm,extimm,extimm,z10")])
 
 (define_insn "*extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
 })
 
 (define_insn "*zero_extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT")))]
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+        (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT,b")))]
   "TARGET_64BIT"
   "@
    llgfr\t%0,%1
-   llgf\t%0,%1"
-  [(set_attr "op_type" "RRE,RXY")])
+   llgf\t%0,%1
+   llgfrl\t%0,%1"
+  [(set_attr "op_type"      "RRE,RXY,RIL")
+   (set_attr "type"         "*,*,larl")
+   (set_attr "cpu_facility" "*,*,z10")])
 
 ;
 ; LLGT-type instructions (zero-extend from 31 bit to 64 bit).
     }
 })
 
+; llhrl, llghrl
+(define_insn "*zero_extendhi<mode>2_z10"
+  [(set (match_operand:GPR 0 "register_operand" "=d,d,d")
+        (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "d,RT,b")))]
+  "TARGET_Z10"
+  "@
+   ll<g>hr\t%0,%1
+   ll<g>h\t%0,%1
+   ll<g>hrl\t%0,%1"
+  [(set_attr "op_type"      "RXY,RRE,RIL")
+   (set_attr "type"         "*,*,larl")
+   (set_attr "cpu_facility" "*,*,z10")])
+
 ; llhr, llcr, llghr, llgcr, llh, llc, llgh, llgc
 (define_insn "*zero_extend<HQI:mode><GPR:mode>2_extimm"
   [(set (match_operand:GPR 0 "register_operand" "=d,d")
 
 (define_expand "adddi3"
   [(parallel
-    [(set (match_operand:DI 0 "register_operand" "")
+    [(set (match_operand:DI 0 "nonimmediate_operand" "")
           (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
                    (match_operand:DI 2 "general_operand" "")))
      (clobber (reg:CC CC_REGNUM))])]
   [(set_attr "op_type"  "RRE,RXY")])
 
 (define_insn_and_split "*adddi3_31z"
-  [(set (match_operand:DI 0 "register_operand" "=&d")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
                  (match_operand:DI 2 "general_operand" "do") ) )
    (clobber (reg:CC CC_REGNUM))]
    operands[8] = operand_subword (operands[2], 1, 0, DImode);")
 
 (define_insn_and_split "*adddi3_31"
-  [(set (match_operand:DI 0 "register_operand" "=&d")
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
                  (match_operand:DI 2 "general_operand" "do") ) )
    (clobber (reg:CC CC_REGNUM))]
 
 (define_expand "addsi3"
   [(parallel
-    [(set (match_operand:SI 0 "register_operand" "")
+    [(set (match_operand:SI 0 "nonimmediate_operand" "")
           (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
                    (match_operand:SI 2 "general_operand" "")))
      (clobber (reg:CC CC_REGNUM))])]
 ; add(di|si)3 instruction pattern(s).
 ;
 
-; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag
+; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag, asi, agsi
 (define_insn "*add<mode>3"
-  [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d")
-        (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
-                 (match_operand:GPR 2 "general_operand" "d,K,Op,On,R,T") ) )
+  [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,d,QS")
+        (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0,0")
+                 (match_operand:GPR 2 "general_operand" "d,K,Op,On,R,T,C") ) )
    (clobber (reg:CC CC_REGNUM))]
   ""
   "@
    al<g>fi\t%0,%2
    sl<g>fi\t%0,%n2
    a<g>\t%0,%2
-   a<y>\t%0,%2"
-  [(set_attr "op_type"  "RR<E>,RI,RIL,RIL,RX<Y>,RXY")])
+   a<y>\t%0,%2
+   a<g>si\t%0,%c2"
+  [(set_attr "op_type"  "RR<E>,RI,RIL,RIL,RX<Y>,RXY,SIY")
+   (set_attr "cpu_facility" "*,*,extimm,extimm,*,*,z10")])
 
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi
 (define_insn "*add<mode>3_carry1_cc"
   [(set (reg CC_REGNUM)
-        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
-                          (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
+        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+                          (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
                  (match_dup 1)))
-   (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+   (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,d")
         (plus:GPR (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode (insn, CCL1mode)"
   "@
    al<g>fi\t%0,%2
    sl<g>fi\t%0,%n2
    al<g>\t%0,%2
-   al<y>\t%0,%2"
-  [(set_attr "op_type"  "RR<E>,RIL,RIL,RX<Y>,RXY")])
+   al<y>\t%0,%2
+   al<g>si\t%0,%c2"
+  [(set_attr "op_type"      "RR<E>,RIL,RIL,RX<Y>,RXY,SIY")
+   (set_attr "cpu_facility" "*,extimm,extimm,*,*,z10")])
 
 ; alr, al, aly, algr, alg
 (define_insn "*add<mode>3_carry1_cconly"
    al<y>\t%0,%2"
   [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
 
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi
 (define_insn "*add<mode>3_carry2_cc"
   [(set (reg CC_REGNUM)
-        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
-                          (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
+        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+                          (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
                  (match_dup 2)))
-   (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+   (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,RS")
         (plus:GPR (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode (insn, CCL1mode)"
   "@
    al<g>fi\t%0,%2
    sl<g>fi\t%0,%n2
    al<g>\t%0,%2
-   al<y>\t%0,%2"
-  [(set_attr "op_type"  "RR<E>,RIL,RIL,RX<Y>,RXY")])
+   al<y>\t%0,%2
+   al<g>si\t%0,%c2"
+  [(set_attr "op_type"  "RR<E>,RIL,RIL,RX<Y>,RXY,SIY")
+   (set_attr "cpu_facility" "*,extimm,extimm,*,*,z10")])
 
 ; alr, al, aly, algr, alg
 (define_insn "*add<mode>3_carry2_cconly"
    al<y>\t%0,%2"
   [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
 
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi
 (define_insn "*add<mode>3_cc"
   [(set (reg CC_REGNUM)
-        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
-                          (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
+        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+                          (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
                  (const_int 0)))
-   (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+   (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,RS")
         (plus:GPR (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode (insn, CCLmode)"
   "@
    al<g>fi\t%0,%2
    sl<g>fi\t%0,%n2
    al<g>\t%0,%2
-   al<y>\t%0,%2"
-  [(set_attr "op_type"  "RR<E>,RIL,RIL,RX<Y>,RXY")])
+   al<y>\t%0,%2
+   al<g>si\t%0,%c2"
+  [(set_attr "op_type"  "RR<E>,RIL,RIL,RX<Y>,RXY,SIY")
+   (set_attr "cpu_facility" "*,extimm,extimm,*,*,z10")])
 
 ; alr, al, aly, algr, alg
 (define_insn "*add<mode>3_cconly"
    al<y>\t%0,%2"
   [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
 
-; ahi, afi, aghi, agfi
+; ahi, afi, aghi, agfi, asi, agsi
 (define_insn "*add<mode>3_imm_cc"
   [(set (reg CC_REGNUM)
-        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
-                          (match_operand:GPR 2 "const_int_operand" "K,Os"))
+        (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0,0")
+                          (match_operand:GPR 2 "const_int_operand" "K,Os,C"))
                  (const_int 0)))
-   (set (match_operand:GPR 0 "register_operand" "=d,d")
+   (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,QS")
         (plus:GPR (match_dup 1) (match_dup 2)))]
   "s390_match_ccmode (insn, CCAmode)
    && (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")
-       || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'O', \"Os\"))
+       || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'O', \"Os\")
+       || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'C', \"C\"))
    && INTVAL (operands[2]) != -((HOST_WIDE_INT)1 << (GET_MODE_BITSIZE(<MODE>mode) - 1))"
   "@
    a<g>hi\t%0,%h2
-   a<g>fi\t%0,%2"
-  [(set_attr "op_type"  "RI,RIL")])
+   a<g>fi\t%0,%2
+   a<g>si\t%0,%c2"
+  [(set_attr "op_type"      "RI,RIL,SIY")
+   (set_attr "cpu_facility" "*,extimm,z10")])
 
 ;
 ; add(tf|df|sf|td|dd)3 instruction pattern(s).
 
 (define_insn "*muldi3_sign"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (mult:DI (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,RT"))
+        (mult:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
                  (match_operand:DI 1 "register_operand" "0,0")))]
   "TARGET_64BIT"
   "@
    msgfr\t%0,%2
    msgf\t%0,%2"
-  [(set_attr "op_type"  "RRE,RXY")
-   (set_attr "type"     "imuldi")])
+  [(set_attr "op_type"      "RRE,RXY")
+   (set_attr "type"         "imuldi")])
 
 (define_insn "muldi3"
-  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
-        (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
-                 (match_operand:DI 2 "general_operand" "d,K,RT")))]
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d,d")
+        (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0")
+                 (match_operand:DI 2 "general_operand" "d,K,RT,Os")))]
   "TARGET_64BIT"
   "@
    msgr\t%0,%2
    mghi\t%0,%h2
-   msg\t%0,%2"
-  [(set_attr "op_type"  "RRE,RI,RXY")
-   (set_attr "type"     "imuldi")])
+   msg\t%0,%2
+   msgfi\t%0,%2"
+  [(set_attr "op_type"      "RRE,RI,RXY,RIL")
+   (set_attr "type"         "imuldi")
+   (set_attr "cpu_facility" "*,*,*,z10")])
 
 ;
 ; mulsi3 instruction pattern(s).
 ;
 
 (define_insn "*mulsi3_sign"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-        (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R"))
-                 (match_operand:SI 1 "register_operand" "0")))]
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))
+                 (match_operand:SI 1 "register_operand" "0,0")))]
   ""
-  "mh\t%0,%2"
-  [(set_attr "op_type"  "RX")
-   (set_attr "type"     "imulhi")])
+  "@
+   mh\t%0,%2
+   mhy\t%0,%2"
+  [(set_attr "op_type"      "RX,RXY")
+   (set_attr "type"         "imulhi")
+   (set_attr "cpu_facility" "*,z10")])
 
 (define_insn "mulsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
-        (mult:SI  (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
-                  (match_operand:SI 2 "general_operand" "d,K,R,T")))]
+  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
+        (mult:SI  (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0")
+                  (match_operand:SI 2 "general_operand" "d,K,R,T,Os")))]
   ""
   "@
    msr\t%0,%2
    mhi\t%0,%h2
    ms\t%0,%2
-   msy\t%0,%2"
-  [(set_attr "op_type"  "RRE,RI,RX,RXY")
-   (set_attr "type"     "imulsi,imulhi,imulsi,imulsi")])
+   msy\t%0,%2
+   msfi\t%0,%2"
+  [(set_attr "op_type"      "RRE,RI,RX,RXY,RIL")
+   (set_attr "type"         "imulsi,imulhi,imulsi,imulsi,imulsi")
+   (set_attr "cpu_facility" "*,*,*,*,z10")])
 
 ;
 ; mulsidi3 instruction pattern(s).
 ;
 
 (define_insn "mulsidi3"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
+  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
         (mult:DI (sign_extend:DI
-                  (match_operand:SI 1 "register_operand" "%0,0"))
+                  (match_operand:SI 1 "register_operand" "%0,0,0"))
                  (sign_extend:DI
-                  (match_operand:SI 2 "nonimmediate_operand" "d,R"))))]
+                  (match_operand:SI 2 "nonimmediate_operand" "d,R,T"))))]
   "!TARGET_64BIT"
   "@
    mr\t%0,%2
-   m\t%0,%2"
-  [(set_attr "op_type"  "RR,RX")
-   (set_attr "type"     "imulsi")])
+   m\t%0,%2
+   mfy\t%0,%2"
+  [(set_attr "op_type"      "RR,RX,RXY")
+   (set_attr "type"         "imulsi")
+   (set_attr "cpu_facility" "*,*,z10")])
 
 ;
 ; umulsidi3 instruction pattern(s).
   [(set_attr "op_type" "RI")
    (set_attr "type"  "branch")])
 
+; crt, cgrt, cit, cgit
+(define_insn "*cmp_and_trap_signed_int<mode>"
+  [(trap_if (match_operator 0 "s390_signed_integer_comparison"
+              [(match_operand:GPR 1 "register_operand"  "d,d")
+               (match_operand:GPR 2 "nonmemory_operand" "d,K")])
+           (const_int 0))]
+  "TARGET_Z10"
+  "@
+   c<g>rt%C0\t%1,%2
+   c<g>it%C0\t%1,%h2"
+  [(set_attr "op_type" "RRF,RIE")
+   (set_attr "type"    "branch")])
+
+; clrt, clgrt, clfit, clgit
+(define_insn "*cmp_and_trap_unsigned_int<mode>"
+  [(trap_if (match_operator 0 "s390_unsigned_integer_comparison"
+              [(match_operand:GPR 1 "register_operand"  "d,d")
+               (match_operand:GPR 2 "nonmemory_operand" "d,D")])
+           (const_int 0))]
+  "TARGET_Z10"
+  "@
+   cl<g>rt%C0\t%1,%2
+   cl<gf>it%C0\t%1,%x2"
+  [(set_attr "op_type" "RRF,RIE")
+   (set_attr "type"    "branch")])
+
 ;;
 ;;- Loop instructions.
 ;;
   ""
   ""
   [(set_attr "length" "0")])
+
+
+;
+; Data prefetch patterns
+;
+
+(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"
+{
+  if (larl_operand (operands[0], Pmode))
+    return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
+
+  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.  */
+
+  return "";
+
+} [(set_attr "type" "load,larl")
+   (set_attr "op_type" "RXY,RIL")])