]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
s390.md ("movstr_short_64", [...]): Merge ...
authorUlrich Weigand <uweigand@de.ibm.com>
Wed, 22 Oct 2003 16:19:54 +0000 (16:19 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Wed, 22 Oct 2003 16:19:54 +0000 (16:19 +0000)
* config/s390/s390.md ("movstr_short_64", "movstr_short_31"): Merge ...
("*movstr_short"): ... into this insn pattern.
("movstr_short"): New expander.
("*movstr_long_64"): Rename from "movstr_long_64", simplify.
("*movstr_long_31"): Rename from "movstr_long_31", simplify.
("movstr_long"): New expander.
("clrstr_short_64", "clrstr_short_31"): Merge ...
("*clrstr_short"): ... into this insn pattern.
("clrstr_short"): New expander.
("*clrstr_long_64"): Rename from "clrstr_long_64", simplify.
("*clrstr_long_31"): Rename from "clrstr_long_31", simplify.
("clrstr_long"): New expander.
("cmpmem_short_64", "cmpmem_short_31"): Merge ...
("*cmpmem_short"): ... into this insn pattern.
("cmpmem_short"): New expander.
("*cmpmem_long_64"): Rename from "cmpmem_long_64".
("*cmpmem_long_31"): Rename from "cmpmem_long_31".
("cmpmem_long"): New expander.
* config/s390/s390.c (s390_expand_movstr): Use new expanders.
(s390_expand_clrstr): Likewise.
(s390_expand_cmpmem): Likewise.

From-SVN: r72807

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/config/s390/s390.md

index 580c3d01da143ab2c098a96ba9689945c287025d..adc1bc099baa41b59fca2961f75ae6d152214527 100644 (file)
@@ -1,3 +1,27 @@
+2003-10-22  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.md ("movstr_short_64", "movstr_short_31"): Merge ...
+       ("*movstr_short"): ... into this insn pattern.
+       ("movstr_short"): New expander.
+       ("*movstr_long_64"): Rename from "movstr_long_64", simplify.
+       ("*movstr_long_31"): Rename from "movstr_long_31", simplify.
+       ("movstr_long"): New expander.
+       ("clrstr_short_64", "clrstr_short_31"): Merge ...
+       ("*clrstr_short"): ... into this insn pattern.
+       ("clrstr_short"): New expander.
+       ("*clrstr_long_64"): Rename from "clrstr_long_64", simplify.
+       ("*clrstr_long_31"): Rename from "clrstr_long_31", simplify.
+       ("clrstr_long"): New expander.
+       ("cmpmem_short_64", "cmpmem_short_31"): Merge ...
+       ("*cmpmem_short"): ... into this insn pattern.
+       ("cmpmem_short"): New expander.
+       ("*cmpmem_long_64"): Rename from "cmpmem_long_64".
+       ("*cmpmem_long_31"): Rename from "cmpmem_long_31".
+       ("cmpmem_long"): New expander.
+       * config/s390/s390.c (s390_expand_movstr): Use new expanders.
+       (s390_expand_clrstr): Likewise.
+       (s390_expand_cmpmem): Likewise.
+
 2003-10-22  Mark Mitchell  <mark@codesourcery.com>
 
        * c-pch.c (struct c_pch_validity): Add pch_init field.
index 10a69676f8b1b007470c88f6f8431bb8827639e6..be564d639a293495b265a2121fd4cc8d2007d6d6 100644 (file)
@@ -2970,34 +2970,15 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED,
 void
 s390_expand_movstr (rtx dst, rtx src, rtx len)
 {
-  rtx (*gen_short) (rtx, rtx, rtx) =
-    TARGET_64BIT ? gen_movstr_short_64 : gen_movstr_short_31;
-  rtx (*gen_long) (rtx, rtx, rtx, rtx) =
-    TARGET_64BIT ? gen_movstr_long_64 : gen_movstr_long_31;
-
-
   if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
     {
       if (INTVAL (len) > 0)
-        emit_insn (gen_short (dst, src, GEN_INT (INTVAL (len) - 1)));
+        emit_insn (gen_movstr_short (dst, src, GEN_INT (INTVAL (len) - 1)));
     }
 
   else if (TARGET_MVCLE)
     {
-      enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode;
-      enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode;
-      rtx reg0 = gen_reg_rtx (double_mode);
-      rtx reg1 = gen_reg_rtx (double_mode);
-
-      emit_move_insn (gen_highpart (single_mode, reg0),
-                     force_operand (XEXP (dst, 0), NULL_RTX));
-      emit_move_insn (gen_highpart (single_mode, reg1),
-                     force_operand (XEXP (src, 0), NULL_RTX));
-
-      convert_move (gen_lowpart (single_mode, reg0), len, 1);
-      convert_move (gen_lowpart (single_mode, reg1), len, 1);
-
-      emit_insn (gen_long (reg0, reg1, reg0, reg1));
+      emit_insn (gen_movstr_long (dst, src, convert_to_mode (Pmode, len, 1)));
     }
 
   else
@@ -3009,7 +2990,7 @@ s390_expand_movstr (rtx dst, rtx src, rtx len)
 
       mode = GET_MODE (len);
       if (mode == VOIDmode)
-        mode = word_mode;
+        mode = Pmode;
 
       type = lang_hooks.types.type_for_mode (mode, 1);
       if (!type)
@@ -3042,7 +3023,7 @@ s390_expand_movstr (rtx dst, rtx src, rtx len)
                                           make_tree (type, blocks),
                                           make_tree (type, const0_rtx)));
 
