OSDN Git Service

* s390-modes.def [CCL1, CCL2, CCT1, CCT2, CCT3, CCUR, CCSR]: Declare
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Aug 2002 16:02:52 +0000 (16:02 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Aug 2002 16:02:52 +0000 (16:02 +0000)
new condition code modes.
s390.c (s390_match_ccmode_set): Handle those new CC modes.
(s390_select_ccmode): Likewise.
(s390_branch_condition_mask): Likewise.

* s390-protos.h (s390_tm_ccmode): Declare.
s390.c (s390_tm_ccmode): New function.
(s390_match_ccmode): Allow VOIDmode as REQ_MODE.

* s390.md ("*cmpdi_tm2"): Rename to "*tmdi_ext".
("*cmpsi_tm2"): Rename to "*tmsi_ext".
("*cmpqi_tm2"): Rename to "*tmqi_ext".

("*cmpdi_tm_reg", "*cmpdi_tm_mem", "*cmpsi_tm_reg", "*cmpsi_tm_mem",
"*cmphi_tm_sub","*cmphi_cct_0",  "*cmpqi_tm", "*cmpqi_tm_sub",
"*cmpqi_cct_0", "*tm_0"): Remove, replace by ...
("*tmdi_reg", "*tmsi_reg", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem",
"*tmqi_mem", "*tmhi_full", "*tmqi_full"): ... these new patterns.

("*ltgr", "*cmpdi_ccs_0_64", "*cmpdi_ccs_0_31", "*ltr", "*icm15",
"*icm15_cconly", "*cmpsi_ccs_0", "*icm3", "*cmphi_ccs_0", "*icm1",
"*cmpqi_ccs_0"): Remove, replace by ...
("*tstdi_sign", "*tstdi", "*tstdi_cconly", "*tstdi_cconly_31",
"*tstsi", "*tstsi_cconly", "*tstsi_cconly2", "*tsthi", "*tsthi_cconly",
"*tstqi", "*tstqi_cconly"): ... these new patterns.

("*cmpsidi_ccs"): Remove, replace by ...
("*cmpsi_ccs_sign"): ... this new pattern.
("*cmpdi_ccs_sign", "*cmpdi_ccu_zero"): New patterns.

("*cmpqi_ccu_0", "*cmpqi_ccu_immed"): Remove, replace by ...
("*cli"): ... this new pattern.

("*adddi3_sign", "*adddi3_zero_cc", "*adddi3_zero_cconly",
"*adddi3_zero", "*adddi3_cc", "*adddi3_cconly", "*adddi3_cconly2"):
New patterns.
("adddi3_64"): Rename to "*adddi3_64".
("adddi3_31"): Replace by insn and splitter "*adddi3_31".
("adddi3"): Adapt expander.

("*addsi3_cc"): Allow "general_operand" for operand 2.
("*addsi3_carry1_cc", "*addsi3_carry1_cconly",
"*addsi3_carry2_cc", "*addsi3_carry2_cconly"): New patterns.

("addhi3", "addqi3"): Remove, replace by ...
("*addsi3_sign", "*addsi3_sub"): ... these new patterns.

("*subdi3_sign", "*subdi3_zero_cc", "*subdi3_zero_cconly",
"*subdi3_zero", "*subdi3_cc", "*subdi3_cconly"): New patterns.
("subdi3"): Replace by insn and splitter "*subdi3_31".
("subdi3"): New expander.

("*subsi3_borrow_cc", "*subsi3_borrow_cconly"): New patterns.

("subhi3", "subqi3"): Remove, replace by ...
("*subsi3_sign", "*subsi3_sub"): ... these new patterns.

("*muldi3_sign"): New pattern.
("muldi3"): Do not clobber CC.
("mulsi3"): Likewise.
("mulsi_6432"): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@56256 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/s390-modes.def
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 83854fc..9791779 100644 (file)
@@ -1,3 +1,68 @@
+2002-08-13  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * s390-modes.def [CCL1, CCL2, CCT1, CCT2, CCT3, CCUR, CCSR]: Declare
+       new condition code modes.
+       s390.c (s390_match_ccmode_set): Handle those new CC modes.
+       (s390_select_ccmode): Likewise.
+       (s390_branch_condition_mask): Likewise.
+
+       * s390-protos.h (s390_tm_ccmode): Declare.
+       s390.c (s390_tm_ccmode): New function.
+       (s390_match_ccmode): Allow VOIDmode as REQ_MODE.
+
+       * s390.md ("*cmpdi_tm2"): Rename to "*tmdi_ext".
+       ("*cmpsi_tm2"): Rename to "*tmsi_ext".
+       ("*cmpqi_tm2"): Rename to "*tmqi_ext".
+
+       ("*cmpdi_tm_reg", "*cmpdi_tm_mem", "*cmpsi_tm_reg", "*cmpsi_tm_mem",
+       "*cmphi_tm_sub","*cmphi_cct_0",  "*cmpqi_tm", "*cmpqi_tm_sub",
+       "*cmpqi_cct_0", "*tm_0"): Remove, replace by ...
+       ("*tmdi_reg", "*tmsi_reg", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem",
+       "*tmqi_mem", "*tmhi_full", "*tmqi_full"): ... these new patterns.
+
+       ("*ltgr", "*cmpdi_ccs_0_64", "*cmpdi_ccs_0_31", "*ltr", "*icm15",
+       "*icm15_cconly", "*cmpsi_ccs_0", "*icm3", "*cmphi_ccs_0", "*icm1", 
+       "*cmpqi_ccs_0"): Remove, replace by ...
+       ("*tstdi_sign", "*tstdi", "*tstdi_cconly", "*tstdi_cconly_31",
+       "*tstsi", "*tstsi_cconly", "*tstsi_cconly2", "*tsthi", "*tsthi_cconly", 
+       "*tstqi", "*tstqi_cconly"): ... these new patterns.
+
+       ("*cmpsidi_ccs"): Remove, replace by ...
+       ("*cmpsi_ccs_sign"): ... this new pattern.
+       ("*cmpdi_ccs_sign", "*cmpdi_ccu_zero"): New patterns.
+
+       ("*cmpqi_ccu_0", "*cmpqi_ccu_immed"): Remove, replace by ...
+       ("*cli"): ... this new pattern.
+
+       ("*adddi3_sign", "*adddi3_zero_cc", "*adddi3_zero_cconly",
+       "*adddi3_zero", "*adddi3_cc", "*adddi3_cconly", "*adddi3_cconly2"):
+       New patterns.
+       ("adddi3_64"): Rename to "*adddi3_64".
+       ("adddi3_31"): Replace by insn and splitter "*adddi3_31".
+       ("adddi3"): Adapt expander.
+
+       ("*addsi3_cc"): Allow "general_operand" for operand 2.
+       ("*addsi3_carry1_cc", "*addsi3_carry1_cconly", 
+       "*addsi3_carry2_cc", "*addsi3_carry2_cconly"): New patterns.
+
+       ("addhi3", "addqi3"): Remove, replace by ...
+       ("*addsi3_sign", "*addsi3_sub"): ... these new patterns.
+
+       ("*subdi3_sign", "*subdi3_zero_cc", "*subdi3_zero_cconly",
+       "*subdi3_zero", "*subdi3_cc", "*subdi3_cconly"): New patterns.
+       ("subdi3"): Replace by insn and splitter "*subdi3_31".
+       ("subdi3"): New expander.
+
+       ("*subsi3_borrow_cc", "*subsi3_borrow_cconly"): New patterns.
+
+       ("subhi3", "subqi3"): Remove, replace by ...
+       ("*subsi3_sign", "*subsi3_sub"): ... these new patterns.
+
+       ("*muldi3_sign"): New pattern.
+       ("muldi3"): Do not clobber CC.
+       ("mulsi3"): Likewise.
+       ("mulsi_6432"): Likewise.
+
 2002-08-13  Denis Chertykov  <denisc@overta.ru>
 
        * config/avr/avr.md: Call CC_STATUS_INIT in all peepnoles
index d472999..db577aa 100644 (file)
@@ -24,6 +24,13 @@ Boston, MA 02111-1307, USA.  */
 CC (CCZ)
 CC (CCA)
 CC (CCL)
+CC (CCL1)
+CC (CCL2)
 CC (CCU)
+CC (CCUR)
 CC (CCS)
+CC (CCSR)
 CC (CCT)
+CC (CCT1)
+CC (CCT2)
+CC (CCT3)
index f06095a..a85e350 100644 (file)
@@ -46,6 +46,7 @@ extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int));
 extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int));
 
 extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
