---
 gcc/common/config/s390/s390-common.c |    4 
 gcc/config.gcc                       |    2 
 gcc/config/s390/2827.md              |  606 +++++++++++++++++++++++++++++++++++
 gcc/config/s390/s390-opts.h          |    1 
 gcc/config/s390/s390.c               |  284 ++++++++++++++!!
 gcc/config/s390/s390.h               |    7 
 gcc/config/s390/s390.md              |   91 +++!!
 gcc/config/s390/s390.opt             |    3 
 8 files changed, 922 insertions(+), 76 modifications(!)

Index: gcc/config/s390/s390.h
===================================================================
*** gcc/config/s390/s390.h.orig
--- gcc/config/s390/s390.h
*************** enum processor_flags
*** 34,40 ****
    PF_EXTIMM = 8,
    PF_DFP = 16,
    PF_Z10 = 32,
!   PF_Z196 = 64
  };
  
  /* This is necessary to avoid a warning about comparing different enum
--- 34,41 ----
    PF_EXTIMM = 8,
    PF_DFP = 16,
    PF_Z10 = 32,
!   PF_Z196 = 64,
!   PF_ZEC12 = 128
  };
  
  /* This is necessary to avoid a warning about comparing different enum
*************** enum processor_flags
*** 59,64 ****
--- 60,67 ----
   	(s390_arch_flags & PF_Z10)
  #define TARGET_CPU_Z196 \
   	(s390_arch_flags & PF_Z196)
+ #define TARGET_CPU_ZEC12 \
+  	(s390_arch_flags & PF_ZEC12)
  
  /* These flags indicate that the generated code should run on a cpu
     providing the respective hardware facility when run in
*************** enum processor_flags
*** 74,79 ****
--- 77,84 ----
         (TARGET_ZARCH && TARGET_CPU_Z10)
  #define TARGET_Z196 \
         (TARGET_ZARCH && TARGET_CPU_Z196)
+ #define TARGET_ZEC12 \
+        (TARGET_ZARCH && TARGET_CPU_ZEC12)
  
  
  #define TARGET_AVOID_CMP_AND_BRANCH (s390_tune == PROCESSOR_2817_Z196)
Index: gcc/config/s390/s390.md
===================================================================
*** gcc/config/s390/s390.md.orig
--- gcc/config/s390/s390.md
***************
*** 259,264 ****
--- 259,266 ----
                           z196_cracked"
               (const_string "none"))
  
+ (define_attr "mnemonic" "unknown" (const_string "unknown"))
+ 
  ;; Length in bytes.
  
  (define_attr "length" ""
***************
*** 272,281 ****
  ;; distinguish between g5 and g6, but there are differences between the two
  ;; CPUs could in theory be modeled.
  
! (define_attr "cpu" "g5,g6,z900,z990,z9_109,z9_ec,z10,z196"
    (const (symbol_ref "s390_tune_attr")))
  
! (define_attr "cpu_facility" "standard,ieee,zarch,longdisp,extimm,dfp,z10,z196"
    (const_string "standard"))
  
  (define_attr "enabled" ""
--- 274,283 ----
  ;; distinguish between g5 and g6, but there are differences between the two
  ;; CPUs could in theory be modeled.
  
! (define_attr "cpu" "g5,g6,z900,z990,z9_109,z9_ec,z10,z196,zEC12"
    (const (symbol_ref "s390_tune_attr")))
  
! (define_attr "cpu_facility" "standard,ieee,zarch,longdisp,extimm,dfp,z10,z196,zEC12"
    (const_string "standard"))
  
  (define_attr "enabled" ""
***************
*** 308,313 ****
--- 310,319 ----
  
           (and (eq_attr "cpu_facility" "z196")
                (match_test "TARGET_Z196"))
+ 	 (const_int 1)
+ 
+          (and (eq_attr "cpu_facility" "zEC12")
+               (match_test "TARGET_ZEC12"))
  	 (const_int 1)]
  	(const_int 0)))
  
***************
*** 324,329 ****
--- 330,338 ----
  ;; Pipeline description for z196
  (include "2817.md")
  
+ ;; Pipeline description for zEC12
+ (include "2827.md")
+ 
  ;; Predicates
  (include "predicates.md")
  
***************
*** 3348,3353 ****
--- 3357,3384 ----
    FAIL;
  })
  
+ (define_insn "*insv<mode>_zEC12"
+   [(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"))]
+   "TARGET_ZEC12
+    && (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 "risbgn\t%0,%3,%b2,%b1,%b4";
+ }
+   [(set_attr "op_type" "RIE")])
+ 
  (define_insn "*insv<mode>_z10"
    [(set (zero_extract:GPR (match_operand:GPR 0 "nonimmediate_operand" "+d")
  			  (match_operand 1 "const_int_operand"    "I")
***************
*** 3374,3379 ****
--- 3405,3438 ----
  
  ; 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>_zEC12_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"))))]
+   "TARGET_ZEC12
+    && 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 "risbgn\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
+ ; 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")
***************
*** 7882,7900 ****
     (set_attr "type"    "branch")
     (set_attr "z10prop" "z10_super_c,z10_super")])
  
! ; 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")
!    (set_attr "z10prop" "z10_super_c,z10_super")])
  
  ;;
  ;;- Loop instructions.
--- 7941,7973 ----
     (set_attr "type"    "branch")
     (set_attr "z10prop" "z10_super_c,z10_super")])
  
! ; clrt, clgrt, clfit, clgit, clt, clgt
  (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, d")
! 		(match_operand:GPR 2 "general_operand"  "d,D,RT")])
  	    (const_int 0))]
    "TARGET_Z10"
    "@
     cl<g>rt%C0\t%1,%2
!    cl<gf>it%C0\t%1,%x2
!    cl<g>t%C0\t%1,%2"
!   [(set_attr "op_type"      "RRF,RIE,RSY")
!    (set_attr "type"         "branch")
!    (set_attr "z10prop"      "z10_super_c,z10_super,*")
!    (set_attr "cpu_facility" "z10,z10,zEC12")])
! 
! ; lat, lgat
! (define_insn "*load_and_trap<mode>"
!   [(trap_if (eq (match_operand:GPR 0 "memory_operand"  "RT")
! 		(const_int 0))
! 	    (const_int 0))
!    (set (match_operand:GPR 1 "register_operand" "=d")
! 	(match_dup 0))]
!   "TARGET_ZEC12"
!   "l<g>at\t%1,%0"
!   [(set_attr "op_type" "RXY")])
! 
  
  ;;
  ;;- Loop instructions.
Index: gcc/config/s390/2827.md
===================================================================
*** /dev/null
--- gcc/config/s390/2827.md
***************
*** 0 ****
--- 1,606 ----
+ ;; Scheduling description for zEC12 (cpu 2827).
+ ;;   Copyright (C) 2012
+ ;;   Free Software Foundation, Inc.
+ ;;   Contributed by Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
+ 
+ ;; This file is part of GCC.
+ 
+ ;; GCC is free software; you can redistribute it and/or modify it under
+ ;; the terms of the GNU General Public License as published by the Free
+ ;; Software Foundation; either version 3, or (at your option) any later
+ ;; version.
+ 
+ ;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ ;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ ;; for more details.
+ 
+ ;; You should have received a copy of the GNU General Public License
+ ;; along with GCC; see the file COPYING3.  If not see
+ ;; <http://www.gnu.org/licenses/>.
+ 
+ 
+ (define_attr "ooo_cracked" ""
+   (cond [(eq_attr "mnemonic" "cgdbr,clfxtr,cdgtr,celfbr,cxgtr,clfebr,clc,lngfr,cs,cfxbr,xc,clfdbr,basr,ex,cxlgtr,clfdtr,srdl,lpgfr,cdlgbr,cgxtr,cxlftr,nc,cxftr,cdfbr,clfxbr,cdftr,clgxbr,cgdtr,cxlgbr,mvc,clgdtr,cegbr,cfebr,cdlftr,sldl,cdlgtr,csg,chhsi,clgebr,cxgbr,cxfbr,cdlfbr,cgebr,lzxr,oc,cdgbr,brasl,cgxbr,cxlfbr,clgxtr,exrl,cfdbr,celgbr,clgdbr,lxr,cpsdr,lcgfr,bras,srda,cefbr") (const_int 1)]
+         (const_int 0)))
+ 
+ (define_attr "ooo_expanded" ""
+   (cond [(eq_attr "mnemonic" "dlr,dsgr,d,dsgf,stam,dsgfr,dlgr,dsg,cds,dr,stm,mvc,dl,cdsg,stmy,dlg,stmg,lam") (const_int 1)]
+         (const_int 0)))
+ 
+ (define_attr "ooo_endgroup" ""
+   (cond [(eq_attr "mnemonic" "ipm") (const_int 1)]
+         (const_int 0)))
+ 
+ (define_attr "ooo_groupalone" ""
+   (cond [(eq_attr "mnemonic" "lnxbr,madb,ltxtr,clc,axtr,msebr,slbgr,xc,alcr,lpxbr,slbr,maebr,mlg,mfy,lxdtr,maeb,lxeb,nc,mxtr,sxtr,dxbr,alc,msdbr,ltxbr,lxdb,madbr,lxdbr,lxebr,mvc,m,mseb,mlr,mlgr,slb,tcxb,msdb,sqxbr,alcgr,oc,flogr,alcg,mxbr,dxtr,axbr,mr,sxbr,slbg,ml,lcxbr") (const_int 1)]
+         (const_int 0)))
+ 
+ (define_insn_reservation "zEC12_simple" 1
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ltg,ogrk,lr,lnebr,lghrl,sdbr,x,asi,lhr,sebr,madb,ar,lhrl,clfxtr,llgfr,clghrl,cgr,cli,agrk,ic,adbr,aebr,lrv,clg,cy,cghi,sy,celfbr,seb,clgfr,al,tm,lang,clfebr,lghr,cdb,lpebr,laa,ark,lh,or,icy,xi,msebr,n,llihl,afi,cs,nrk,sth,lgr,l,lcr,stey,xg,crt,slgfr,ny,ld,j,llihh,slgr,clfhsi,slg,lb,lgrl,lrl,llihf,lndbr,llcr,laxg,mvghi,rllg,sdb,xrk,laag,alhsik,algfi,algr,aly,agfi,lrvr,d,crl,llgc,tmhl,algsi,lgh,icmh,clhrl,xgrk,icm,iilf,ork,lbr,cg,ldgr,lgf,iihf,llghr,sg,clfdbr,llgtr,stam,cebr,tmhh,tceb,slgf,basr,lgbr,maebr,lgb,cgfi,aeb,ltebr,lax,clfit,lrvgr,nihl,ni,clfdtr,srdl,mdb,srk,xihf,stgrl,sthrl,algf,ltr,cdlgbr,cgit,ng,lat,llghrl,ltgr,nihh,clgfrl,srlk,maeb,agr,cxlftr,ler,bcr,stcy,cds,clfi,nihf,ly,clt,lgat,alg,lhy,lgfrl,clghsi,clrt,tmll,srlg,tcdb,ay,sty,clr,lgfi,lan,lpdbr,clgt,adb,ahik,sra,algrk,cdfbr,lcebr,clfxbr,msdbr,ceb,clgr,tmy,tmlh,alghsik,lcgr,mvi,cdbr,ltgf,xr,larl,ldr,llgcr,clgrt,clrl,cghsi,cliy,madbr,oy,ogr,llgt,meebr,slr,clgxbr,chi,s,icmy,llc,ngr,clhhsi,ltgfr,llill,lhi,o,meeb,clgdtr,sll,clgrl,clgf,ledbr,cegbr,mviy,algfr,rll,cdlftr,sldl,cdlgtr,lg,niy,st,sgr,ag,le,xgr,cr,stg,llilh,sr,lzer,cdsg,sllk,mdbr,stoc,csg,clgit,chhsi,strl,llilf,lndfr,ngrk,clgebr,clgfi,llgh,mseb,ltdbr,oill,la,llhrl,stc,lghi,oihl,xiy,sllg,llgf,cgrt,ldeb,cl,sl,cdlfbr,oi,oilh,nr,srak,oihh,ear,slgrk,og,c,slgfi,sthy,oilf,oiy,msdb,oihf,a,cfi,lzxr,lzdr,srag,cdgbr,brasl,alr,cgrl,llgfrl,cit,clgxtr,ley,exrl,lcdfr,lay,xilf,lcdbr,alsi,mvhhi,srl,chsi,lgfr,lrvg,cly,sgrk,ahi,celgbr,nill,clgdbr,jg,slrk,lxr,sar,slfi,cpsdr,lcgfr,aghik,nilh,mvhi,lpdfr,xy,alrk,lao,agsi,ldy,nilf,llhr,alfi,laog,sly,aghi,ldebr,bras,srda,cefbr,lt")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgdbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgdbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_clm" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "clm")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lnxbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lnxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lngr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lngr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cdgtr" 45
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cdgtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ddtr" 37
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ddtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mhy" 5
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mhy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dlr" 25
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dlr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ltxtr" 18
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ltxtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxgtr" 32
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxgtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lgdr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lgdr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_clc" 5
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "clc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dsgr" 25
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dsgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_axtr" 27
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "axtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lngfr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lngfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cghrl" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cghrl")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ah" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ah")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgh" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgh")) "nothing")
+ 
+ (define_insn_reservation "zEC12_locg" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "locg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msgfi" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msgfi")) "nothing")
+ 
+ (define_insn_reservation "zEC12_slbgr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "slbgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lpgr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lpgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_loc" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "loc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgf" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgf")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lmy" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lmy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_std" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "std")) "nothing")
+ 
+ (define_insn_reservation "zEC12_xc" 4
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "xc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msy" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sqebr" 29
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sqebr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_alcr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "alcr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msgr" 8
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mhi" 5
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mhi")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mdtr" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mdtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dsgf" 25
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dsgf")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lpxbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lpxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_stdy" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "stdy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_deb" 23
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "deb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ltdtr" 17
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ltdtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dsgfr" 25
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dsgfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_slbr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "slbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dlgr" 27
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dlgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dsg" 25
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dsg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mlg" 9
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mlg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ex" 16
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ex")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mfy" 7
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mfy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxlgtr" 4
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxlgtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lxdtr" 15
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lxdtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mghi" 5
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mghi")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lpgfr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lpgfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ledtr" 34
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ledtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ms" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ms")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ldetr" 17
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ldetr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_tdcxt" 12
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "tdcxt")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lpr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lpr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msgf" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msgf")) "nothing")
+ 
+ (define_insn_reservation "zEC12_chy" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "chy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgxtr" 30
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgxtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lmg" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lmg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_tdcet" 14
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "tdcet")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lxeb" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lxeb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msg" 8
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_nc" 4
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "nc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_locgr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "locgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_debr" 23
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "debr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_chrl" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "chrl")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mxtr" 37
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mxtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sgfr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sgfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxftr" 4
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxftr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sxtr" 27
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sxtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dxbr" 50
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_alc" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "alc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgfrl" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgfrl")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ltxbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ltxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dr" 16
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lxdb" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lxdb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_tdcdt" 11
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "tdcdt")) "nothing")
+ 
+ (define_insn_reservation "zEC12_clmy" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "clmy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_locr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "locr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_agf" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "agf")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lm" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lm")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msgfr" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msgfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lxdbr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lxdbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_stm" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "stm")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgdtr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgdtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lxebr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lxebr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxlgbr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxlgbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mvc" 4
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mvc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sqdbr" 43
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sqdbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dl" 25
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dl")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cfebr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cfebr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_agfr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "agfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lnr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lnr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_m" 7
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "m")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ipm" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ipm")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxbr" 18
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ddbr" 30
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ddbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_stmy" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "stmy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ste" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ste")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ahy" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ahy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mlr" 7
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mlr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sqeb" 29
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sqeb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dlg" 27
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dlg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxgbr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxgbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxfbr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxfbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mlgr" 9
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mlgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgfr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgfr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_slb" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "slb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sdtr" 12
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sdtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_tcxb" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "tcxb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgebr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgebr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ch" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ch")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sh" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sh")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sgf" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sgf")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msr" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sqxbr" 50
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sqxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_alcgr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "alcgr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_oc" 4
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "oc")) "nothing")
+ 
+ (define_insn_reservation "zEC12_adtr" 24
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "adtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cgxbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cgxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxlfbr" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxlfbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sqdb" 43
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sqdb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_flogr" 7
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "flogr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_popcnt" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "popcnt")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cfdbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cfdbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_alcg" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "alcg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mxbr" 41
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_dxtr" 45
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "dxtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_axbr" 12
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "axbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mr" 7
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_stmg" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "stmg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_sxbr" 12
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "sxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ddb" 30
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ddb")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cdtr" 11
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cdtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_cxtr" 14
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "cxtr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_slbg" 3
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "slbg")) "nothing")
+ 
+ (define_insn_reservation "zEC12_ml" 7
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "ml")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lam" 0
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lam")) "nothing")
+ 
+ (define_insn_reservation "zEC12_lcxbr" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "lcxbr")) "nothing")
+ 
+ (define_insn_reservation "zEC12_msfi" 6
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "msfi")) "nothing")
+ 
+ (define_insn_reservation "zEC12_shy" 2
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "shy")) "nothing")
+ 
+ (define_insn_reservation "zEC12_mh" 5
+   (and (eq_attr "cpu" "zEC12")
+        (eq_attr "mnemonic" "mh")) "nothing")
+ 
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** struct processor_costs z196_cost =
*** 254,259 ****
--- 254,291 ----
    COSTS_N_INSNS (160),   /* DSGR cracked */
  };
  
