[Committed] S/390: Support the new instructions introduced with System z10 Enterprise Class Mainframe

Andreas Krebbel Andreas.Krebbel@de.ibm.com
Wed May 28 14:59:00 GMT 2008


Committed to mainline.

This patch does not cover the pipeline description for z10. The new
instruction support can be used without it although it will certainly
not provide the expected performance.

The pipeline description will be posted soon.

Bye,

-Andreas-


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.


Index: gcc/config/s390/constraints.md
===================================================================
*** gcc/config/s390/constraints.md.orig	2008-05-15 10:27:36.000000000 +0200
--- gcc/config/s390/constraints.md	2008-05-27 08:50:08.000000000 +0200
***************
*** 1,5 ****
  ;; Constraints definitions belonging to the gcc backend for IBM S/390.
! ;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
  ;; Written by Wolfgang Gellerich, using code and information found in
  ;; files s390.md, s390.h, and s390.c.
  ;;
--- 1,5 ----
  ;; Constraints definitions belonging to the gcc backend for IBM S/390.
! ;; 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.
  ;;
***************
*** 24,33 ****
--- 24,37 ----
  ;; 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).
***************
*** 102,107 ****
--- 106,124 ----
  ;;  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"
***************
*** 127,133 ****
         (match_test "ival >= -32768 && ival <= 32767")))
  
  
- 
  (define_constraint "L"
    "Value appropriate as displacement.
        (0..4095) for short displacement
--- 144,149 ----
***************
*** 355,361 ****
    (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)"))
--- 371,376 ----
***************
*** 371,376 ****
--- 386,412 ----
    (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 
***************
*** 425,431 ****
    (match_test "s390_mem_constraint (\"BT\", op)"))
  
  
- 
  (define_address_constraint "U"
    "Pointer with short displacement"
    (match_test "s390_mem_constraint (\"U\", op)"))
--- 461,466 ----
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig	2008-05-27 08:49:56.000000000 +0200
--- gcc/config/s390/s390.c	2008-05-27 08:50:08.000000000 +0200
***************
*** 1,8 ****
  /* 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.
     Contributed by Hartmut Penner (hpenner@de.ibm.com) and
!                   Ulrich Weigand (uweigand@de.ibm.com).
  
  This file is part of GCC.
  
--- 1,9 ----
  /* Subroutines used for code generation on IBM S/390 and zSeries
     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) and
!                   Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
  
  This file is part of GCC.
  
*************** s390_branch_condition_mask (rtx code)
*** 1061,1066 ****
--- 1062,1102 ----
      }
  }
  
+ 
+ /* 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.  */
*************** s390_branch_condition_mask (rtx code)
*** 1068,1073 ****
--- 1104,1111 ----
  static const char *
  s390_branch_condition_mnemonic (rtx code, int inv)
  {
+   int mask;
+ 
    static const char *const mnemonic[16] =
      {
        NULL, "o", "h", "nle",
*************** s390_branch_condition_mnemonic (rtx code
*** 1076,1082 ****
        "le", "nh", "no", NULL
      };
  
!   int mask = s390_branch_condition_mask (code);
    gcc_assert (mask >= 0);
  
    if (inv)
--- 1114,1126 ----
        "le", "nh", "no", NULL
      };
  
!   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)
*************** s390_single_part (rtx op,
*** 1153,1158 ****
--- 1197,1263 ----
    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.  */
*************** s390_mem_constraint (const char *str, rt
*** 2034,2043 ****
  	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))
  	return 0;
        break;
  
--- 2139,2147 ----
  	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))
  	return 0;
        break;
  
*************** s390_mem_constraint (const char *str, rt
*** 2054,2063 ****
      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))
  	return 0;
        break;
  
--- 2158,2166 ----
      case 'W':
        if (!TARGET_LONG_DISPLACEMENT)
  	return 0;
!       if (!s390_decompose_address (op, &addr))
! 	return 0;
!       if (s390_short_displacement (addr.disp))
  	return 0;
        break;
  