+extern enum machine_mode s390_tm_ccmode PARAMS ((rtx, rtx, int));
 extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
 extern int symbolic_reference_mentioned_p PARAMS ((rtx));
 extern int legitimate_la_operand_p PARAMS ((rtx));
index fa7cd68..b43883b 100644 (file)
@@ -172,19 +172,22 @@ s390_match_ccmode_set (set, req_mode)
   switch (set_mode)
     {
     case CCSmode:
-      if (req_mode != CCSmode)
-        return 0;
-      break;
+    case CCSRmode:
     case CCUmode:
-      if (req_mode != CCUmode)
-        return 0;
-      break;
+    case CCURmode:
     case CCLmode:
-      if (req_mode != CCLmode)
+    case CCL1mode:
+    case CCL2mode:
+    case CCT1mode:
+    case CCT2mode:
+    case CCT3mode:
+      if (req_mode != set_mode)
         return 0;
       break;
+
     case CCZmode:
-      if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode)
+      if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode
+         && req_mode != CCSRmode && req_mode != CCURmode)
         return 0;
       break;
  
@@ -197,7 +200,8 @@ s390_match_ccmode_set (set, req_mode)
 
 /* Return true if every SET in INSN that sets the CC register 
    has source and destination with matching CC modes and that 
-   CC mode is at least as constrained as REQ_MODE.  */
+   CC mode is at least as constrained as REQ_MODE.  
+   If REQ_MODE is VOIDmode, always return false.  */
  
 int
 s390_match_ccmode (insn, req_mode)
@@ -206,6 +210,10 @@ s390_match_ccmode (insn, req_mode)
 {
   int i;
 
+  /* s390_tm_ccmode returns VOIDmode to indicate failure.  */
+  if (req_mode == VOIDmode)
+    return 0;
+
   if (GET_CODE (PATTERN (insn)) == SET)
     return s390_match_ccmode_set (PATTERN (insn), req_mode);
 
@@ -221,6 +229,45 @@ s390_match_ccmode (insn, req_mode)
   return 1;
 }
 
+/* If a test-under-mask instruction can be used to implement 
+   (compare (and ... OP1) OP2), return the CC mode required
+   to do that.  Otherwise, return VOIDmode.  
+   MIXED is true if the instruction can distinguish between
+   CC1 and CC2 for mixed selected bits (TMxx), it is false
+   if the instruction cannot (TM).  */
+
+enum machine_mode
+s390_tm_ccmode (op1, op2, mixed)
+     rtx op1;
+     rtx op2;
+     int mixed;
+{
+  int bit0, bit1;
+
+  /* ??? Fixme: should work on CONST_DOUBLE as well.  */
+  if (GET_CODE (op1) != CONST_INT || GET_CODE (op2) != CONST_INT)
+    return VOIDmode;
+
+  /* Selected bits all zero: CC0.  */
+  if (INTVAL (op2) == 0)
+    return CCTmode;
+
+  /* Selected bits all one: CC3.  */
+  if (INTVAL (op2) == INTVAL (op1))
+    return CCT3mode;
+
+  /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2.  */
+  if (mixed)
+    {
+      bit1 = exact_log2 (INTVAL (op2));
+      bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));
+      if (bit0 != -1 && bit1 != -1)
+        return bit0 > bit1 ? CCT1mode : CCT2mode;
+    }
+
+  return VOIDmode;
+}
+
 /* Given a comparison code OP (EQ, NE, etc.) and the operands 
    OP0 and OP1 of a COMPARE, return the mode to be used for the 
    comparison.  */
@@ -239,6 +286,28 @@ s390_select_ccmode (code, op0, op1)
            || GET_CODE (op1) == NEG)
          return CCLmode;
 
+       if (GET_CODE (op0) == AND)
+         {
+           /* Check whether we can potentially do it via TM.  */
+           enum machine_mode ccmode;
+           ccmode = s390_tm_ccmode (XEXP (op0, 1), op1, 1);
+           if (ccmode != VOIDmode)
+             {
+               /* Relax CCTmode to CCZmode to allow fall-back to AND
+                  if that turns out to be beneficial.  */
+               return ccmode == CCTmode ? CCZmode : ccmode;
+             }
+         }
+
+       if (register_operand (op0, HImode) 
+           && GET_CODE (op1) == CONST_INT
+           && (INTVAL (op1) == -1 || INTVAL (op1) == 65535))
+         return CCT3mode;
+       if (register_operand (op0, QImode) 
+           && GET_CODE (op1) == CONST_INT
+           && (INTVAL (op1) == -1 || INTVAL (op1) == 255))
+         return CCT3mode;
+
        return CCZmode;
 
       case LE:
@@ -253,12 +322,29 @@ s390_select_ccmode (code, op0, op1)
       case UNGE:
       case UNGT:
       case LTGT:
+       if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
+           && GET_CODE (op1) != CONST_INT)
+         return CCSRmode;
        return CCSmode;
 
-      case LEU:
       case LTU:
       case GEU:
+       if (GET_CODE (op0) == PLUS)
+         return CCL1mode;
+
+       if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
+           && GET_CODE (op1) != CONST_INT)
+         return CCURmode;
+       return CCUmode;
+
+      case LEU:
       case GTU:
+       if (GET_CODE (op0) == MINUS)
+         return CCL2mode;
+
+       if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
+           && GET_CODE (op1) != CONST_INT)
+         return CCURmode;
        return CCUmode;
 
       default:
@@ -295,13 +381,61 @@ s390_branch_condition_mask (code)
         }
       break;
 
+    case CCT1mode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC1;
+       case NE:        return CC0 | CC2 | CC3;
+       default:
+         abort ();
+        }
+      break;
+
+    case CCT2mode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC2;
+       case NE:        return CC0 | CC1 | CC3;
+       default:
+         abort ();
+        }
+      break;
+
+    case CCT3mode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC3;
+       case NE:        return CC0 | CC1 | CC2;
+       default:
+         abort ();
+        }
+      break;
+
     case CCLmode:
       switch (GET_CODE (code))
         {
         case EQ:       return CC0 | CC2;
        case NE:        return CC1 | CC3;
-       case UNORDERED: return CC2 | CC3;  /* carry */
-       case ORDERED:   return CC0 | CC1;  /* no carry */
+       default:
+         abort ();
+        }
+      break;
+
+    case CCL1mode:
+      switch (GET_CODE (code))
+        {
+       case LTU:       return CC2 | CC3;  /* carry */
+       case GEU:       return CC0 | CC1;  /* no carry */
+       default:
+         abort ();
+        }
+      break;
+
+    case CCL2mode:
+      switch (GET_CODE (code))
+        {
+       case GTU:       return CC0 | CC1;  /* borrow */
+       case LEU:       return CC2 | CC3;  /* no borrow */
        default:
          abort ();
         }
@@ -321,6 +455,20 @@ s390_branch_condition_mask (code)
         }
       break;
 
+    case CCURmode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC0;
+        case NE:       return CC2 | CC1 | CC3;
+        case LTU:      return CC2;
+        case GTU:      return CC1;
+        case LEU:      return CC0 | CC2;
+        case GEU:      return CC0 | CC1;
+       default:
+         abort ();
+        }
+      break;
+
     case CCSmode:
       switch (GET_CODE (code))
         {
@@ -341,6 +489,29 @@ s390_branch_condition_mask (code)
        default:
          abort ();
         }