+ static const
+ struct processor_costs zEC12_cost =
+ {
+   COSTS_N_INSNS (7),     /* M     */
+   COSTS_N_INSNS (5),     /* MGHI  */
+   COSTS_N_INSNS (5),     /* MH    */
+   COSTS_N_INSNS (5),     /* MHI   */
+   COSTS_N_INSNS (7),     /* ML    */
+   COSTS_N_INSNS (7),     /* MR    */
+   COSTS_N_INSNS (6),     /* MS    */
+   COSTS_N_INSNS (8),     /* MSG   */
+   COSTS_N_INSNS (6),     /* MSGF  */
+   COSTS_N_INSNS (6),     /* MSGFR */
+   COSTS_N_INSNS (8),     /* MSGR  */
+   COSTS_N_INSNS (6),     /* MSR   */
+   COSTS_N_INSNS (1) ,    /* multiplication in DFmode */
+   COSTS_N_INSNS (40),    /* MXBR B+40 */
+   COSTS_N_INSNS (100),   /* SQXBR B+100 */
+   COSTS_N_INSNS (42),    /* SQDBR B+42 */
+   COSTS_N_INSNS (28),    /* SQEBR B+28 */
+   COSTS_N_INSNS (1),     /* MADBR B */
+   COSTS_N_INSNS (1),     /* MAEBR B */
+   COSTS_N_INSNS (131),   /* DXBR B+131 */
+   COSTS_N_INSNS (29),    /* DDBR */
+   COSTS_N_INSNS (22),    /* DEBR */
+   COSTS_N_INSNS (160),   /* DLGR cracked */
+   COSTS_N_INSNS (160),   /* DLR cracked */
+   COSTS_N_INSNS (160),   /* DR expanded */
+   COSTS_N_INSNS (160),   /* DSGFR cracked */
+   COSTS_N_INSNS (160),   /* DSGR cracked */
+ };
+ 
  extern int reload_completed;
  
  /* Kept up to date using the SCHED_VARIABLE_ISSUE hook.  */