-      emit_insn (gen_short (dst, src, GEN_INT (255)));
+      emit_insn (gen_movstr_short (dst, src, GEN_INT (255)));
       s390_load_address (dst_addr,
                         gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
       s390_load_address (src_addr,
@@ -3054,7 +3035,8 @@ s390_expand_movstr (rtx dst, rtx src, rtx len)
 
       expand_end_loop ();
 
-      emit_insn (gen_short (dst, src, convert_to_mode (word_mode, count, 1)));
+      emit_insn (gen_movstr_short (dst, src, 
+                                  convert_to_mode (Pmode, count, 1)));
       emit_label (end_label);
     }
 }
@@ -3064,33 +3046,15 @@ s390_expand_movstr (rtx dst, rtx src, rtx len)
 void
 s390_expand_clrstr (rtx dst, rtx len)
 {
-  rtx (*gen_short) (rtx, rtx) =
-    TARGET_64BIT ? gen_clrstr_short_64 : gen_clrstr_short_31;
-  rtx (*gen_long) (rtx, rtx, rtx) =
-    TARGET_64BIT ? gen_clrstr_long_64 : gen_clrstr_long_31;
-
-
   if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
     {
       if (INTVAL (len) > 0)
-        emit_insn (gen_short (dst, GEN_INT (INTVAL (len) - 1)));
+        emit_insn (gen_clrstr_short (dst, GEN_INT (INTVAL (len) - 1)));
     }
 
   else if (TARGET_MVCLE)
     {
-      enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode;
-      enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode;
-      rtx reg0 = gen_reg_rtx (double_mode);
-      rtx reg1 = gen_reg_rtx (double_mode);
-
-      emit_move_insn (gen_highpart (single_mode, reg0),
-                     force_operand (XEXP (dst, 0), NULL_RTX));
-      convert_move (gen_lowpart (single_mode, reg0), len, 1);
-
-      emit_move_insn (gen_highpart (single_mode, reg1), const0_rtx);
-      emit_move_insn (gen_lowpart (single_mode, reg1), const0_rtx);
-
-      emit_insn (gen_long (reg0, reg1, reg0));
+      emit_insn (gen_clrstr_long (dst, convert_to_mode (Pmode, len, 1)));
     }
 
   else
@@ -3102,7 +3066,7 @@ s390_expand_clrstr (rtx dst, rtx len)
 
       mode = GET_MODE (len);
       if (mode == VOIDmode)
-        mode = word_mode;
+        mode = Pmode;
 
       type = lang_hooks.types.type_for_mode (mode, 1);
       if (!type)
@@ -3133,7 +3097,7 @@ s390_expand_clrstr (rtx dst, rtx len)
                                           make_tree (type, blocks),
                                           make_tree (type, const0_rtx)));
 