*************** s390_preferred_reload_class (rtx op, enu
*** 2693,2698 ****
--- 2796,2927 ----
    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.  */
*************** s390_secondary_reload (bool in_p, rtx x,
*** 2705,2710 ****
--- 2934,2993 ----
    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))
*************** s390_expand_plus_operand (rtx target, rt
*** 2811,2820 ****
     STRICT specifies whether strict register checking applies.  */
  
  bool
! legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
! 		      rtx addr, int strict)
  {
    struct s390_address ad;
    if (!s390_decompose_address (addr, &ad))
      return false;
  
--- 3094,3109 ----
     STRICT specifies whether strict register checking applies.  */
  
  bool
! 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;
  
*************** s390_expand_addcc (enum rtx_code cmp_cod
*** 4052,4065 ****
    return false;
  }
  
! /* Expand code for the insv template. Return true if successful, false else.  */
  
! bool 
  s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
  {
    int bitsize = INTVAL (op1);
    int bitpos = INTVAL (op2);
  
    /* We need byte alignment.  */
    if (bitsize % BITS_PER_UNIT)
      return false;
--- 4341,4371 ----
    return false;
  }
  
! /* Expand code for the insv template. Return true if successful.  */
  
! 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;
*************** print_operand_address (FILE *file, rtx a
*** 4596,4601 ****
--- 4902,4914 ----
  {
    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))))