*************** s390_option_override (void)
*** 1583,1588 ****
--- 1615,1623 ----
      case PROCESSOR_2817_Z196:
        s390_cost = &z196_cost;
        break;
+     case PROCESSOR_2827_ZEC12:
+       s390_cost = &zEC12_cost;
+       break;
      default:
        s390_cost = &z900_cost;
      }
*************** s390_option_override (void)
*** 1607,1613 ****
  #endif
  
    if (s390_tune == PROCESSOR_2097_Z10
!       || s390_tune == PROCESSOR_2817_Z196)
      {
        maybe_set_param_value (PARAM_MAX_UNROLLED_INSNS, 100,
  			     global_options.x_param_values,
--- 1642,1649 ----
  #endif
  
    if (s390_tune == PROCESSOR_2097_Z10
!       || s390_tune == PROCESSOR_2817_Z196
!       || s390_tune == PROCESSOR_2827_ZEC12)
      {
        maybe_set_param_value (PARAM_MAX_UNROLLED_INSNS, 100,
  			     global_options.x_param_values,
*************** static bool
*** 2860,2866 ****
  legitimate_reload_fp_constant_p (rtx op)
  {
    /* Accept floating-point zero operands if the load zero instruction
!      can be used.  */
    if (TARGET_Z196
        && GET_CODE (op) == CONST_DOUBLE
        && s390_float_const_zero_p (op))
--- 2896,2903 ----
  legitimate_reload_fp_constant_p (rtx op)
  {
    /* Accept floating-point zero operands if the load zero instruction
!      can be used.  Prior to z196 the load fp zero instruction caused a
!      performance penalty if the result is used as BFP number.  */
    if (TARGET_Z196
        && GET_CODE (op) == CONST_DOUBLE
        && s390_float_const_zero_p (op))
*************** preferred_la_operand_p (rtx op1, rtx op2
*** 3262,3268 ****
      return false;
  
    /* Avoid LA instructions with index register on z196; it is
!      preferable to use regular add instructions when possible.  */
    if (addr.indx && s390_tune == PROCESSOR_2817_Z196)
      return false;
  
--- 3299,3307 ----
      return false;
  
    /* Avoid LA instructions with index register on z196; it is
!      preferable to use regular add instructions when possible.
!      Starting with zEC12 the la with index register is "uncracked"
!      again.  */
    if (addr.indx && s390_tune == PROCESSOR_2817_Z196)
      return false;
  
*************** s390_expand_insv (rtx dest, rtx op1, rtx
*** 4530,4537 ****
        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;
      }
--- 4569,4581 ----
        op = gen_rtx_SET (GET_MODE(src),
  			gen_rtx_ZERO_EXTRACT (GET_MODE (dest), dest, op1, op2),
  			src);
! 
!       if (!TARGET_ZEC12)
! 	{
! 	  clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
! 	  op = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clobber));
! 	}
!       emit_insn (op);
  
        return true;
      }
*************** s390_adjust_priority (rtx insn ATTRIBUTE
*** 5561,5567 ****
    if (s390_tune != PROCESSOR_2084_Z990
        && s390_tune != PROCESSOR_2094_Z9_109
        && s390_tune != PROCESSOR_2097_Z10
!       && s390_tune != PROCESSOR_2817_Z196)
      return priority;
  
    switch (s390_safe_attr_type (insn))
--- 5605,5612 ----
    if (s390_tune != PROCESSOR_2084_Z990
        && s390_tune != PROCESSOR_2094_Z9_109
        && s390_tune != PROCESSOR_2097_Z10
!       && s390_tune != PROCESSOR_2817_Z196
!       && s390_tune != PROCESSOR_2827_ZEC12)
      return priority;
  
    switch (s390_safe_attr_type (insn))
*************** s390_issue_rate (void)
*** 5593,5598 ****
--- 5638,5644 ----
      case PROCESSOR_2817_Z196:
        return 3;
      case PROCESSOR_2097_Z10:
+     case PROCESSOR_2827_ZEC12:
        return 2;
      default:
        return 1;
*************** s390_reorg (void)
*** 10418,10424 ****
  
    /* Walk over the insns and do some >=z10 specific changes.  */
    if (s390_tune == PROCESSOR_2097_Z10
!       || s390_tune == PROCESSOR_2817_Z196)
      {
        rtx insn;
        bool insn_added_p = false;
--- 10464,10471 ----
  
    /* Walk over the insns and do some >=z10 specific changes.  */
    if (s390_tune == PROCESSOR_2097_Z10
!       || s390_tune == PROCESSOR_2817_Z196
!       || s390_tune == PROCESSOR_2827_ZEC12)
      {
        rtx insn;
        bool insn_added_p = false;
*************** s390_z10_prevent_earlyload_conflicts (rt
*** 10528,10559 ****
    ready[0] = tmp;
  }
  
  /* This function is called via hook TARGET_SCHED_REORDER before
     issueing one insn from list READY which contains *NREADYP entries.
     For target z10 it reorders load instructions to avoid early load
     conflicts in the floating point pipeline  */
  static int
! s390_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
  		    rtx *ready, int *nreadyp, int clock ATTRIBUTE_UNUSED)
  {
    if (s390_tune == PROCESSOR_2097_Z10)
      if (reload_completed && *nreadyp > 1)
        s390_z10_prevent_earlyload_conflicts (ready, nreadyp);
  
    return s390_issue_rate ();
  }
  
  /* This function is called via hook TARGET_SCHED_VARIABLE_ISSUE after
     the scheduler has issued INSN.  It stores the last issued insn into
     last_scheduled_insn in order to make it available for
     s390_sched_reorder.  */
  static int
! s390_sched_variable_issue (FILE *file ATTRIBUTE_UNUSED,
!                            int verbose ATTRIBUTE_UNUSED,
!                          rtx insn, int more)
  {
    last_scheduled_insn = insn;
  
    if (GET_CODE (PATTERN (insn)) != USE
        && GET_CODE (PATTERN (insn)) != CLOBBER)
      return more - 1;
--- 10575,10816 ----
    ready[0] = tmp;
  }
  
+ 
+ /* The s390_sched_state variable tracks the state of the current or
+    the last instruction group.
+ 
+    0,1,2 number of instructions scheduled in the current group
+    3     the last group is complete - normal insns
+    4     the last group was a cracked/expanded insn */
+ 
+ static int s390_sched_state;
+ 
+ #define S390_OOO_SCHED_STATE_NORMAL  3
+ #define S390_OOO_SCHED_STATE_CRACKED 4
+ 
+ #define S390_OOO_SCHED_ATTR_MASK_CRACKED    0x1
+ #define S390_OOO_SCHED_ATTR_MASK_EXPANDED   0x2
+ #define S390_OOO_SCHED_ATTR_MASK_ENDGROUP   0x4
+ #define S390_OOO_SCHED_ATTR_MASK_GROUPALONE 0x8
+ 
+ static unsigned int
+ s390_get_sched_attrmask (rtx insn)
+ {
+   unsigned int mask = 0;
+ 
+   if (get_attr_ooo_cracked (insn))
+     mask |= S390_OOO_SCHED_ATTR_MASK_CRACKED;
+   if (get_attr_ooo_expanded (insn))
+     mask |= S390_OOO_SCHED_ATTR_MASK_EXPANDED;
+   if (get_attr_ooo_endgroup (insn))
+     mask |= S390_OOO_SCHED_ATTR_MASK_ENDGROUP;
+   if (get_attr_ooo_groupalone (insn))
+     mask |= S390_OOO_SCHED_ATTR_MASK_GROUPALONE;
+   return mask;
+ }
+ 
+ /* Return the scheduling score for INSN.  The higher the score the
+    better.  The score is calculated from the OOO scheduling attributes
+    of INSN and the scheduling state s390_sched_state.  */
+ static int
+ s390_sched_score (rtx insn)
+ {
+   unsigned int mask = s390_get_sched_attrmask (insn);
+   int score = 0;
+ 
+   switch (s390_sched_state)
+     {
+     case 0:
+       /* Try to put insns into the first slot which would otherwise
+ 	 break a group.  */
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_CRACKED) != 0
+ 	  || (mask & S390_OOO_SCHED_ATTR_MASK_EXPANDED) != 0)
+ 	score += 5;
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_GROUPALONE) != 0)
+ 	score += 10;
+     case 1:
+       /* Prefer not cracked insns while trying to put together a
+ 	 group.  */
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_CRACKED) == 0
+ 	  && (mask & S390_OOO_SCHED_ATTR_MASK_EXPANDED) == 0
+ 	  && (mask & S390_OOO_SCHED_ATTR_MASK_GROUPALONE) == 0)
+ 	score += 10;
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_ENDGROUP) == 0)
+ 	score += 5;
+       break;
+     case 2:
+       /* Prefer not cracked insns while trying to put together a
+ 	 group.  */
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_CRACKED) == 0
+ 	  && (mask & S390_OOO_SCHED_ATTR_MASK_EXPANDED) == 0
+ 	  && (mask & S390_OOO_SCHED_ATTR_MASK_GROUPALONE) == 0)
+ 	score += 10;
+       /* Prefer endgroup insns in the last slot.  */
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_ENDGROUP) != 0)
+ 	score += 10;
+       break;
+     case S390_OOO_SCHED_STATE_NORMAL:
+       /* Prefer not cracked insns if the last was not cracked.  */
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_CRACKED) == 0
+ 	  && (mask & S390_OOO_SCHED_ATTR_MASK_EXPANDED) == 0)
+ 	score += 5;
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_GROUPALONE) != 0)
+ 	score += 10;
+       break;
+     case S390_OOO_SCHED_STATE_CRACKED:
+       /* Try to keep cracked insns together to prevent them from
+ 	 interrupting groups.  */
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_CRACKED) != 0
+ 	  || (mask & S390_OOO_SCHED_ATTR_MASK_EXPANDED) != 0)
+ 	score += 5;
+       break;
+     }
+   return score;
+ }
+ 
  /* This function is called via hook TARGET_SCHED_REORDER before
     issueing one insn from list READY which contains *NREADYP entries.
     For target z10 it reorders load instructions to avoid early load
     conflicts in the floating point pipeline  */
  static int