-      emit_insn (gen_short (dst, GEN_INT (255)));
+      emit_insn (gen_clrstr_short (dst, GEN_INT (255)));
       s390_load_address (dst_addr,
                         gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
 
@@ -3143,7 +3107,7 @@ s390_expand_clrstr (rtx dst, rtx len)
 
       expand_end_loop ();
 
-      emit_insn (gen_short (dst, convert_to_mode (word_mode, count, 1)));
+      emit_insn (gen_clrstr_short (dst, convert_to_mode (Pmode, count, 1)));
       emit_label (end_label);
     }
 }
@@ -3154,10 +3118,6 @@ s390_expand_clrstr (rtx dst, rtx len)
 void
 s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
 {
-  rtx (*gen_short) (rtx, rtx, rtx) =
-    TARGET_64BIT ? gen_cmpmem_short_64 : gen_cmpmem_short_31;
-  rtx (*gen_long) (rtx, rtx, rtx, rtx) =
-    TARGET_64BIT ? gen_cmpmem_long_64 : gen_cmpmem_long_31;
   rtx (*gen_result) (rtx) =
     GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si;
 
@@ -3169,7 +3129,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
     {
       if (INTVAL (len) > 0)
         {
-          emit_insn (gen_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
+          emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
           emit_insn (gen_result (target));
         }
       else
@@ -3178,20 +3138,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
 
   else /* if (TARGET_MVCLE) */
     {
-      enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode;
-      enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode;
-      rtx reg0 = gen_reg_rtx (double_mode);
-      rtx reg1 = gen_reg_rtx (double_mode);
-
-      emit_move_insn (gen_highpart (single_mode, reg0),
-                     force_operand (XEXP (op0, 0), NULL_RTX));
-      emit_move_insn (gen_highpart (single_mode, reg1),
-                     force_operand (XEXP (op1, 0), NULL_RTX));
-
-      convert_move (gen_lowpart (single_mode, reg0), len, 1);
-      convert_move (gen_lowpart (single_mode, reg1), len, 1);
-
-      emit_insn (gen_long (reg0, reg1, reg0, reg1));
+      emit_insn (gen_cmpmem_long (op0, op1, convert_to_mode (Pmode, len, 1)));
       emit_insn (gen_result (target));
     }
 
@@ -3207,7 +3154,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
 
       mode = GET_MODE (len);
       if (mode == VOIDmode)
-        mode = word_mode;
+        mode = Pmode;
 
       type = lang_hooks.types.type_for_mode (mode, 1);
       if (!type)
@@ -3240,7 +3187,7 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
                                           make_tree (type, blocks),
                                           make_tree (type, const0_rtx)));
 
-      emit_insn (gen_short (op0, op1, GEN_INT (255)));
+      emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (255)));
       temp = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCSmode, 33), const0_rtx);
       temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
                        gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx);
@@ -3258,7 +3205,8 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
 
       expand_end_loop ();
 
-      emit_insn (gen_short (op0, op1, convert_to_mode (word_mode, count, 1)));
+      emit_insn (gen_cmpmem_short (op0, op1, 
+                                  convert_to_mode (Pmode, count, 1)));
       emit_label (end_label);
 
       emit_insn (gen_result (target));
index 9b3d009a7f2e67b2222297f6ccc706f7d878af82..1e1b08dea534f088a10294ba0e5f30dce663ca4e 100644 (file)
 ; Move a block that is up to 256 bytes in length.
 ; The block length is taken as (operands[2] % 256) + 1.
 
-(define_insn "movstr_short_64"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
-        (match_operand:BLK 1 "memory_operand" "Q,Q"))
-   (use (match_operand:DI 2 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch:DI 3 "=X,&a"))]
-  "TARGET_64BIT"
-{
-  switch (which_alternative)
-    {
-      case 0:
-       return "mvc\t%O0(%b2+1,%R0),%1";
-
-      case 1:
-       output_asm_insn ("bras\t%3,.+10", operands);
-       output_asm_insn ("mvc\t%O0(1,%R0),%1", operands);
-       return "ex\t%2,0(%3)";
-
-      default:
-        abort ();
-    }
-}
-  [(set_attr "op_type" "SS,NN")
-   (set_attr "type"    "cs,cs")
-   (set_attr "atype"   "*,agen")
-   (set_attr "length"  "*,14")])
+(define_expand "movstr_short"
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (match_operand:BLK 1 "memory_operand" ""))
+     (use (match_operand 2 "nonmemory_operand" ""))
+     (clobber (match_dup 3))])]
+  ""
+  "operands[3] = gen_rtx_SCRATCH (Pmode);")
 