*************** print_operand_address (FILE *file, rtx a
*** 4629,4634 ****
--- 4942,4948 ----
      '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.
*************** print_operand (FILE *file, rtx x, int co
*** 4774,4779 ****
--- 5088,5095 ----
      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')
*************** s390_encode_section_info (tree decl, rtx
*** 8563,8573 ****
  {
    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;
  }
  
  /* Output thunk to FILE that implements a C++ virtual function call (with
--- 8879,8908 ----
  {
    default_encode_section_info (decl, rtl, first);
  
!   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: gcc/config/s390/s390.md
===================================================================
*** gcc/config/s390/s390.md.orig	2008-05-27 08:49:56.000000000 +0200
--- gcc/config/s390/s390.md	2008-05-27 08:50:08.000000000 +0200
***************
*** 1,8 ****
  ;;- Machine description for GNU compiler -- S/390 / zSeries version.
! ;;  Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
  ;;  Free Software Foundation, Inc.
  ;;  Contributed by Hartmut Penner (hpenner@de.ibm.com) and
! ;;                 Ulrich Weigand (uweigand@de.ibm.com).
  
  ;; This file is part of GCC.
  
--- 1,9 ----
  ;;- Machine description for GNU compiler -- S/390 / zSeries version.
! ;;  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) and
! ;;                 Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
  
  ;; This file is part of GCC.
  
***************
*** 38,43 ****
--- 39,45 ----
  ;;     %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.
***************
*** 189,195 ****
  ;; 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"
    (const_string "NN"))
  
  ;; Instruction type attribute used for scheduling.
--- 191,197 ----
  ;; 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,SIL,RRS,RIS"
    (const_string "NN"))
  
  ;; Instruction type attribute used for scheduling.
***************
*** 218,225 ****
  ;; 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)]
      (const_int 6)))
  
  
--- 220,227 ----
  ;; 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,RRF,RRR")  (const_int 4)]
      (const_int 6)))
  
  
***************
*** 286,291 ****
--- 288,294 ----
  (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])
***************
*** 315,320 ****
--- 318,324 ----
  ;; 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 
***************
*** 457,463 ****
  ;; Maximum unsigned integer that fits in MODE.
  (define_mode_attr max_uint [(HI "65535") (QI "255")])
  
- 
  ;;
  ;;- Compare instructions.
  ;;
--- 461,466 ----
***************
*** 543,556 ****
  
  (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")
          (sign_extend:DI (match_dup 0)))]
    "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
!   "ltgfr\t%2,%0"
!   [(set_attr "op_type" "RRE")])
  
  ; ltr, lt, ltgr, ltg
  (define_insn "*tst<mode>_extimm"
--- 546,564 ----
  
  (define_insn "*tstdi_sign"
    [(set (reg CC_REGNUM)
!         (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
!    ltgf\t%2,%0"
!   [(set_attr "op_type"      "RRE,RXY")
!    (set_attr "cpu_facility" "*,z10")])
  
  ; ltr, lt, ltgr, ltg
  (define_insn "*tst<mode>_extimm"
***************
*** 726,815 ****
  
  (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")))]
    "s390_match_ccmode(insn, CCSRmode) && TARGET_64BIT"
    "@
     cgfr\t%0,%1
!    cgf\t%0,%1"
!   [(set_attr "op_type" "RRE,RXY")])
  
  (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")))]
    "s390_match_ccmode(insn, CCSRmode)"
    "@
     ch\t%0,%1
!    chy\t%0,%1"
!   [(set_attr "op_type" "RX,RXY")])
  
! ; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg
  (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")))]
    "s390_match_ccmode(insn, CCSmode)"
    "@
     c<g>r\t%0,%1
     c<g>hi\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")])
  
  
  ; Compare (unsigned) instructions
  
  (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")))]
    "s390_match_ccmode (insn, CCURmode) && TARGET_64BIT"
    "@
     clgfr\t%0,%1
!    clgf\t%0,%1"
!   [(set_attr "op_type" "RRE,RXY")])
  
  (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")))]
    "s390_match_ccmode (insn, CCUmode) && TARGET_64BIT"
    "@
     clgr\t%0,%1
     clgfi\t%0,%1
     clg\t%0,%1
     #
     #"
!   [(set_attr "op_type" "RRE,RIL,RXY,SS,SS")])
  
  (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")))]
    "s390_match_ccmode (insn, CCUmode)"
    "@
     clr\t%0,%1
     clfi\t%0,%o1
     cl\t%0,%1
     cly\t%0,%1
     #
     #"
!   [(set_attr "op_type" "RR,RIL,RX,RXY,SS,SS")])
  
  (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")))]
    "s390_match_ccmode (insn, CCUmode)
     && !register_operand (operands[1], HImode)"
    "@
     clm\t%0,3,%S1
     clmy\t%0,3,%S1
     #
     #"
!   [(set_attr "op_type" "RS,RSY,SS,SS")])
  
  (define_insn "*cmpqi_ccu"
    [(set (reg CC_REGNUM)
--- 734,892 ----
  
  (define_insn "*cmpdi_ccs_sign"
    [(set (reg CC_REGNUM)
!         (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
!    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,b"))
!                  (match_operand:SI 0 "register_operand" "d,d,d")))]
    "s390_match_ccmode(insn, CCSRmode)"
    "@
     ch\t%0,%1
!    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, chsi, cghsi, crl, cgrl
  (define_insn "*cmp<mode>_ccs"
    [(set (reg CC_REGNUM)
!         (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
!    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,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
!    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, 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,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,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,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,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,SIL,SS,SS")
!    (set_attr "cpu_facility" "*,*,z10,*,*")])
  
  (define_insn "*cmpqi_ccu"
    [(set (reg CC_REGNUM)
***************
*** 885,890 ****
--- 962,1020 ----
     [(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.
  ;;
***************
*** 951,956 ****
--- 1081,1140 ----
  ; 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"
***************
*** 1020,1030 ****
  
  (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")
          (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"))]
    "TARGET_64BIT"
    "@
     lghi\t%0,%h1
--- 1204,1214 ----
  
  (define_insn "*movdi_64"
    [(set (match_operand:DI 0 "nonimmediate_operand"
!                             "=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,b,d,RT,
!                              d,*f,R,T,*f,*f,d,K,t,d,t,Q,?Q"))]
    "TARGET_64BIT"
    "@
     lghi\t%0,%h1
***************
*** 1038,1043 ****
--- 1222,1228 ----
     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
***************
*** 1046,1062 ****
     ldy\t%0,%1
     std\t%1,%0
     stdy\t%1,%0
     #
     #
     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 "cpu_facility" "*,*,*,*,*,extimm,extimm,extimm,dfp,dfp,longdisp,
!                              *,*,*,*,*,longdisp,*,longdisp,*,*,*,*,*")])
  
  (define_split
    [(set (match_operand:DI 0 "register_operand" "")
--- 1231,1251 ----
     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,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,
!                              z10,*,*,*,*,*,longdisp,*,longdisp,
!                              z10,z10,*,*,*,*,*")])
  
  (define_split
    [(set (match_operand:DI 0 "register_operand" "")
***************
*** 1092,1099 ****
     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"))]
    "!TARGET_64BIT"
    "@
     lm\t%0,%N0,%S1
--- 1281,1290 ----
     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,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
***************
*** 1107,1115 ****
     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,*")])
  
  (define_split
    [(set (match_operand:DI 0 "nonimmediate_operand" "")
--- 1298,1323 ----
     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 "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" "")
***************
*** 1227,1235 ****
  
  (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")
          (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"))]
    "TARGET_ZARCH"
    "@
     lhi\t%0,%h1
--- 1435,1443 ----
  
  (define_insn "*movsi_zarch"
    [(set (match_operand:SI 0 "nonimmediate_operand"
! 			    "=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,b,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,d,K,Q,?Q"))]
    "TARGET_ZARCH"
    "@
     lhi\t%0,%h1
***************
*** 1237,1242 ****
--- 1445,1451 ----
     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
***************
*** 1250,1261 ****
     ear\t%0,%1
     sar\t%0,%1
     stam\t%1,%1,%S0
     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,*,*,*,*,*")])
  
  (define_insn "*movsi_esa"
    [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t,?Q")
--- 1459,1474 ----
     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,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")
***************
*** 1381,1399 ****
  })
  
  (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"))]
    ""
    "@
     lr\t%0,%1
     lhi\t%0,%h1
     lh\t%0,%1
     lhy\t%0,%1
     sth\t%1,%0
     sthy\t%1,%0
     #"
!   [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")
!    (set_attr "type" "lr,*,*,*,store,store,*")])
  
  (define_peephole2
    [(set (match_operand:HI 0 "register_operand" "")
--- 1594,1616 ----
  })
  
  (define_insn "*movhi"
!   [(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,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" "")
***************
*** 2014,2019 ****
--- 2231,2247 ----
  ;; 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")
***************
*** 2158,2166 ****
  ;
  
  (define_expand "movmem<mode>"
!   [(set (match_operand:BLK 0 "memory_operand" "")
!         (match_operand:BLK 1 "memory_operand" ""))
!    (use (match_operand:GPR 2 "general_operand" ""))
     (match_operand 3 "" "")]
    ""
    "s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;")
--- 2386,2394 ----
  ;
  
  (define_expand "movmem<mode>"
!   [(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;")
***************
*** 2179,2193 ****
    "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"))]
    "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
     && GET_MODE (operands[4]) == Pmode"
    "#"
!   [(set_attr "type" "cs")])
  
  (define_split
    [(set (match_operand:BLK 0 "memory_operand" "")
--- 2407,2422 ----
    "operands[3] = gen_rtx_SCRATCH (Pmode);")
  
  (define_insn "*movmem_short"
!   [(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 "cpu_facility" "*,*,z10,*")])
  
  (define_split
    [(set (match_operand:BLK 0 "memory_operand" "")
***************
*** 2220,2225 ****
--- 2449,2468 ----
          (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" ""))
+    (use (match_operand 2 "register_operand" ""))
+    (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
     (clobber (match_operand 3 "register_operand" ""))]
    "reload_completed && TARGET_CPU_ZARCH"
    [(set (match_dup 3) (label_ref (match_dup 4)))
***************
*** 2358,2373 ****
    "operands[2] = gen_rtx_SCRATCH (Pmode);")
  
  (define_insn "*clrmem_short"
!   [(set (match_operand:BLK 0 "memory_operand" "=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"))
     (clobber (reg:CC CC_REGNUM))]
    "(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
     && GET_MODE (operands[3]) == Pmode"
    "#"
!   [(set_attr "type" "cs")])
  
  (define_split
    [(set (match_operand:BLK 0 "memory_operand" "")
--- 2601,2617 ----
    "operands[2] = gen_rtx_SCRATCH (Pmode);")
  
  (define_insn "*clrmem_short"
!   [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
          (const_int 0))
!    (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 "cpu_facility" "*,*,z10,*")])
  
  (define_split
    [(set (match_operand:BLK 0 "memory_operand" "")
***************
*** 2404,2409 ****
--- 2648,2669 ----
          (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))
+    (use (match_operand 1 "register_operand" ""))
+    (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
     (clobber (match_operand 2 "register_operand" ""))
     (clobber (reg:CC CC_REGNUM))]
    "reload_completed && TARGET_CPU_ZARCH"
***************
*** 2499,2513 ****
  
  (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"))]
    "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
     && GET_MODE (operands[4]) == Pmode"
    "#"
!   [(set_attr "type" "cs")])
  
  (define_split
    [(set (reg:CCU CC_REGNUM)
--- 2759,2774 ----
  
  (define_insn "*cmpmem_short"
    [(set (reg:CCU CC_REGNUM)
!         (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 "cpu_facility" "*,*,z10,*")])
  
  (define_split
    [(set (reg:CCU CC_REGNUM)
***************
*** 2543,2548 ****
--- 2804,2824 ----
                       (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" "")
+                      (match_operand:BLK 1 "memory_operand" "")))
+    (use (match_operand 2 "register_operand" ""))
+    (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
     (clobber (match_operand 3 "register_operand" ""))]
    "reload_completed && TARGET_CPU_ZARCH"
    [(set (match_dup 3) (label_ref (match_dup 4)))
***************
*** 2776,2781 ****
--- 3052,3134 ----
    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")
***************
*** 2871,2883 ****
  })
  
  (define_insn "*extendsidi2"
!   [(set (match_operand:DI 0 "register_operand" "=d,d")
!         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT")))]
    "TARGET_64BIT"
    "@
     lgfr\t%0,%1
!    lgf\t%0,%1"
!   [(set_attr "op_type" "RRE,RXY")])
  
  ;
  ; extend(hi|qi)(si|di)2 instruction pattern(s).
--- 3224,3239 ----
  })
  
  (define_insn "*extendsidi2"
!   [(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
!    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).
***************
*** 2912,2924 ****
  ;
  
  (define_insn "*extendhidi2_extimm"
!   [(set (match_operand:DI 0 "register_operand" "=d,d")
!         (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,RT")))]
    "TARGET_64BIT && TARGET_EXTIMM"
    "@
     lghr\t%0,%1
!    lgh\t%0,%1"
!   [(set_attr "op_type" "RRE,RXY")])
  
  (define_insn "*extendhidi2"
    [(set (match_operand:DI 0 "register_operand" "=d")
--- 3268,3283 ----
  ;
  
  (define_insn "*extendhidi2_extimm"
!   [(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
!    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")
***************
*** 2932,2945 ****
  ;
  
  (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")))]
    "TARGET_EXTIMM"
    "@
     lhr\t%0,%1
     lh\t%0,%1
!    lhy\t%0,%1"
!   [(set_attr "op_type" "RRE,RX,RXY")])
  
  (define_insn "*extendhisi2"
    [(set (match_operand:SI 0 "register_operand" "=d,d")
--- 3291,3307 ----
  ;
  
  (define_insn "*extendhisi2_extimm"
!   [(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
!    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")
***************
*** 3011,3023 ****
  })
  
  (define_insn "*zero_extendsidi2"
!   [(set (match_operand:DI 0 "register_operand" "=d,d")
!         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT")))]
    "TARGET_64BIT"
    "@
     llgfr\t%0,%1
!    llgf\t%0,%1"
!   [(set_attr "op_type" "RRE,RXY")])
  
  ;
  ; LLGT-type instructions (zero-extend from 31 bit to 64 bit).
--- 3373,3388 ----
  })
  
  (define_insn "*zero_extendsidi2"
!   [(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
!    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).
***************
*** 3116,3121 ****
--- 3481,3499 ----
      }
  })
  
+ ; 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")
***************
*** 3628,3634 ****
  
  (define_expand "adddi3"
    [(parallel
!     [(set (match_operand:DI 0 "register_operand" "")
            (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
                     (match_operand:DI 2 "general_operand" "")))
       (clobber (reg:CC CC_REGNUM))])]
--- 4006,4012 ----
  
  (define_expand "adddi3"
    [(parallel
!     [(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))])]
***************
*** 3683,3689 ****
    [(set_attr "op_type"  "RRE,RXY")])
  
  (define_insn_and_split "*adddi3_31z"
!   [(set (match_operand:DI 0 "register_operand" "=&d")
          (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
                   (match_operand:DI 2 "general_operand" "do") ) )
     (clobber (reg:CC CC_REGNUM))]
--- 4061,4067 ----
    [(set_attr "op_type"  "RRE,RXY")])
  
  (define_insn_and_split "*adddi3_31z"
!   [(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))]
***************
*** 3708,3714 ****
     operands[8] = operand_subword (operands[2], 1, 0, DImode);")
  
  (define_insn_and_split "*adddi3_31"
!   [(set (match_operand:DI 0 "register_operand" "=&d")
          (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
                   (match_operand:DI 2 "general_operand" "do") ) )
     (clobber (reg:CC CC_REGNUM))]
--- 4086,4092 ----
     operands[8] = operand_subword (operands[2], 1, 0, DImode);")
  
  (define_insn_and_split "*adddi3_31"
!   [(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))]
***************
*** 3745,3751 ****
  
  (define_expand "addsi3"
    [(parallel
!     [(set (match_operand:SI 0 "register_operand" "")
            (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
                     (match_operand:SI 2 "general_operand" "")))
       (clobber (reg:CC CC_REGNUM))])]
--- 4123,4129 ----
  
  (define_expand "addsi3"
    [(parallel
!     [(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))])]
***************
*** 3767,3777 ****
  ; add(di|si)3 instruction pattern(s).
  ;
  
! ; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag
  (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") ) )
     (clobber (reg:CC CC_REGNUM))]
    ""
    "@
--- 4145,4155 ----
  ; add(di|si)3 instruction pattern(s).
  ;
  
! ; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag, asi, agsi
  (define_insn "*add<mode>3"
!   [(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))]
    ""
    "@
***************
*** 3780,3795 ****
     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")])
  
! ; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
  (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"))
                   (match_dup 1)))
!    (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
          (plus:GPR (match_dup 1) (match_dup 2)))]
    "s390_match_ccmode (insn, CCL1mode)"
    "@
--- 4158,4175 ----
     al<g>fi\t%0,%2
     sl<g>fi\t%0,%n2
     a<g>\t%0,%2
!    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, 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,0")
! 			   (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
                   (match_dup 1)))
!    (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)"
    "@
***************
*** 3797,3804 ****
     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")])
  
  ; alr, al, aly, algr, alg
  (define_insn "*add<mode>3_carry1_cconly"
--- 4177,4186 ----
     al<g>fi\t%0,%2
     sl<g>fi\t%0,%n2
     al<g>\t%0,%2
!    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"
***************
*** 3814,3826 ****
     al<y>\t%0,%2"
    [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
  
! ; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
  (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"))
                   (match_dup 2)))
!    (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
          (plus:GPR (match_dup 1) (match_dup 2)))]
    "s390_match_ccmode (insn, CCL1mode)"
    "@
--- 4196,4208 ----
     al<y>\t%0,%2"
    [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
  
! ; 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,0")
! 			   (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
                   (match_dup 2)))
!    (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)"
    "@
***************
*** 3828,3835 ****
     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")])
  
  ; alr, al, aly, algr, alg
  (define_insn "*add<mode>3_carry2_cconly"
--- 4210,4219 ----
     al<g>fi\t%0,%2
     sl<g>fi\t%0,%n2
     al<g>\t%0,%2
!    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"
***************
*** 3845,3857 ****
     al<y>\t%0,%2"
    [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
  
! ; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
  (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"))
                   (const_int 0)))
!    (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
          (plus:GPR (match_dup 1) (match_dup 2)))]
    "s390_match_ccmode (insn, CCLmode)"
    "@
--- 4229,4241 ----
     al<y>\t%0,%2"
    [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
  
! ; 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,0")
! 			   (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
                   (const_int 0)))
!    (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)"
    "@
***************
*** 3859,3866 ****
     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")])
  
  ; alr, al, aly, algr, alg
  (define_insn "*add<mode>3_cconly"
--- 4243,4252 ----
     al<g>fi\t%0,%2
     sl<g>fi\t%0,%n2
     al<g>\t%0,%2
!    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"
***************
*** 3889,3910 ****
     al<y>\t%0,%2"
    [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
  
! ; ahi, afi, aghi, agfi
  (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"))
                   (const_int 0)))
!    (set (match_operand:GPR 0 "register_operand" "=d,d")
          (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\"))
     && 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")])
  
  ;
  ; add(tf|df|sf|td|dd)3 instruction pattern(s).
--- 4275,4299 ----
     al<y>\t%0,%2"
    [(set_attr "op_type"  "RR<E>,RX<Y>,RXY")])
  
! ; 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,0")
! 			   (match_operand:GPR 2 "const_int_operand" "K,Os,C"))
                   (const_int 0)))
!    (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]), '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
!    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).
***************
*** 4503,4571 ****
  
  (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"))
                   (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")])
  
  (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")))]
    "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")])
  
  ;
  ; 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")))]
    ""
!   "mh\t%0,%2"
!   [(set_attr "op_type"  "RX")
!    (set_attr "type"     "imulhi")])
  
  (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")))]
    ""
    "@
     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")])
  
  ;
  ; mulsidi3 instruction pattern(s).
  ;
  
  (define_insn "mulsidi3"
!   [(set (match_operand:DI 0 "register_operand" "=d,d")
          (mult:DI (sign_extend:DI
! 	           (match_operand:SI 1 "register_operand" "%0,0"))
                   (sign_extend:DI
! 	           (match_operand:SI 2 "nonimmediate_operand" "d,R"))))]
    "!TARGET_64BIT"
    "@
     mr\t%0,%2
!    m\t%0,%2"
!   [(set_attr "op_type"  "RR,RX")
!    (set_attr "type"     "imulsi")])
  
  ;
  ; umulsidi3 instruction pattern(s).
--- 4892,4969 ----
  
  (define_insn "*muldi3_sign"
    [(set (match_operand:DI 0 "register_operand" "=d,d")
!         (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")])
  
  (define_insn "muldi3"
!   [(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
!    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,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
!    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,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
!    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,d")
          (mult:DI (sign_extend:DI
! 	           (match_operand:SI 1 "register_operand" "%0,0,0"))
                   (sign_extend:DI
! 	           (match_operand:SI 2 "nonimmediate_operand" "d,R,T"))))]
    "!TARGET_64BIT"
    "@
     mr\t%0,%2
!    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).
***************
*** 6762,6767 ****
--- 7160,7191 ----
    [(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.
  ;;
***************
*** 7908,7910 ****
--- 8332,8361 ----
    ""
    ""
    [(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")])
Index: gcc/config/s390/predicates.md
===================================================================
*** gcc/config/s390/predicates.md.orig	2008-05-15 10:27:36.000000000 +0200
--- gcc/config/s390/predicates.md	2008-05-27 08:50:08.000000000 +0200
***************
*** 1,5 ****
  ;; Predicate definitions for S/390 and zSeries.
! ;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
  ;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
  ;;                Ulrich Weigand (uweigand@de.ibm.com).
  ;;
--- 1,5 ----
  ;; Predicate definitions for S/390 and zSeries.
! ;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
  ;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
  ;;                Ulrich Weigand (uweigand@de.ibm.com).
  ;;
***************
*** 110,116 ****
    if (GET_CODE (op) == LABEL_REF)
      return true;
    if (GET_CODE (op) == SYMBOL_REF)
!     return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
  	    && SYMBOL_REF_TLS_MODEL (op) == 0
  	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
  
--- 110,116 ----
    if (GET_CODE (op) == LABEL_REF)
      return true;
    if (GET_CODE (op) == SYMBOL_REF)
!     return (!SYMBOL_REF_ALIGN1_P (op)
  	    && SYMBOL_REF_TLS_MODEL (op) == 0
  	    && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
  
***************
*** 172,177 ****
--- 172,189 ----
    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: gcc/config/s390/s390-protos.h
===================================================================
*** gcc/config/s390/s390-protos.h.orig	2008-05-15 10:27:36.000000000 +0200
--- gcc/config/s390/s390-protos.h	2008-05-27 08:50:08.000000000 +0200
***************
*** 1,5 ****
  /* Definitions of target machine for GNU compiler, for IBM S/390.
!    Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
     Contributed by Hartmut Penner (hpenner@de.ibm.com)
  
  This file is part of GCC.
--- 1,7 ----
  /* Definitions of target machine for GNU compiler, for IBM S/390.
!    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.
*************** extern int s390_mem_constraint (const ch
*** 27,33 ****
  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);
! 
  
  
  /* Declare functions in s390.c.  */
--- 29,35 ----
  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.  */
*************** extern int s390_const_ok_for_constraint_
*** 51,56 ****
--- 53,59 ----
  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);
*************** extern enum reg_class s390_secondary_inp
*** 80,85 ****
--- 83,90 ----
  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);
*************** extern void s390_emit_tpf_eh_return (rtx
*** 113,118 ****
--- 118,124 ----
  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: gcc/config/s390/s390.h
===================================================================
*** gcc/config/s390/s390.h.orig	2008-05-27 08:49:56.000000000 +0200
--- gcc/config/s390/s390.h	2008-05-27 08:50:08.000000000 +0200
***************
*** 1,8 ****
  /* 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.
     Contributed by Hartmut Penner (hpenner@de.ibm.com) and
                    Ulrich Weigand (uweigand@de.ibm.com).
  
  This file is part of GCC.
  
--- 1,9 ----
  /* Definitions of target machine for GNU compiler, for IBM S/390
     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).
+                   Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
  
  This file is part of GCC.
  
*************** extern enum processor_flags s390_tune_fl
*** 62,67 ****
--- 63,72 ----
  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 \
*************** extern enum processor_flags s390_arch_fl
*** 75,80 ****
--- 80,89 ----
  #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 \
*************** extern const enum reg_class regclass_map
*** 491,501 ****
  #define PREFERRED_RELOAD_CLASS(X, CLASS)	\
    s390_preferred_reload_class ((X), (CLASS))
  
! /* We need secondary memory to move data between GPRs and FPRs.  */
  #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
   ((CLASS1) != (CLASS2)                                \
    && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS)     \
!   && (!TARGET_DFP || 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.  */
--- 500,513 ----
  #define PREFERRED_RELOAD_CLASS(X, CLASS)	\
    s390_preferred_reload_class ((X), (CLASS))
  
! /* 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 || !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.  */
*************** CUMULATIVE_ARGS;
*** 693,698 ****
--- 705,717 ----
  /* 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)
  
*************** do {									\
*** 959,965 ****
  #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)
  
  /* Check whether integer displacement is in range.  */
  #define DISP_IN_RANGE(d) \
--- 978,989 ----
  #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_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) \



More information about the Gcc-patches mailing list