! s390_sched_reorder (FILE *file, int verbose,
  		    rtx *ready, int *nreadyp, int clock ATTRIBUTE_UNUSED)
  {
    if (s390_tune == PROCESSOR_2097_Z10)
      if (reload_completed && *nreadyp > 1)
        s390_z10_prevent_earlyload_conflicts (ready, nreadyp);
  
+   if (s390_tune == PROCESSOR_2827_ZEC12
+       && reload_completed
+       && *nreadyp > 1)
+     {
+       int i;
+       int last_index = *nreadyp - 1;
+       int max_index = -1;
+       int max_score = -1;
+       rtx tmp;
+ 
+       /* Just move the insn with the highest score to the top (the
+ 	 end) of the list.  A full sort is not needed since a conflict
+ 	 in the hazard recognition cannot happen.  So the top insn in
+ 	 the ready list will always be taken.  */
+       for (i = last_index; i >= 0; i--)
+ 	{
+ 	  int score;
+ 
+ 	  if (recog_memoized (ready[i]) < 0)
+ 	    continue;
+ 
+ 	  score = s390_sched_score (ready[i]);
+ 	  if (score > max_score)
+ 	    {
+ 	      max_score = score;
+ 	      max_index = i;
+ 	    }
+ 	}
+ 
+       if (max_index != -1)
+ 	{
+ 	  if (max_index != last_index)
+ 	    {
+ 	      tmp = ready[max_index];
+ 	      ready[max_index] = ready[last_index];
+ 	      ready[last_index] = tmp;
+ 
+ 	      if (verbose > 5)
+ 		fprintf (file,
+ 			 "move insn %d to the top of list\n",
+ 			 INSN_UID (ready[last_index]));
+ 	    }
+ 	  else if (verbose > 5)
+ 	    fprintf (file,
+ 		     "best insn %d already on top\n",
+ 		     INSN_UID (ready[last_index]));
+ 	}
+ 
+       if (verbose > 5)
+ 	{
+ 	  fprintf (file, "ready list ooo attributes - sched state: %d\n",
+ 		   s390_sched_state);
+ 
+ 	  for (i = last_index; i >= 0; i--)
+ 	    {
+ 	      if (recog_memoized (ready[i]) < 0)
+ 		continue;
+ 	      fprintf (file, "insn %d score: %d: ", INSN_UID (ready[i]),
+ 		       s390_sched_score (ready[i]));
+ #define PRINT_OOO_ATTR(ATTR) fprintf (file, "%s ", get_attr_##ATTR (ready[i]) ? #ATTR : "!" #ATTR);
+ 	      PRINT_OOO_ATTR (ooo_cracked);
+ 	      PRINT_OOO_ATTR (ooo_expanded);
+ 	      PRINT_OOO_ATTR (ooo_endgroup);
+ 	      PRINT_OOO_ATTR (ooo_groupalone);
+ #undef PRINT_OOO_ATTR
+ 	      fprintf (file, "\n");
+ 	    }
+ 	}
+     }
+ 
    return s390_issue_rate ();
  }
  