-(define_insn "movstr_short_31"
+(define_insn "*movstr_short"
   [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
         (match_operand:BLK 1 "memory_operand" "Q,Q"))
-   (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch:SI 3 "=X,&a"))]
-  "!TARGET_64BIT"
+   (use (match_operand 2 "nonmemory_operand" "n,a"))
+   (clobber (match_scratch 3 "=X,&a"))]
+  "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
+   && GET_MODE (operands[3]) == Pmode"
 {
   switch (which_alternative)
     {
 
 ; Move a block of arbitrary length.
 
-(define_insn "movstr_long_64"
-  [(set (match_operand:TI 0 "register_operand" "=d")
-        (ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0")
-                            (lshiftrt:TI (match_dup 2) (const_int 64)))
-                   (const_int 64)))
-   (set (match_operand:TI 1 "register_operand" "=d")
-        (ashift:TI (plus:TI (match_operand:TI 3 "register_operand" "1")
-                            (lshiftrt:TI (match_dup 3) (const_int 64)))
-                   (const_int 64)))
-   (set (mem:BLK (subreg:DI (match_dup 2) 0))
-        (mem:BLK (subreg:DI (match_dup 3) 0)))
+(define_expand "movstr_long"
+  [(parallel
+    [(clobber (match_dup 2))
+     (clobber (match_dup 3))
+     (set (match_operand:BLK 0 "memory_operand" "")
+          (match_operand:BLK 1 "memory_operand" ""))
+     (use (match_operand 2 "general_operand" ""))
+     (use (match_dup 3))
+     (clobber (reg:CC 33))])]
+  ""
+{
+  enum machine_mode dword_mode = word_mode == DImode ? TImode : DImode;
+  rtx reg0 = gen_reg_rtx (dword_mode);
+  rtx reg1 = gen_reg_rtx (dword_mode);
+  rtx addr0 = gen_lowpart (Pmode, gen_highpart (word_mode, reg0));
+  rtx addr1 = gen_lowpart (Pmode, gen_highpart (word_mode, reg1));
+  rtx len0 = gen_lowpart (Pmode, reg0);
+  rtx len1 = gen_lowpart (Pmode, reg1);
+
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, reg0));
+  emit_move_insn (addr0, force_operand (XEXP (operands[0], 0), NULL_RTX));
+  emit_move_insn (len0, operands[2]);
+
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
+  emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
+  emit_move_insn (len1, operands[2]);
+
+  operands[0] = replace_equiv_address_nv (operands[0], addr0);
+  operands[1] = replace_equiv_address_nv (operands[1], addr1);
+  operands[2] = reg0;
+  operands[3] = reg1;
+})
+
+(define_insn "*movstr_long_64"
+  [(clobber (match_operand:TI 0 "register_operand" "=d"))
+   (clobber (match_operand:TI 1 "register_operand" "=d"))
+   (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
+        (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0)))
+   (use (match_dup 2))
+   (use (match_dup 3))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
   "mvcle\t%0,%1,0\;jo\t.-4"
    (set_attr "type"    "vs")
    (set_attr "length"  "8")])
 
-(define_insn "movstr_long_31"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0")
-                            (lshiftrt:DI (match_dup 2) (const_int 32)))
-                   (const_int 32)))
-   (set (match_operand:DI 1 "register_operand" "=d")
-        (ashift:DI (plus:DI (match_operand:DI 3 "register_operand" "1")
-                            (lshiftrt:DI (match_dup 3) (const_int 32)))
-                   (const_int 32)))
-   (set (mem:BLK (subreg:SI (match_dup 2) 0))
-        (mem:BLK (subreg:SI (match_dup 3) 0)))
+(define_insn "*movstr_long_31"
+  [(clobber (match_operand:DI 0 "register_operand" "=d"))
+   (clobber (match_operand:DI 1 "register_operand" "=d"))
+   (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
+        (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0)))
+   (use (match_dup 2))
+   (use (match_dup 3))
    (clobber (reg:CC 33))]
   "!TARGET_64BIT"
   "mvcle\t%0,%1,0\;jo\t.-4"
   "s390_expand_clrstr (operands[0], operands[1]); DONE;")
 
 ; Clear a block that is up to 256 bytes in length.