+      break;
+
+    case CCSRmode:
+      switch (GET_CODE (code))
+        {
+        case EQ:       return CC0;
+        case NE:       return CC2 | CC1 | CC3;
+        case LT:       return CC2;
+        case GT:       return CC1;
+        case LE:       return CC0 | CC2;
+        case GE:       return CC0 | CC1;
+       case UNORDERED: return CC3;
+       case ORDERED:   return CC0 | CC2 | CC1;
+       case UNEQ:      return CC0 | CC3;
+        case UNLT:     return CC2 | CC3;
+        case UNGT:     return CC1 | CC3;
+        case UNLE:     return CC0 | CC2 | CC3;
+        case UNGE:     return CC0 | CC1 | CC3;
+       case LTGT:      return CC2 | CC1;
+       default:
+         abort ();
+        }
+      break;
 
     default:
       abort ();
index cbec795..35e2d3e 100644 (file)
   DONE;
 }")
 
-;(define_expand "cmphi"
-;  [(set (reg:CC 33)
-;        (compare:CC (match_operand:HI 0 "register_operand" "")
-;                    (match_operand:HI 1 "general_operand" "")))]
-;  ""
-;  "
-;{
-;  s390_compare_op0 = operands[0];
-;  s390_compare_op1 = operands[1];
-;  DONE;
-;}")
-
-;(define_expand "cmpqi"
-;  [(set (reg:CC 33)
-;        (compare:CC (match_operand:QI 0 "register_operand" "")
-;                    (match_operand:QI 1 "general_operand" "")))]
-;  ""
-;  "
-;{
-;  s390_compare_op0 = operands[0];
-;  s390_compare_op1 = operands[1];
-;  DONE;
-;}")
-
 (define_expand "cmpdf"
   [(set (reg:CC 33)
         (compare:CC (match_operand:DF 0 "register_operand" "")
 }")
 
 
-; DI instructions
+; Test-under-Mask (zero_extract) instructions
 
-(define_insn "*cmpdi_tm2"
+(define_insn "*tmdi_ext"
   [(set (reg 33)
         (compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
                                  (match_operand:DI 1 "const_int_operand" "n")
 }"
   [(set_attr "op_type" "RI")])
 
-(define_insn "*cmpdi_tm_reg"
+(define_insn "*tmsi_ext"
   [(set (reg 33)
-        (compare (and:DI (match_operand:DI 0 "register_operand" "%d")
-                         (match_operand:DI 1 "immediate_operand" "n"))
+        (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+                                 (match_operand:SI 1 "const_int_operand" "n")
+                                  (match_operand:SI 2 "const_int_operand" "n"))
                  (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
-   && s390_single_hi (operands[1], DImode, 0) >= 0"
+  "s390_match_ccmode(insn, CCTmode)
+   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
+   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
+   && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
+      == INTVAL (operands[2]) >> 4"
   "*
 {
-  int part = s390_single_hi (operands[1], DImode, 0);
-  operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
+  int part = INTVAL (operands[2]) >> 4;
+  int block = (1 << INTVAL (operands[1])) - 1;
+  int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
+
+  operands[2] = GEN_INT (block << shift);
 
   switch (part)
     {
-      case 0: return \"tmhh\\t%0,%x1\";
-      case 1: return \"tmhl\\t%0,%x1\";
-      case 2: return \"tmlh\\t%0,%x1\";
-      case 3: return \"tmll\\t%0,%x1\";
+      case 0: return \"tmh\\t%0,%x2\";
+      case 1: return \"tml\\t%0,%x2\";
       default: abort ();
     }
 }"
   [(set_attr "op_type" "RI")])
 
-(define_insn "*cmpdi_tm_mem"
+(define_insn "*tmqi_ext"
   [(set (reg 33)
-        (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
-                         (match_operand:DI 1 "immediate_operand" "n"))
+        (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
+                                 (match_operand:SI 1 "const_int_operand" "n")
+                                  (match_operand:SI 2 "const_int_operand" "n"))
                  (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
-   && s390_single_qi (operands[1], DImode, 0) >= 0"
+  "s390_match_ccmode(insn, CCTmode)
+   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
+   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
   "*
 {
-  int part = s390_single_qi (operands[1], DImode, 0);
-  operands[1] = GEN_INT (s390_extract_qi (operands[1], DImode, part));
+  int block = (1 << INTVAL (operands[1])) - 1;
+  int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
 
-  operands[0] = gen_rtx_MEM (QImode, 
-                            plus_constant (XEXP (operands[0], 0), part));
-  return \"tm\\t%0,%b1\";
+  operands[2] = GEN_INT (block << shift);
+  return \"tm\\t%0,%b2\";
 }"
   [(set_attr "op_type" "SI")
    (set_attr "atype"   "mem")])
 
-(define_insn "*ltgr"
-  [(set (reg 33)
-        (compare (match_operand:DI 0 "register_operand" "d")
-                 (match_operand:DI 1 "const0_operand" "")))
-   (set (match_operand:DI 2 "register_operand" "=d")
-        (match_dup 0))]
-  "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
-  "ltgr\\t%2,%0"
-  [(set_attr "op_type" "RRE")])
-
-(define_insn "*cmpdi_ccs_0_64"
-  [(set (reg 33)
-        (compare (match_operand:DI 0 "register_operand" "d")
-                 (match_operand:DI 1 "const0_operand" "")))]
-  "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
-  "ltgr\\t%0,%0"
-  [(set_attr "op_type" "RRE")])
-
-(define_insn "*cmpdi_ccs_0_31"
-  [(set (reg 33)
-        (compare (match_operand:DI 0 "register_operand" "d")
-                 (match_operand:DI 1 "const0_operand" "")))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "srda\\t%0,0"
-  [(set_attr "op_type" "RS")])
-
-(define_insn "*cmpdi_ccs"
-  [(set (reg 33)
-        (compare (match_operand:DI 0 "register_operand" "d,d,d")
-                 (match_operand:DI 1 "general_operand" "d,K,m")))]
-  "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
-  "@
-   cgr\\t%0,%1
-   cghi\\t%0,%c1
-   cg\\t%0,%1"
-  [(set_attr "op_type" "RRE,RI,RXE")
-   (set_attr "atype"    "reg,reg,mem")])
-   
-(define_insn "*cmpdi_ccu"
-  [(set (reg 33)
-        (compare (match_operand:DI 0 "register_operand" "d,d")
-                 (match_operand:DI 1 "general_operand" "d,m")))]
-  "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT"
-  "@
-   clgr\\t%0,%1
-   clg\\t%0,%1"
-  [(set_attr "op_type" "RRE,RXE")
-   (set_attr "atype"   "reg,mem")])
-
-(define_insn "*cmpdi_ccu_mem"
-  [(set (reg 33)
-        (compare (match_operand:DI 0 "s_operand" "oQ")
-                 (match_operand:DI 1 "s_imm_operand" "oQ")))]
-  "s390_match_ccmode(insn, CCUmode)"
-  "clc\\t%O0(8,%R0),%1"
-  [(set_attr "op_type" "SS")
-   (set_attr "atype"   "mem")])
-
-; SI instructions
+; Test-under-Mask instructions
 
-(define_insn "*cmpsi_tm2"
+(define_insn "*tmdi_reg"
   [(set (reg 33)
-        (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
-                                 (match_operand:SI 1 "const_int_operand" "n")
-                                  (match_operand:SI 2 "const_int_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)
-   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
-   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
-   && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
-      == INTVAL (operands[2]) >> 4"
+        (compare (and:DI (match_operand:DI 0 "register_operand" "%d")
+                         (match_operand:DI 1 "immediate_operand" "n"))
+                 (match_operand:DI 2 "immediate_operand" "n")))]
+  "TARGET_64BIT
+   && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
+   && s390_single_hi (operands[1], DImode, 0) >= 0"
   "*
 {
-  int part = INTVAL (operands[2]) >> 4;
-  int block = (1 << INTVAL (operands[1])) - 1;
-  int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
-
-  operands[2] = GEN_INT (block << shift);
+  int part = s390_single_hi (operands[1], DImode, 0);
+  operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
 
   switch (part)
     {
-      case 0: return \"tmh\\t%0,%x2\";
-      case 1: return \"tml\\t%0,%x2\";
+      case 0: return \"tmhh\\t%0,%x1\";
+      case 1: return \"tmhl\\t%0,%x1\";
+      case 2: return \"tmlh\\t%0,%x1\";
+      case 3: return \"tmll\\t%0,%x1\";
       default: abort ();
     }
 }"
   [(set_attr "op_type" "RI")])
 
-(define_insn "*cmpsi_tm_reg"
+(define_insn "*tmsi_reg"
   [(set (reg 33)
         (compare (and:SI (match_operand:SI 0 "register_operand" "%d")
                          (match_operand:SI 1 "immediate_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)
+                 (match_operand:SI 2 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
    && s390_single_hi (operands[1], SImode, 0) >= 0"
   "*
 {
 }"
   [(set_attr "op_type" "RI")])
 
-(define_insn "*cmpsi_tm_mem"
+(define_insn "*tmdi_mem"
+  [(set (reg 33)
+        (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
+                         (match_operand:DI 1 "immediate_operand" "n"))
+                 (match_operand:DI 2 "immediate_operand" "n")))]
+  "TARGET_64BIT
+   && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
+   && s390_single_qi (operands[1], DImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_qi (operands[1], DImode, 0);
+  operands[1] = GEN_INT (s390_extract_qi (operands[1], DImode, part));
+
+  operands[0] = gen_rtx_MEM (QImode, 
+                            plus_constant (XEXP (operands[0], 0), part));
+  return \"tm\\t%0,%b1\";
+}"
+  [(set_attr "op_type" "SI")
+   (set_attr "atype"   "mem")])
+
+(define_insn "*tmsi_mem"
   [(set (reg 33)
         (compare (and:SI (match_operand:SI 0 "s_operand" "%Qo")
                          (match_operand:SI 1 "immediate_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)
+                 (match_operand:SI 2 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
    && s390_single_qi (operands[1], SImode, 0) >= 0"
   "*
 {
   [(set_attr "op_type" "SI")
    (set_attr "atype"   "mem")])
 
-(define_insn "*ltr"
+(define_insn "*tmhi_mem"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "register_operand" "d")
-                 (match_operand:SI 1 "const0_operand" "")))
-   (set (match_operand:SI 2 "register_operand" "=d")
-        (match_dup 0))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "ltr\\t%2,%0"
-  [(set_attr "op_type" "RR")])
+        (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
+                         (match_operand:SI 1 "immediate_operand" "n"))
+                 (match_operand:SI 2 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
+   && s390_single_qi (operands[1], HImode, 0) >= 0"
+  "*
+{
+  int part = s390_single_qi (operands[1], HImode, 0);
+  operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
 
-(define_insn "*icm15"
-  [(set (reg 33)
-        (compare (match_operand:SI 0 "s_operand" "Qo")
-                 (match_operand:SI 1 "const0_operand" "")))
-   (set (match_operand:SI 2 "register_operand" "=d")
-        (match_dup 0))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "icm\\t%2,15,%0"
-  [(set_attr "op_type" "RS")
+  operands[0] = gen_rtx_MEM (QImode, 
+                            plus_constant (XEXP (operands[0], 0), part));
+  return \"tm\\t%0,%b1\";
+}"
+  [(set_attr "op_type" "SI")
    (set_attr "atype"   "mem")])
 
-(define_insn "*icm15_cconly"
+(define_insn "*tmqi_mem"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "s_operand" "Qo")
-                 (match_operand:SI 1 "const0_operand" "")))
-   (clobber (match_scratch:SI 2 "=d"))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "icm\\t%2,15,%0"
-  [(set_attr "op_type" "RS")
+        (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
+                         (match_operand:SI 1 "immediate_operand" "n"))
+                 (match_operand:SI 2 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
+  "tm\\t%0,%b1"
+  [(set_attr "op_type" "SI")
    (set_attr "atype"   "mem")])
 
-(define_insn "*cmpsi_ccs_0"
+(define_insn "*tmhi_full"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "register_operand" "d")
-                 (match_operand:SI 1 "const0_operand" "")))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "ltr\\t%0,%0"
-  [(set_attr "op_type" "RR")])
+        (compare (match_operand:HI 0 "register_operand" "d")
+                 (match_operand:HI 1 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, s390_tm_ccmode (GEN_INT (-1), operands[1], 1))"
+  "tml\\t%0,65535"
+  [(set_attr "op_type" "RX")])
 
-(define_insn "*cmpsidi_ccs"
+(define_insn "*tmqi_full"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "register_operand" "d")
-                 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "ch\\t%0,%1"
-  [(set_attr "op_type" "RR")
-   (set_attr "atype"   "mem")])
+        (compare (match_operand:QI 0 "register_operand" "d")
+                 (match_operand:QI 1 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, s390_tm_ccmode (GEN_INT (-1), operands[1], 1))"
+  "tml\\t%0,255"
+  [(set_attr "op_type" "RI")])
 
-(define_insn "*cmpsi_ccs"
+
+; Load-and-Test instructions
+
+(define_insn "*tstdi_sign"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "register_operand" "d,d,d")
-                 (match_operand:SI 1 "general_operand" "d,K,m")))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "@
-   cr\\t%0,%1
-   chi\\t%0,%c1
-   c\\t%0,%1"
-  [(set_attr "op_type" "RR,RI,RX")
-   (set_attr "atype"   "reg,reg,mem")])
-   
-(define_insn "*cmpsi_ccu"
+        (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")])
+
+(define_insn "*tstdi"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "register_operand" "d,d")
-                 (match_operand:SI 1 "general_operand" "d,m")))]
-  "s390_match_ccmode(insn, CCUmode)"
-  "@
-   clr\\t%0,%1
-   cl\\t%0,%1"
-  [(set_attr "op_type" "RR,RX")
-   (set_attr "atype"   "reg,mem")])
+        (compare (match_operand:DI 0 "register_operand" "d")
+                 (match_operand:DI 1 "const0_operand" "")))
+   (set (match_operand:DI 2 "register_operand" "=d")
+        (match_dup 0))]
+  "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+  "ltgr\\t%2,%0"
+  [(set_attr "op_type" "RRE")])
 
-(define_insn "*cmpsi_ccu_mem"
+(define_insn "*tstdi_cconly"
   [(set (reg 33)
-        (compare (match_operand:SI 0 "s_operand" "oQ")
-                 (match_operand:SI 1 "s_imm_operand" "oQ")))]
-  "s390_match_ccmode(insn, CCUmode)"
-  "clc\\t%O0(4,%R0),%1"
-   [(set_attr "op_type" "SS")
-    (set_attr "atype"   "mem")])
+        (compare (match_operand:DI 0 "register_operand" "d")
+                 (match_operand:DI 1 "const0_operand" "")))]
+  "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+  "ltgr\\t%0,%0"
+  [(set_attr "op_type" "RRE")])
 
+(define_insn "*tstdi_cconly_31"
+  [(set (reg 33)
+        (compare (match_operand:DI 0 "register_operand" "d")
+                 (match_operand:DI 1 "const0_operand" "")))]
+  "s390_match_ccmode(insn, CCSmode) && !TARGET_64BIT"
+  "srda\\t%0,0"
+  [(set_attr "op_type" "RS")])
 
-; HI instructions
+(define_insn "*tstsi"
+  [(set (reg 33)
+        (compare (match_operand:SI 0 "nonimmediate_operand" "d,Q")
+                 (match_operand:SI 1 "const0_operand" "")))
+   (set (match_operand:SI 2 "register_operand" "=d,d")
+        (match_dup 0))]
+  "s390_match_ccmode(insn, CCSmode)"
+  "@
+   ltr\\t%2,%0
+   icm\\t%2,15,%0"
+  [(set_attr "op_type" "RR,RS")
+   (set_attr "atype"   "reg,mem")])
 
-(define_insn "*cmphi_tm_sub"
+(define_insn "*tstsi_cconly"
   [(set (reg 33)
-        (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
-                         (match_operand:SI 1 "immediate_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)
-   && s390_single_qi (operands[1], HImode, 0) >= 0"
-  "*
-{
-  int part = s390_single_qi (operands[1], HImode, 0);
-  operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
+        (compare (match_operand:SI 0 "nonimmediate_operand" "d,Q")
+                 (match_operand:SI 1 "const0_operand" "")))
+   (clobber (match_scratch:SI 2 "=X,d"))]
+  "s390_match_ccmode(insn, CCSmode)"
+  "@
+   ltr\\t%0,%0
+   icm\\t%2,15,%0"
+  [(set_attr "op_type" "RR,RS")
+   (set_attr "atype"   "reg,mem")])
 
-  operands[0] = gen_rtx_MEM (QImode, 
-                            plus_constant (XEXP (operands[0], 0), part));
-  return \"tm\\t%0,%b1\";
-}"
-  [(set_attr "op_type" "SI")
-   (set_attr "atype"   "mem")])
+(define_insn "*tstsi_cconly2"
+  [(set (reg 33)
+        (compare (match_operand:SI 0 "register_operand" "d")
+                 (match_operand:SI 1 "const0_operand" "")))]
+  "s390_match_ccmode(insn, CCSmode)"
+  "ltr\\t%0,%0"
+  [(set_attr "op_type" "RR")])
 
-(define_insn "*icm3"
+(define_insn "*tsthi"
   [(set (reg 33)
         (compare (match_operand:HI 0 "s_operand" "Qo")
                  (match_operand:HI 1 "const0_operand" "")))
   [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
-(define_insn "*cmphi_cct_0"
-  [(set (reg 33)
-        (compare (match_operand:HI 0 "register_operand" "d")
-                 (match_operand:HI 1 "const0_operand"   "")))]
-  "s390_match_ccmode(insn, CCTmode)"
-  "tml\\t%0,65535"
-  [(set_attr "op_type" "RX")])
-
-(define_insn "*cmphi_ccs_0"
+(define_insn "*tsthi_cconly"
   [(set (reg 33)
         (compare (match_operand:HI 0 "s_operand" "Qo")
                  (match_operand:HI 1 "const0_operand" "")))
   [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
-(define_insn "*cmphi_ccu"
+(define_insn "*tstqi"
   [(set (reg 33)
-        (compare (match_operand:HI 0 "register_operand" "d")
-                 (match_operand:HI 1 "s_imm_operand" "Qo")))]
-  "s390_match_ccmode(insn, CCUmode)"
-  "clm\\t%0,3,%1"
+        (compare (match_operand:QI 0 "s_operand" "Qo")
+                 (match_operand:QI 1 "const0_operand" "")))
+   (set (match_operand:QI 2 "register_operand" "=d")
+        (match_dup 0))]
+  "s390_match_ccmode(insn, CCSmode)"
+  "icm\\t%2,1,%0"
   [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
-(define_insn "*cmphi_ccu_mem"
+(define_insn "*tstqi_cconly"
   [(set (reg 33)
-        (compare (match_operand:HI 0 "s_operand" "oQ")
-                 (match_operand:HI 1 "s_imm_operand" "oQ")))]
-  "s390_match_ccmode(insn, CCUmode)"
-  "clc\\t%O0(2,%R0),%1"
-  [(set_attr "op_type" "SS")
+        (compare (match_operand:QI 0 "s_operand" "Qo")
+                 (match_operand:QI 1 "const0_operand" "")))
+   (clobber (match_scratch:QI 2 "=d"))]
+  "s390_match_ccmode(insn, CCSmode)"
+  "icm\\t%2,1,%0"
+  [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
 
-; QI instructions
+; Compare (signed) instructions
 
-(define_insn "*cmpqi_tm2"
+(define_insn "*cmpdi_ccs_sign"
   [(set (reg 33)
-        (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
-                                 (match_operand:SI 1 "const_int_operand" "n")
-                                  (match_operand:SI 2 "const_int_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)
-   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 
-   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
-  "*
-{
-  int block = (1 << INTVAL (operands[1])) - 1;
-  int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
-
-  operands[2] = GEN_INT (block << shift);
-  return \"tm\\t%0,%b2\";
-}"
-  [(set_attr "op_type" "SI")
-   (set_attr "atype"   "mem")])
-
-(define_insn "*cmpqi_tm"
-  [(set (reg 33)
-        (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%d,Q")
-                         (match_operand:QI 1 "immediate_operand" "n,n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)"
+        (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
+                 (match_operand:DI 0 "register_operand" "d,d")))]
+  "s390_match_ccmode(insn, CCSRmode) && TARGET_64BIT"
   "@
-   tml\\t%0,%b1
-   tm\\t%0,%b1"
-  [(set_attr "op_type" "RI,SI")
+   cgfr\\t%0,%1
+   cgf\\t%0,%1"
+  [(set_attr "op_type" "RRE,RXE")
    (set_attr "atype"   "reg,mem")])
 
-(define_insn "*cmpqi_tm_sub"
+(define_insn "*cmpdi_ccs"
   [(set (reg 33)
-        (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
-                         (match_operand:SI 1 "immediate_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)"
-  "tm\\t%0,%b1"
-  [(set_attr "op_type" "SI")
+        (compare (match_operand:DI 0 "register_operand" "d,d,d")
+                 (match_operand:DI 1 "general_operand" "d,K,m")))]
+  "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+  "@
+   cgr\\t%0,%1
+   cghi\\t%0,%c1
+   cg\\t%0,%1"
+  [(set_attr "op_type" "RRE,RI,RXE")
+   (set_attr "atype"    "reg,reg,mem")])
+   
+(define_insn "*cmpsi_ccs_sign"
+  [(set (reg 33)
+        (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))
+                 (match_operand:SI 0 "register_operand" "d")))]
+  "s390_match_ccmode(insn, CCSRmode)"
+  "ch\\t%0,%1"
+  [(set_attr "op_type" "RX")
    (set_attr "atype"   "mem")])
 
-(define_insn "*icm1"
+(define_insn "*cmpsi_ccs"
   [(set (reg 33)
-        (compare (match_operand:QI 0 "s_operand" "Qo")
-                 (match_operand:QI 1 "const0_operand" "")))
-   (set (match_operand:QI 2 "register_operand" "=d")
-        (match_dup 0))]
+        (compare (match_operand:SI 0 "register_operand" "d,d,d")
+                 (match_operand:SI 1 "general_operand" "d,K,m")))]
   "s390_match_ccmode(insn, CCSmode)"
-  "icm\\t%2,1,%0"
-  [(set_attr "op_type" "RS")
-   (set_attr "atype"   "mem")])
+  "@
+   cr\\t%0,%1
+   chi\\t%0,%c1
+   c\\t%0,%1"
+  [(set_attr "op_type" "RR,RI,RX")
+   (set_attr "atype"   "reg,reg,mem")])
+   
 
-(define_insn "*tm_0"
+; Compare (unsigned) instructions
+
+(define_insn "*cmpdi_ccu_zero"
   [(set (reg 33)
-        (compare (zero_extend:SI (and:QI (match_operand:QI 0 "s_operand" "Qo")
-                                         (match_operand:QI 1 "immediate_operand" "")))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode) &&
-   INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
-  "tm\\t%0,%1"
-  [(set_attr "op_type" "RI")
-   (set_attr "atype"   "mem")])
+        (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
+                 (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,RXE")
+   (set_attr "atype"   "reg,mem")])
 
-(define_insn "*cmpqi_cct_0"
+(define_insn "*cmpdi_ccu"
   [(set (reg 33)
-        (compare (match_operand:QI 0 "register_operand" "d")
-                 (match_operand:QI 1 "const0_operand"   "")))]
-  "s390_match_ccmode(insn, CCTmode)"
-  "tml\\t%0,255"
-  [(set_attr "op_type" "RI")])
+        (compare (match_operand:DI 0 "register_operand" "d,d")
+                 (match_operand:DI 1 "general_operand" "d,m")))]
+  "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT"
+  "@
+   clgr\\t%0,%1
+   clg\\t%0,%1"
+  [(set_attr "op_type" "RRE,RXE")
+   (set_attr "atype"   "reg,mem")])
 
-(define_insn "*cmpqi_ccs_0"
+(define_insn "*cmpsi_ccu"
   [(set (reg 33)
-        (compare (match_operand:QI 0 "s_operand" "Qo")
-                 (match_operand:QI 1 "const0_operand" "")))
-   (clobber (match_scratch:QI 2 "=d"))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "icm\\t%2,1,%0"
-  [(set_attr "op_type" "RS")
-   (set_attr "atype"   "mem")])
+        (compare (match_operand:SI 0 "register_operand" "d,d")
+                 (match_operand:SI 1 "general_operand" "d,m")))]
+  "s390_match_ccmode(insn, CCUmode)"
+  "@
+   clr\\t%0,%1
+   cl\\t%0,%1"
+  [(set_attr "op_type" "RR,RX")
+   (set_attr "atype"   "reg,mem")])
 
-(define_insn "*cmpqi_ccu_0"
+(define_insn "*cmphi_ccu"
   [(set (reg 33)
-        (compare (match_operand:QI 0 "s_operand"      "Qo")
-                 (match_operand:QI 1 "const0_operand" "")))]
+        (compare (match_operand:HI 0 "register_operand" "d")
+                 (match_operand:HI 1 "s_imm_operand" "Qo")))]
   "s390_match_ccmode(insn, CCUmode)"
-  "cli\\t%0,0"
-  [(set_attr "op_type" "SI")
+  "clm\\t%0,3,%1"
+  [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
 (define_insn "*cmpqi_ccu"
   [(set_attr "op_type" "RS")
    (set_attr "atype"   "mem")])
 
-(define_insn "*cmpqi_ccu_immed"
+(define_insn "*cli"
   [(set (reg 33)
         (compare (match_operand:QI 0 "s_operand" "Qo")
-                 (match_operand:QI 1 "const_int_operand" "n")))]
-  "s390_match_ccmode(insn, CCUmode) &&
-   INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
-  "cli\\t%0,%1"
+                 (match_operand:QI 1 "immediate_operand" "n")))]
+  "s390_match_ccmode (insn, CCUmode)"
+  "cli\\t%0,%b1"
   [(set_attr "op_type" "SI")
    (set_attr "atype"   "mem")])
 
+(define_insn "*cmpdi_ccu_mem"
+  [(set (reg 33)
+        (compare (match_operand:DI 0 "s_operand" "oQ")
+                 (match_operand:DI 1 "s_imm_operand" "oQ")))]
+  "s390_match_ccmode(insn, CCUmode)"
+  "clc\\t%O0(8,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
+
+(define_insn "*cmpsi_ccu_mem"
+  [(set (reg 33)
+        (compare (match_operand:SI 0 "s_operand" "oQ")
+                 (match_operand:SI 1 "s_imm_operand" "oQ")))]
+  "s390_match_ccmode(insn, CCUmode)"
+  "clc\\t%O0(4,%R0),%1"
+   [(set_attr "op_type" "SS")
+    (set_attr "atype"   "mem")])
+
+(define_insn "*cmphi_ccu_mem"
+  [(set (reg 33)
+        (compare (match_operand:HI 0 "s_operand" "oQ")
+                 (match_operand:HI 1 "s_imm_operand" "oQ")))]
+  "s390_match_ccmode(insn, CCUmode)"
+  "clc\\t%O0(2,%R0),%1"
+  [(set_attr "op_type" "SS")
+   (set_attr "atype"   "mem")])
+
 (define_insn "*cmpqi_ccu_mem"
   [(set (reg 33)
         (compare (match_operand:QI 0 "s_operand" "oQ")
 ; adddi3 instruction pattern(s).
 ;
 
-(define_insn "addaddr_esame"
-  [(set (match_operand:DI 0 "register_operand" "=a,a")
-        (plus:DI (match_operand:DI 1 "register_operand" "%a,a")
-                 (match_operand:DI 2 "nonmemory_operand" "J,a")))]
-  "TARGET_64BIT && (((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
-     (REGNO (operands[1]) == BASE_REGISTER)) && 
-       (GET_CODE (operands[2]) == REG ||
-        CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
+(define_insn "addaddr_esame"
+  [(set (match_operand:DI 0 "register_operand" "=a,a")
+        (plus:DI (match_operand:DI 1 "register_operand" "%a,a")
+                 (match_operand:DI 2 "nonmemory_operand" "J,a")))]
+  "TARGET_64BIT && (((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
+     (REGNO (operands[1]) == BASE_REGISTER)) && 
+       (GET_CODE (operands[2]) == REG ||
+        CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
+  "@
+   la\\t%0,%c2(,%1)
+   la\\t%0,0(%1,%2)"
+  [(set_attr "op_type" "RX")
+   (set_attr "atype"   "mem")
+   (set_attr "type"    "la")])
+
+(define_insn "*adddi3_sign"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (plus:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_operand:DI 1 "register_operand" "0,0")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   agfr\\t%0,%2
+   agf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*adddi3_zero_cc"
+  [(set (reg 33) 
+        (compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+                          (match_operand:DI 1 "register_operand" "0,0"))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d,d")
+        (plus:DI (zero_extend:DI (match_dup 2)) (match_dup 1)))]
+  "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+  "@
+   algfr\\t%0,%2
+   algf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*adddi3_zero_cconly"
+  [(set (reg 33) 
+        (compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+                          (match_operand:DI 1 "register_operand" "0,0"))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+  "@
+   algfr\\t%0,%2
+   algf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*adddi3_zero"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_operand:DI 1 "register_operand" "0,0")))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   algfr\\t%0,%2
+   algf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*adddi3_cc"
+  [(set (reg 33) 
+        (compare (plus:DI (match_operand:DI 1 "register_operand" "%0,0")
+                          (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d,d")
+        (plus:DI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+  "@
+   algr\\t%0,%2
+   alg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*adddi3_cconly"
+  [(set (reg 33) 
+        (compare (plus:DI (match_operand:DI 1 "register_operand" "%0,0")
+                          (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
   "@
-   la\\t%0,%c2(,%1)
-   la\\t%0,0(%1,%2)"
-  [(set_attr "op_type" "RX")
-   (set_attr "atype"   "mem")
-   (set_attr "type"    "la")])
+   algr\\t%0,%2
+   alg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*adddi3_cconly2"
+  [(set (reg 33) 
+        (compare (match_operand:DI 1 "register_operand" "%0,0")
+                 (neg:SI (match_operand:DI 2 "general_operand" "d,m"))))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode(insn, CCLmode) && TARGET_64BIT"
+  "@
+   algr\\t%0,%2
+   alg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
 
-(define_insn "adddi3_64"
+(define_insn "*adddi3_64"
   [(set (match_operand:DI 0 "register_operand" "=d,d,d")
         (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0")
                  (match_operand:DI 2 "general_operand" "d,K,m") ) )
   [(set_attr "op_type"  "RRE,RI,RXE")
    (set_attr "atype"    "reg,reg,mem")])
 
-(define_insn "adddi3_31"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (plus:DI (match_operand:DI 1 "register_operand" "0,0")
-                 (match_operand:DI 2 "general_operand" "d,m") ) )
+(define_insn_and_split "*adddi3_31"
+  [(set (match_operand:DI 0 "register_operand" "=&d")
+        (plus:DI (match_operand:DI 1 "register_operand" "%0")
+                 (match_operand:DI 2 "general_operand" "dm") ) )
    (clobber (reg:CC 33))]
   "!TARGET_64BIT"
-  "*
-{
-   switch (which_alternative)
-     {
-     case 0: /* d <- d */
-       output_asm_insn (\"ar\\t%0,%2\", operands);
-       output_asm_insn (\"alr\\t%N0,%N2\", operands);
-       break;
-
-     case 1: /* d <- m */
-       output_asm_insn (\"a\\t%0,%2\", operands);
-       output_asm_insn (\"al\\t%N0,%N2\", operands);
-       break;
-
-     default:
-       abort ();
-     }
-
-   output_asm_insn (\"brc\\t12,.+8\", operands);
-   return \"ahi\\t%0,1\";
-}"
-  [(set_attr "op_type" "NN,NN")
-   (set_attr "atype"   "reg,mem")
-   (set_attr "type"    "o2,o2")
-   (set_attr "length"  "12,16")])
+  "#"
+  "&& reload_completed"
+  [(parallel
+    [(set (match_dup 3) (plus:SI (match_dup 4) (match_dup 5)))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (reg:CCL1 33)
+          (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
+                        (match_dup 7)))
+     (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
+   (set (pc)
+        (if_then_else (ltu (reg:CCL1 33) (const_int 0))
+                      (pc)
+                      (label_ref (match_dup 9))))
+   (parallel
+    [(set (match_dup 3) (plus:SI (match_dup 3) (const_int 1)))
+     (clobber (reg:CC 33))])
+   (match_dup 9)]
+  "operands[3] = operand_subword (operands[0], 0, 1, DImode);
+   operands[4] = operand_subword (operands[1], 0, 1, DImode);
+   operands[5] = operand_subword (operands[2], 0, 1, DImode);
+   operands[6] = operand_subword (operands[0], 1, 1, DImode);
+   operands[7] = operand_subword (operands[1], 1, 1, DImode);
+   operands[8] = operand_subword (operands[2], 1, 1, DImode);
+   operands[9] = gen_label_rtx ();"
+  [(set_attr "op_type"  "NN")
+   (set_attr "type"     "o3")])
 
 (define_expand "adddi3"
-  [(set (match_operand:DI 0 "register_operand" "")
-        (plus:DI (match_operand:DI 1 "register_operand" "")
-                 (match_operand:DI 2 "general_operand" "")))]
+  [(parallel
+    [(set (match_operand:DI 0 "register_operand" "")
+          (plus:DI (match_operand:DI 1 "register_operand" "")
+                   (match_operand:DI 2 "general_operand" "")))
+     (clobber (reg:CC 33))])]
   ""
-  "
-{
-  if (TARGET_64BIT)
-    emit_insn(gen_adddi3_64 (operands[0],operands[1],operands[2]));
-  else
-    emit_insn(gen_adddi3_31 (operands[0],operands[1],operands[2]));
-  DONE;                
-}")
+  "")
 
 (define_insn "*la_64"
   [(set (match_operand:DI 0 "register_operand" "=d")
     (set_attr "atype"    "mem")
     (set_attr "type"     "la")])
 
+(define_insn "*addsi3_carry1_cc"
+  [(set (reg 33) 
+        (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+                          (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_dup 1)))
+   (set (match_operand:SI 0 "register_operand" "=d,d")
+        (plus:SI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode (insn, CCL1mode)" 
+  "@
+   alr\\t%0,%2
+   al\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*addsi3_carry1_cconly"
+  [(set (reg 33) 
+        (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+                          (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_dup 1)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
+  "s390_match_ccmode (insn, CCL1mode)" 
+  "@
+   alr\\t%0,%2
+   al\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*addsi3_carry2_cc"
+  [(set (reg 33) 
+        (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+                          (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_dup 2)))
+   (set (match_operand:SI 0 "register_operand" "=d,d")
+        (plus:SI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode (insn, CCL1mode)" 
+  "@
+   alr\\t%0,%2
+   al\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*addsi3_carry2_cconly"
+  [(set (reg 33) 
+        (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+                          (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_dup 2)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
+  "s390_match_ccmode (insn, CCL1mode)" 
+  "@
+   alr\\t%0,%2
+   al\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])  
+
 (define_insn "*addsi3_cc"
   [(set (reg 33) 
         (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
-                          (match_operand:SI 2 "nonimmediate_operand" "d,m"))
+                          (match_operand:SI 2 "general_operand" "d,m"))
                  (const_int 0)))
    (set (match_operand:SI 0 "register_operand" "=d,d")
         (plus:SI (match_dup 1) (match_dup 2)))]
-  "s390_match_ccmode(insn, CCLmode)"
+  "s390_match_ccmode (insn, CCLmode)" 
   "@
    alr\\t%0,%2
    al\\t%0,%2"
                           (match_operand:SI 2 "general_operand" "d,m"))
                  (const_int 0)))
    (clobber (match_scratch:SI 0 "=d,d"))]
-  "s390_match_ccmode(insn, CCLmode)"
+  "s390_match_ccmode (insn, CCLmode)" 
   "@
    alr\\t%0,%2
    al\\t%0,%2"
   [(set_attr "op_type"  "RR,RX")
    (set_attr "atype"    "reg,mem")])  
 
+(define_insn "*addsi3_sign"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))
+   (clobber (reg:CC 33))]
+  ""
+  "ah\\t%0,%2"
+  [(set_attr "op_type"  "RX")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*addsi3_sub"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (subreg:SI (match_operand:HI 2 "memory_operand" "m") 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "ah\\t%0,%2"
+  [(set_attr "op_type"  "RX")
+   (set_attr "atype"    "mem")])
+
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d,d")
         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
 
 
 ;
-; addhi3 instruction pattern(s).
-;
-
-(define_insn "addhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
-        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
-                 (match_operand:HI 2 "general_operand" "d,K,m")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   ar\\t%0,%2
-   ahi\\t%0,%h2
-   ah\\t%0,%2"
-  [(set_attr "op_type"  "RR,RI,RX")
-   (set_attr "atype"    "reg,reg,mem")])
-
-
-;
-; addqi3 instruction pattern(s).
-;
-
-(define_insn "addqi3"
-  [(set (match_operand:QI 0 "register_operand" "=d,d")
-        (plus:QI (match_operand:QI 1 "register_operand" "%0,0")
-                 (match_operand:QI 2 "general_operand" "a,n")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   ar\\t%0,%2
-   ahi\\t%0,%h2"
-  [(set_attr "op_type"  "RX,RX")
-   (set_attr "atype"    "reg,mem")])
-
-
-;
 ; adddf3 instruction pattern(s).
 ;
 
 ; subdi3 instruction pattern(s).
 ;
 
+(define_insn "*subdi3_sign"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+                  (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   sgfr\\t%0,%2
+   sgf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*subdi3_zero_cc"
+  [(set (reg 33) 
+        (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+                           (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m")))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d,d")
+        (minus:DI (match_dup 1) (zero_extend:DI (match_dup 2))))]
+  "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+  "@
+   slgfr\\t%0,%2
+   slgf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*subdi3_zero_cconly"
+  [(set (reg 33) 
+        (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+                           (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m")))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+  "@
+   slgfr\\t%0,%2
+   slgf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])  
+
+(define_insn "*subdi3_zero"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+                  (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
+   (clobber (reg:CC 33))]
+  "TARGET_64BIT"
+  "@
+   slgfr\\t%0,%2
+   slgf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*subdi3_cc"
+  [(set (reg 33)
+        (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+                           (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d,d")
+        (minus:DI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode (insn, CCLmode)"
+  "@
+   slgr\\t%0,%2
+   slg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*subdi3_cconly"
+  [(set (reg 33)
+        (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+                           (match_operand:DI 2 "general_operand" "d,m"))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d,d"))]
+  "s390_match_ccmode (insn, CCLmode)"
+  "@
+   slgr\\t%0,%2
+   slg\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")])
+
 (define_insn "*subdi3_64"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
         (minus:DI (match_operand:DI 1 "register_operand" "0,0")
   [(set_attr "op_type"  "RRE,RRE")
    (set_attr "atype"    "reg,mem")])
 
-(define_insn "subdi3"
-  [(set (match_operand:DI 0 "register_operand" "=d,d")
-        (minus:DI (match_operand:DI 1 "register_operand" "0,0")
-                  (match_operand:DI 2 "general_operand" "d,m")))
+(define_insn_and_split "*subdi3_31"
+  [(set (match_operand:DI 0 "register_operand" "=&d")
+        (minus:DI (match_operand:DI 1 "register_operand" "0")
+                  (match_operand:DI 2 "general_operand" "dm") ) )
    (clobber (reg:CC 33))]
-  ""
-  "*
-{
-   switch (which_alternative)
-     {
-     case 0: /* d <- d */
-       output_asm_insn (\"sr\\t%0,%2\", operands);
-       output_asm_insn (\"slr\\t%N0,%N2\", operands);
-       break;
-     case 1: /* d <- m */
-       output_asm_insn (\"s\\t%0,%2\", operands);
-       output_asm_insn (\"sl\\t%N0,%N2\", operands);
-       break;
-
-     default:
-       abort ();
-     }
+  "!TARGET_64BIT"
+  "#"
+  "&& reload_completed"
+  [(parallel
+    [(set (match_dup 3) (minus:SI (match_dup 4) (match_dup 5)))
+     (clobber (reg:CC 33))])
+   (parallel
+    [(set (reg:CCL2 33)
+          (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
+                        (match_dup 7)))
+     (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
+   (set (pc)
+        (if_then_else (gtu (reg:CCL2 33) (const_int 0))
+                      (pc)
+                      (label_ref (match_dup 9))))
+   (parallel
+    [(set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))
+     (clobber (reg:CC 33))])
+   (match_dup 9)]
+  "operands[3] = operand_subword (operands[0], 0, 1, DImode);
+   operands[4] = operand_subword (operands[1], 0, 1, DImode);
+   operands[5] = operand_subword (operands[2], 0, 1, DImode);
+   operands[6] = operand_subword (operands[0], 1, 1, DImode);
+   operands[7] = operand_subword (operands[1], 1, 1, DImode);
+   operands[8] = operand_subword (operands[2], 1, 1, DImode);
+   operands[9] = gen_label_rtx ();"
+  [(set_attr "op_type"  "NN")
+   (set_attr "type"     "o3")])
 
-   output_asm_insn (\"brc\\t11,.+8\", operands);
-   return \"ahi\\t%0,-1\";
-}"
-  [(set_attr "op_type"  "NN,NN")
-   (set_attr "atype"    "reg,mem")
-   (set_attr "type"     "other,other")
-   (set_attr "length"   "12,16")])
+(define_expand "subdi3"
+  [(parallel
+    [(set (match_operand:DI 0 "register_operand" "")
+          (minus:DI (match_operand:DI 1 "register_operand" "")
+                    (match_operand:DI 2 "general_operand" "")))
+     (clobber (reg:CC 33))])]
+  ""
+  "")
 
 ;
 ; subsi3 instruction pattern(s).
 ;
 
+(define_insn "*subsi3_borrow_cc"
+  [(set (reg 33)
+        (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+                           (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_dup 1)))
+   (set (match_operand:SI 0 "register_operand" "=d,d")
+        (minus:SI (match_dup 1) (match_dup 2)))]
+  "s390_match_ccmode(insn, CCL2mode)"
+  "@
+   slr\\t%0,%2
+   sl\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
+(define_insn "*subsi3_borrow_cconly"
+  [(set (reg 33)
+        (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+                           (match_operand:SI 2 "general_operand" "d,m"))
+                 (match_dup 1)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
+  "s390_match_ccmode(insn, CCL2mode)"
+  "@
+   slr\\t%0,%2
+   sl\\t%0,%2"
+  [(set_attr "op_type"  "RR,RX")
+   (set_attr "atype"    "reg,mem")])
+
 (define_insn "*subsi3_cc"
   [(set (reg 33)
         (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
   [(set_attr "op_type"  "RR,RX")
    (set_attr "atype"    "reg,mem")])
 
+(define_insn "*subsi3_sign"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (minus:SI (match_operand:SI 1 "register_operand" "0")
+                  (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))
+   (clobber (reg:CC 33))]
+  ""
+  "sh\\t%0,%2"
+  [(set_attr "op_type"  "RX")
+   (set_attr "atype"    "mem")])
+
+(define_insn "*subsi3_sub"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (minus:SI (match_operand:SI 1 "register_operand" "0")
+                  (subreg:SI (match_operand:HI 2 "memory_operand" "m") 0)))
+   (clobber (reg:CC 33))]
+  ""
+  "sh\\t%0,%2"
+  [(set_attr "op_type"  "RX")
+   (set_attr "atype"    "mem")])
+
 (define_insn "subsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (minus:SI (match_operand:SI 1 "register_operand" "0,0")
   [(set_attr "op_type"  "RR,RX")
    (set_attr "atype"    "reg,mem")])
 
-;
-; subhi3 instruction pattern(s).
-;
-
-(define_insn "subhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,d")
-        (minus:HI (match_operand:HI 1 "register_operand" "0,0")
-                  (match_operand:HI 2 "general_operand" "d,m")))
-   (clobber (reg:CC 33))]
-  ""
-  "@
-   sr\\t%0,%2
-   sh\\t%0,%2"
-  [(set_attr "op_type"  "RR,RX")
-   (set_attr "atype"    "reg,mem")])
-
-;
-; subqi3 instruction pattern(s).
-;
-
-(define_insn "subqi3"
-  [(set (match_operand:QI 0 "register_operand" "=d")
-        (minus:QI (match_operand:QI 1 "register_operand" "0")
-                  (match_operand:QI 2 "register_operand" "d")))
-   (clobber (reg:CC 33))]
-  ""
-  "sr\\t%0,%2"
-   [(set_attr "op_type"  "RR")])
 
 ;
 ; subdf3 instruction pattern(s).
 ; muldi3 instruction pattern(s).
 ;
 
+(define_insn "*muldi3_sign"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (mult:DI (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,m"))
+                 (match_operand:DI 1 "register_operand" "0,0")))]
+  "TARGET_64BIT"
+  "@
+   msgfr\\t%0,%2
+   msgf\\t%0,%2"
+  [(set_attr "op_type"  "RRE,RXE")
+   (set_attr "atype"    "reg,mem")
+   (set_attr "type"     "imul")])
+
+
 (define_insn "muldi3"
   [(set (match_operand:DI 0 "register_operand" "=d,d,d")
         (mult:DI (match_operand:DI 1 "register_operand" "%0,0,0")
-                 (match_operand:DI 2 "general_operand" "d,K,m")))
-   (clobber (reg:CC 33))]
+                 (match_operand:DI 2 "general_operand" "d,K,m")))]
   "TARGET_64BIT"
   "@
    msgr\\t%0,%2
    mghi\\t%0,%h2
    msg\\t%0,%2"
-  [(set_attr "op_type"  "RRE,RI,RX")
+  [(set_attr "op_type"  "RRE,RI,RXE")
    (set_attr "atype"    "reg,reg,mem")
    (set_attr "type"     "imul")])
 
 (define_insn "mulsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d,d")
         (mult:SI  (match_operand:SI 1 "register_operand" "%0,0,0")
-                  (match_operand:SI 2 "general_operand" "d,K,m")))
-   (clobber (reg:CC 33))]
+                  (match_operand:SI 2 "general_operand" "d,K,m")))]
   ""
   "@
    msr\\t%0,%2
          (mult:DI (sign_extend:DI 
                    (truncate:SI (match_operand:DI 1 "register_operand" "0,0")))
                   (sign_extend:DI
-                   (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
-    (clobber (reg:CC 33))]
+                   (match_operand:SI 2 "nonimmediate_operand" "d,m"))))]
    "!TARGET_64BIT"
    "@
     mr\\t%0,%2