+ 
  /* This function is called via hook TARGET_SCHED_VARIABLE_ISSUE after
     the scheduler has issued INSN.  It stores the last issued insn into
     last_scheduled_insn in order to make it available for
     s390_sched_reorder.  */
  static int
! s390_sched_variable_issue (FILE *file, int verbose, rtx insn, int more)
  {
    last_scheduled_insn = insn;
  
+   if (s390_tune == PROCESSOR_2827_ZEC12
+       && reload_completed
+       && recog_memoized (insn) >= 0)
+     {
+       unsigned int mask = s390_get_sched_attrmask (insn);
+ 
+       if ((mask & S390_OOO_SCHED_ATTR_MASK_CRACKED) != 0
+ 	  || (mask & S390_OOO_SCHED_ATTR_MASK_EXPANDED) != 0)
+ 	s390_sched_state = S390_OOO_SCHED_STATE_CRACKED;
+       else if ((mask & S390_OOO_SCHED_ATTR_MASK_ENDGROUP) != 0
+ 	       || (mask & S390_OOO_SCHED_ATTR_MASK_GROUPALONE) != 0)
+ 	s390_sched_state = S390_OOO_SCHED_STATE_NORMAL;
+       else
+ 	{
+ 	  /* Only normal insns are left (mask == 0).  */
+ 	  switch (s390_sched_state)
+ 	    {
+ 	    case 0:
+ 	    case 1:
+ 	    case 2:
+ 	    case S390_OOO_SCHED_STATE_NORMAL:
+ 	      if (s390_sched_state == S390_OOO_SCHED_STATE_NORMAL)
+ 		s390_sched_state = 1;
+ 	      else
+ 		s390_sched_state++;
+ 
+ 	      break;
+ 	    case S390_OOO_SCHED_STATE_CRACKED:
+ 	      s390_sched_state = S390_OOO_SCHED_STATE_NORMAL;
+ 	      break;
+ 	    }
+ 	}
+       if (verbose > 5)
+ 	{
+ 	  fprintf (file, "insn %d: ", INSN_UID (insn));
+ #define PRINT_OOO_ATTR(ATTR)						\
+ 	  fprintf (file, "%s ", get_attr_##ATTR (insn) ? #ATTR : "");
+ 	  PRINT_OOO_ATTR (ooo_cracked);
+ 	  PRINT_OOO_ATTR (ooo_expanded);
+ 	  PRINT_OOO_ATTR (ooo_endgroup);
+ 	  PRINT_OOO_ATTR (ooo_groupalone);
+ #undef PRINT_OOO_ATTR
+ 	  fprintf (file, "\n");
+ 	  fprintf (file, "sched state: %d\n", s390_sched_state);
+ 	}
+     }
+ 
+ 
    if (GET_CODE (PATTERN (insn)) != USE
        && GET_CODE (PATTERN (insn)) != CLOBBER)
      return more - 1;
*************** s390_sched_init (FILE *file ATTRIBUTE_UN
*** 10567,10572 ****
--- 10824,10830 ----
  		 int max_ready ATTRIBUTE_UNUSED)
  {
    last_scheduled_insn = NULL_RTX;
+   s390_sched_state = 0;
  }
  
  /* This function checks the whole of insn X for memory references. The
*************** s390_loop_unroll_adjust (unsigned nunrol
*** 10597,10603 ****
    unsigned i;
    unsigned mem_count = 0;
  
!   if (s390_tune != PROCESSOR_2097_Z10 && s390_tune != PROCESSOR_2817_Z196)
      return nunroll;
  
    /* Count the number of memory references within the loop body.  */
--- 10855,10863 ----
    unsigned i;
    unsigned mem_count = 0;
  
!   if (s390_tune != PROCESSOR_2097_Z10
!       && s390_tune != PROCESSOR_2817_Z196
!       && s390_tune != PROCESSOR_2827_ZEC12)
      return nunroll;
  
    /* Count the number of memory references within the loop body.  */
Index: gcc/config/s390/s390.opt
===================================================================
*** gcc/config/s390/s390.opt.orig
--- gcc/config/s390/s390.opt
*************** Enum(processor_type) String(z10) Value(P
*** 73,78 ****
--- 73,81 ----
  EnumValue
  Enum(processor_type) String(z196) Value(PROCESSOR_2817_Z196)
  
+ EnumValue
+ Enum(processor_type) String(zEC12) Value(PROCESSOR_2827_ZEC12)
+ 
  mbackchain
  Target Report Mask(BACKCHAIN)
  Maintain backchain pointer
Index: gcc/config.gcc
===================================================================
*** gcc/config.gcc.orig
--- gcc/config.gcc
*************** case "${target}" in
*** 3409,3415 ****
  		for which in arch tune; do
  			eval "val=\$with_$which"
  			case ${val} in
! 			"" | g5 | g6 | z900 | z990 | z9-109 | z9-ec | z10 | z196)
  				# OK
  				;;
  			*)
--- 3409,3415 ----
  		for which in arch tune; do
  			eval "val=\$with_$which"
  			case ${val} in
! 			"" | g5 | g6 | z900 | z990 | z9-109 | z9-ec | z10 | z196 | zEC12)
  				# OK
  				;;
  			*)
Index: gcc/config/s390/s390-opts.h
===================================================================
*** gcc/config/s390/s390-opts.h.orig
--- gcc/config/s390/s390-opts.h
*************** enum processor_type
*** 35,40 ****
--- 35,41 ----
    PROCESSOR_2094_Z9_EC,
    PROCESSOR_2097_Z10,
    PROCESSOR_2817_Z196,
+   PROCESSOR_2827_ZEC12,
    PROCESSOR_max
  };
  
Index: gcc/common/config/s390/s390-common.c
===================================================================
*** gcc/common/config/s390/s390-common.c.orig
--- gcc/common/config/s390/s390-common.c
*************** EXPORTED_CONST int processor_flags_table
*** 41,47 ****
      /* z10 */    PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
                   | PF_EXTIMM | PF_DFP | PF_Z10,
      /* z196 */   PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
!                  | PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196
    };
  
  /* Change optimizations to be performed, depending on the
--- 41,49 ----
      /* z10 */    PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
                   | PF_EXTIMM | PF_DFP | PF_Z10,
      /* z196 */   PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
!                  | PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196,
!     /* zEC12 */  PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
!                  | PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196 | PF_ZEC12
    };
  
  /* Change optimizations to be performed, depending on the