-; The block length is taken as (operands[2] % 256) + 1.
+; The block length is taken as (operands[1] % 256) + 1.
 
-(define_insn "clrstr_short_64"
+(define_expand "clrstr_short"
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand" "")
+          (const_int 0))
+     (use (match_operand 1 "nonmemory_operand" ""))
+     (clobber (match_dup 2))
+     (clobber (reg:CC 33))])]
+  ""
+  "operands[2] = gen_rtx_SCRATCH (Pmode);")
+
+(define_insn "*clrstr_short"
   [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
         (const_int 0))
-   (use (match_operand:DI 1 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch:DI 2 "=X,&a"))
+   (use (match_operand 1 "nonmemory_operand" "n,a"))
+   (clobber (match_scratch 2 "=X,&a"))
    (clobber (reg:CC 33))]
-  "TARGET_64BIT"
+  "(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
+   && GET_MODE (operands[2]) == Pmode"
 {
   switch (which_alternative)
     {
    (set_attr "atype"   "*,agen")
    (set_attr "length"  "*,14")])
 
-(define_insn "clrstr_short_31"
-  [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
-        (const_int 0))
-   (use (match_operand:SI 1 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch:SI 2 "=X,&a"))
-   (clobber (reg:CC 33))]
-  "!TARGET_64BIT"
+; Clear a block of arbitrary length.
+
+(define_expand "clrstr_long"
+  [(parallel
+    [(clobber (match_dup 1))
+     (set (match_operand:BLK 0 "memory_operand" "")
+          (const_int 0))
+     (use (match_operand 1 "general_operand" ""))
+     (use (match_dup 2))
+     (clobber (reg:CC 33))])]
+  ""
 {
-  switch (which_alternative)
-    {
-      case 0:
-       return "xc\t%O0(%b1+1,%R0),%0";
+  enum machine_mode dword_mode = word_mode == DImode ? TImode : DImode;
+  rtx reg0 = gen_reg_rtx (dword_mode);
+  rtx reg1 = gen_reg_rtx (dword_mode);
+  rtx addr0 = gen_lowpart (Pmode, gen_highpart (word_mode, reg0));
+  rtx len0 = gen_lowpart (Pmode, reg0);
 
-      case 1:
-       output_asm_insn ("bras\t%2,.+10", operands);
-       output_asm_insn ("xc\t%O0(1,%R0),%0", operands);
-       return "ex\t%1,0(%2)";
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, reg0));
+  emit_move_insn (addr0, force_operand (XEXP (operands[0], 0), NULL_RTX));
+  emit_move_insn (len0, operands[1]);
 
-      default:
-        abort ();
-    }
-}
-  [(set_attr "op_type" "SS,NN")
-   (set_attr "type"    "cs,cs")
-   (set_attr "atype"   "*,agen")
-   (set_attr "length"  "*,14")])
+  emit_move_insn (reg1, const0_rtx);
 
-; Clear a block of arbitrary length.
+  operands[0] = replace_equiv_address_nv (operands[0], addr0);
+  operands[1] = reg0;
+  operands[2] = reg1;
+})
 
-(define_insn "clrstr_long_64"
-  [(set (match_operand:TI 0 "register_operand" "=d")
-        (ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0")
-                            (lshiftrt:TI (match_dup 2) (const_int 64)))
-                   (const_int 64)))
-   (set (mem:BLK (subreg:DI (match_dup 2) 0))
+(define_insn "*clrstr_long_64"
+  [(clobber (match_operand:TI 0 "register_operand" "=d"))
+   (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
         (const_int 0))
+   (use (match_dup 2))
    (use (match_operand:TI 1 "register_operand" "d"))
    (clobber (reg:CC 33))]
   "TARGET_64BIT"
    (set_attr "type"    "vs")
    (set_attr "length"  "8")])
 
-(define_insn "clrstr_long_31"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-        (ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0")
-                            (lshiftrt:DI (match_dup 2) (const_int 32)))
-                   (const_int 32)))
-   (set (mem:BLK (subreg:SI (match_dup 2) 0))
+(define_insn "*clrstr_long_31"
+  [(clobber (match_operand:DI 0 "register_operand" "=d"))
+   (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
         (const_int 0))
+   (use (match_dup 2))
    (use (match_operand:DI 1 "register_operand" "d"))
    (clobber (reg:CC 33))]
   "!TARGET_64BIT"
 ; Compare a block that is up to 256 bytes in length.
 ; The block length is taken as (operands[2] % 256) + 1.
 
-(define_insn "cmpmem_short_64"
-  [(set (reg:CCS 33)
-        (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
-                     (match_operand:BLK 1 "memory_operand" "Q,Q")))
-   (use (match_operand:DI 2 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch:DI 3 "=X,&a"))]
-  "TARGET_64BIT"
-{
-  switch (which_alternative)
-    {
-      case 0:
-       return "clc\t%O0(%b2+1,%R0),%1";
-
-      case 1:
-       output_asm_insn ("bras\t%3,.+10", operands);
-       output_asm_insn ("clc\t%O0(1,%R0),%1", operands);
-       return "ex\t%2,0(%3)";
-
-      default:
-        abort ();
-    }
-}
-  [(set_attr "op_type" "SS,NN")
-   (set_attr "type"    "cs,cs")
-   (set_attr "atype"   "*,agen")
-   (set_attr "length"  "*,14")])
+(define_expand "cmpmem_short"
+  [(parallel
+    [(set (reg:CCS 33)
+          (compare:CCS (match_operand:BLK 0 "memory_operand" "")
+                       (match_operand:BLK 1 "memory_operand" "")))
+     (use (match_operand 2 "nonmemory_operand" ""))
+     (clobber (match_dup 3))])]
+  ""
+  "operands[3] = gen_rtx_SCRATCH (Pmode);")
 
-(define_insn "cmpmem_short_31"
+(define_insn "*cmpmem_short"
   [(set (reg:CCS 33)
         (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
                      (match_operand:BLK 1 "memory_operand" "Q,Q")))
-   (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
-   (clobber (match_scratch:SI 3 "=X,&a"))]
-  "!TARGET_64BIT"
+   (use (match_operand 2 "nonmemory_operand" "n,a"))
+   (clobber (match_scratch 3 "=X,&a"))]
+  "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
+   && GET_MODE (operands[3]) == Pmode"
 {
   switch (which_alternative)
     {
 
 ; Compare a block of arbitrary length.
 
-(define_insn "cmpmem_long_64"
+(define_expand "cmpmem_long"
+  [(parallel
+    [(clobber (match_dup 2))
+     (clobber (match_dup 3))
+     (set (reg:CCS 33)
+          (compare:CCS (match_operand:BLK 0 "memory_operand" "")
+                       (match_operand:BLK 1 "memory_operand" "")))
+     (use (match_operand 2 "general_operand" ""))
+     (use (match_dup 3))])]
+  ""
+{
+  enum machine_mode dword_mode = word_mode == DImode ? TImode : DImode;
+  rtx reg0 = gen_reg_rtx (dword_mode);
+  rtx reg1 = gen_reg_rtx (dword_mode);
+  rtx addr0 = gen_lowpart (Pmode, gen_highpart (word_mode, reg0));
+  rtx addr1 = gen_lowpart (Pmode, gen_highpart (word_mode, reg1));
+  rtx len0 = gen_lowpart (Pmode, reg0);
+  rtx len1 = gen_lowpart (Pmode, reg1);
+
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, reg0));
+  emit_move_insn (addr0, force_operand (XEXP (operands[0], 0), NULL_RTX));
+  emit_move_insn (len0, operands[2]);
+
+  emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
+  emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
+  emit_move_insn (len1, operands[2]);
+
+  operands[0] = replace_equiv_address_nv (operands[0], addr0);
+  operands[1] = replace_equiv_address_nv (operands[1], addr1);
+  operands[2] = reg0;
+  operands[3] = reg1;
+})
+
+(define_insn "*cmpmem_long_64"
   [(clobber (match_operand:TI 0 "register_operand" "=d"))
    (clobber (match_operand:TI 1 "register_operand" "=d"))
    (set (reg:CCS 33)
   [(set_attr "op_type" "RR")
    (set_attr "type"    "vs")])
 
-(define_insn "cmpmem_long_31"
+(define_insn "*cmpmem_long_31"
   [(clobber (match_operand:DI 0 "register_operand" "=d"))
    (clobber (match_operand:DI 1 "register_operand" "=d"))
    (set (reg:CCS 33)