OSDN Git Service

* Revamped multiply support for MIPS chips.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jun 1998 15:56:47 +0000 (15:56 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jun 1998 15:56:47 +0000 (15:56 +0000)
        * mips.c (extend_operator): New function.
        (highpart_shift_operator): Likewise.
        * mips.h: Declare new functions.
        (PREDICATE_CODES): Add support for new predicates.
        * mips.md (mulsi3 expander): Simplify.
        (mulsi_mult3): Add another constraint alternative.  Support
        3 operand multiply instructions as found on various mips
        parts.
        (mulsi3_r4650): Delete pattern, now handled by mulsi_mult3.
        (mul_acc_si): New pattern and associated splitters.
        (mulsidi3 expander): Rework to use mulsidi3_64bit and
        mulsidi3_internal.
        (umulsidi3): New expander.
        (mulsidi3_internal): Accept either sign or zero extended
        operands and generate code as appropriate appropriately.
        (mulsidi3_64bit): Similarly.
        (smulsi3_highpart): Turn into an expander and generate code
        to match new patterns.
        (umulsi3_highpart): Likewise.
        (xmulsi3_highpart_internal): New pattern.
        (maddi patterns): Delete.  Replace with:
        (mul_acc_di, mul-acc_64bit_di): New patterns.

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

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md

index b879382..a5ebd22 100644 (file)
@@ -1,3 +1,30 @@
+Mon Jun  8 16:54:12 1998  Ken Raeburn   <raeburn@cygnus.com>
+                          Jeff Law      <law@cygnus.com>
+
+       * Revamped multiply support for MIPS chips.
+       * mips.c (extend_operator): New function.
+       (highpart_shift_operator): Likewise.
+       * mips.h: Declare new functions.
+       (PREDICATE_CODES): Add support for new predicates.
+       * mips.md (mulsi3 expander): Simplify.
+       (mulsi_mult3): Add another constraint alternative.  Support
+       3 operand multiply instructions as found on various mips
+       parts.
+       (mulsi3_r4650): Delete pattern, now handled by mulsi_mult3.
+       (mul_acc_si): New pattern and associated splitters.
+       (mulsidi3 expander): Rework to use mulsidi3_64bit and
+       mulsidi3_internal.
+       (umulsidi3): New expander.
+       (mulsidi3_internal): Accept either sign or zero extended
+       operands and generate code as appropriate appropriately.
+       (mulsidi3_64bit): Similarly.
+       (smulsi3_highpart): Turn into an expander and generate code
+       to match new patterns.
+       (umulsi3_highpart): Likewise.
+       (xmulsi3_highpart_internal): New pattern.
+       (maddi patterns): Delete.  Replace with:
+       (mul_acc_di, mul-acc_64bit_di): New patterns.
+
 Mon Jun  8 14:16:15 EDT 1998  Andrew MacLeod  <amacleod@cygnus.com>
 
        * eh-common.h: Remove NEW_EH_MODEL compile time flag, and replace with
index aad3c81..e10c048 100644 (file)
@@ -8408,3 +8408,29 @@ machine_dependent_reorg (first)
      constants table, we don't need to output the constant in the real
      constant table, but we have no way to prevent that.  */
 }
+
+/* Return nonzero if X is a SIGN or ZERO extend operator.  */
+int
+extend_operator (x, mode)
+     rtx x;
+     enum machine_mode mode;
+{
+  enum rtx_code code = GET_CODE (x);
+  return code == SIGN_EXTEND || code == ZERO_EXTEND;
+}
+
+/* Accept any operator that can be used to shift the high half of the
+   input value to the lower half, suitable for truncation.  The
+   remainder (the lower half of the input, and the upper half of the
+   output) will be discarded.  */
+int
+highpart_shift_operator (x, mode)
+     rtx x;
+     enum machine_mode mode;
+{
+  enum rtx_code code = GET_CODE (x);
+  return (code == LSHIFTRT
+         || code == ASHIFTRT
+         || code == ROTATERT
+         || code == ROTATE);
+}
index c53d452..fb6f051 100644 (file)
@@ -260,6 +260,8 @@ extern int          se_uns_arith_operand ();
 extern int             se_arith_operand ();
 extern int             se_nonmemory_operand ();
 extern int             se_nonimmediate_operand ();
+extern int              extend_operator ();
+extern int              highpart_shift_operator ();
 extern int             m16_uimm3_b ();
 extern int             m16_simm4_1 ();
 extern int             m16_nsimm4_1 ();
@@ -3641,7 +3643,10 @@ while (0)
                                  REG, SIGN_EXTEND }},                  \
   {"se_nonimmediate_operand",   { SUBREG, REG, MEM, SIGN_EXTEND }},    \
   {"consttable_operand",       { LABEL_REF, SYMBOL_REF, CONST_INT,     \
-                                 CONST_DOUBLE, CONST }},
+                                 CONST_DOUBLE, CONST }},               \
+  {"extend_operator",           { SIGN_EXTEND, ZERO_EXTEND }},          \
+  {"highpart_shift_operator",   { ASHIFTRT, LSHIFTRT, ROTATERT, ROTATE }},
+
 
 \f
 /* If defined, a C statement to be executed just prior to the
index 4155dd1..595362d 100644 (file)
    (set_attr "mode"    "SF")
    (set_attr "length"  "2")])  ;; mul.s + nop
 
+
 ;; ??? The R4000 (only) has a cpu bug.  If a double-word shift executes while
 ;; a multiply is in progress, it may give an incorrect result.  Avoid
 ;; this by keeping the mflo with the mult on the R4000.
 {
   if (GENERATE_MULT3)
     emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2]));
-  else if (TARGET_MAD)
-    emit_insn (gen_mulsi3_r4650 (operands[0], operands[1], operands[2]));
   else if (mips_cpu != PROCESSOR_R4000 || TARGET_MIPS16)
     emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2]));
   else
 }")
 
 (define_insn "mulsi3_mult3"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (mult:SI (match_operand:SI 1 "register_operand" "d")
-                (match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=l"))
-   (clobber (match_scratch:SI 5 "=a"))]
+  [(set (match_operand:SI 0 "register_operand" "=d,?l")
+       (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+                (match_operand:SI 2 "register_operand" "d,d")))
+   (clobber (match_scratch:SI 3 "=h,h"))
+   (clobber (match_scratch:SI 4 "=l,X"))
+   (clobber (match_scratch:SI 5 "=a,a"))]
   "GENERATE_MULT3"
-  "mult\\t%0,%1,%2"
+  "*
+{
+  if (which_alternative == 1)
+    return \"mult\\t%1,%2\";
+  if (TARGET_MAD)
+    return \"mul\\t%0,%1,%2\";
+  return \"mult\\t%0,%1,%2\";
+}"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"  "1")])
    (set_attr "mode"    "SI")
    (set_attr "length"  "3")])          ;; mult + mflo + delay
 
-(define_insn "mulsi3_r4650"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (mult:SI (match_operand:SI 1 "register_operand" "d")
-                (match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=l"))
-   (clobber (match_scratch:SI 5 "=a"))]
-  "TARGET_MAD"
-  "mul\\t%0,%1,%2"
-  [(set_attr "type"    "imul")
+;; The all-d alternative is needed because the combiner will find this
+;; pattern and then register alloc/reload will move registers around to
+;; make them fit, and we don't want to trigger unnecessary loads to LO.
+;; For the moment, that seems to mostly disable the "macc" instruction
+;; though; some "?" marks may be needed.  Using "*d" helps, but causes
+;; stack spills in some cases.
+(define_insn "*mul_acc_si"
+  [(set (match_operand:SI 0 "register_operand" "=l,d,d")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
+                         (match_operand:SI 2 "register_operand" "d,d,d"))
+                (match_operand:SI 3 "register_operand" "0,l,d")))
+   (clobber (match_scratch:SI 4 "=h,h,h"))
+   (clobber (match_scratch:SI 5 "=X,3,l"))
+   (clobber (match_scratch:SI 6 "=a,a,a"))
+   (clobber (match_scratch:SI 7 "=X,X,d"))]
+  "GENERATE_MADD"
+  "*
+{
+  static char *const madd[] = { \"madd\\t%1,%2\",    \"madd\\t%0,%1,%2\" };
+  static char *const macc[] = { \"macc\\t$0,%1,%2\", \"macc\\t%0,%1,%2\" };
+  if (which_alternative == 2)
+    return \"#\";
+  return madd[which_alternative];
+}"
+  [(set_attr "type"    "imul,imul,multi")
    (set_attr "mode"    "SI")
-   (set_attr "length"  "1")])
+   (set_attr "length"  "1,1,2")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                         (match_operand:SI 2 "register_operand" ""))
+                (match_operand:SI 3 "register_operand" "")))
+   (clobber (match_scratch:SI 4 ""))
+   (clobber (match_scratch:SI 5 ""))
+   (clobber (match_scratch:SI 6 ""))
+   (clobber (match_scratch:SI 7 ""))]
+  "reload_completed && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[3]))"
+  [(parallel [(set (match_dup 7)
+                  (mult:SI (match_dup 1) (match_dup 2)))
+             (clobber (match_dup 4))
+             (clobber (match_dup 5))
+             (clobber (match_dup 6))])
+   (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 3)))]
+  "")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+       (minus:SI (match_operand:SI 1 "register_operand" "")
+                 (mult:SI (match_operand:SI 2 "register_operand" "")
+                          (match_operand:SI 3 "register_operand" ""))))
+   (clobber (match_scratch:SI 4 ""))
+   (clobber (match_scratch:SI 5 ""))
+   (clobber (match_scratch:SI 6 ""))
+   (clobber (match_scratch:SI 7 ""))]
+  "reload_completed && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[1]))"
+  [(parallel [(set (match_dup 7)
+                  (mult:SI (match_dup 2) (match_dup 3)))
+             (clobber (match_dup 4))
+             (clobber (match_dup 5))
+             (clobber (match_dup 6))])
+   (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 7)))]
+  "")
 
 (define_expand "muldi3"
   [(set (match_operand:DI 0 "register_operand" "=l")
    (clobber (match_scratch:DI 3 "=h"))
    (clobber (match_scratch:DI 4 "=a"))]
   "TARGET_64BIT"
+
   "
 {
   if (GENERATE_MULT3 || mips_cpu == PROCESSOR_R4000 || TARGET_MIPS16)
   ""
   "
 {
+  rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx);
   if (TARGET_64BIT)
-    emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2]));
+    emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2],
+                                  dummy, dummy));
   else
-    emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2]));
+    emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2],
+                                     dummy, dummy));
   DONE;
 }")
 
-(define_insn "mulsidi3_internal"
-  [(set (match_operand:DI 0 "register_operand" "=x")
-       (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-                (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:SI 3 "=a"))]
-  "!TARGET_64BIT"
-  "mult\\t%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")
-   (set_attr "length"  "1")])
-
-(define_insn "mulsidi3_64bit"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-                (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=h"))]
-  "TARGET_64BIT"
-  "mult\\t%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")
-   (set_attr "length"  "1")])
-
-(define_insn "smulsi3_highpart"
-  [(set (match_operand:SI 0 "register_operand" "=h")
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-                              (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
-                     (const_int 32))))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
-  ""
-  "mult\\t%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")
-   (set_attr "length"  "1")])
-
 (define_expand "umulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=x")
        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
   ""
   "
 {
+  rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx);
   if (TARGET_64BIT)
-    emit_insn (gen_umulsidi3_64bit (operands[0], operands[1], operands[2]));
+    emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2],
+                                  dummy, dummy));
   else
-    emit_insn (gen_umulsidi3_internal (operands[0], operands[1], operands[2]));
+    emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2],
+                                     dummy, dummy));
   DONE;
 }")
 
-(define_insn "umulsidi3_internal"
+(define_insn "mulsidi3_internal"
   [(set (match_operand:DI 0 "register_operand" "=x")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-                (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:SI 3 "=a"))]
-  "!TARGET_64BIT"
-  "multu\\t%1,%2"
+       (mult:DI (match_operator:DI 3 "extend_operator"
+                                   [(match_operand:SI 1 "register_operand" "d")])
+                (match_operator:DI 4 "extend_operator"
+                                   [(match_operand:SI 2 "register_operand" "d")])))
+   (clobber (match_scratch:SI 5 "=a"))]
+  "!TARGET_64BIT && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mult\\t%1,%2\";
+  return \"multu\\t%1,%2\";
+}"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"  "1")])
 
-(define_insn "umulsidi3_64bit"
+(define_insn "mulsidi3_64bit"
   [(set (match_operand:DI 0 "register_operand" "=a")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-                (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=h"))]
-  "TARGET_64BIT"
-  "multu\\t%1,%2"
+       (mult:DI (match_operator:DI 3 "extend_operator"
+                                   [(match_operand:SI 1 "register_operand" "d")])
+                (match_operator:DI 4 "extend_operator"
+                                   [(match_operand:SI 2 "register_operand" "d")])))
+   (clobber (match_scratch:DI 5 "=l"))
+   (clobber (match_scratch:DI 6 "=h"))]
+  "TARGET_64BIT && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mult\\t%1,%2\";
+  return \"multu\\t%1,%2\";
+}"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"  "1")])
 
-(define_insn "umulsi3_highpart"
+;; _highpart patterns
+(define_expand "smulsi3_highpart"
+  [(set (match_operand:SI 0 "register_operand" "=h")
+       (truncate:SI
+        (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+                              (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
+                     (const_int 32))))]
+  ""
+  "
+{
+  rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx);
+  rtx dummy2 = gen_rtx_LSHIFTRT (DImode, const0_rtx, const0_rtx);
+  rtx (*genfn)() = gen_xmulsi3_highpart_internal;
+  emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
+                      dummy, dummy2));
+  DONE;
+}")
+
+(define_expand "umulsi3_highpart"
   [(set (match_operand:SI 0 "register_operand" "=h")
        (truncate:SI
         (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
                               (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))
-                     (const_int 32))))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+                     (const_int 32))))]
   ""
-  "multu\\t%1,%2"
+  "
+{
+  rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx);
+  rtx dummy2 = gen_rtx_LSHIFTRT (DImode, const0_rtx, const0_rtx);
+  rtx (*genfn)() = gen_xmulsi3_highpart_internal;
+  emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
+                      dummy, dummy2));
+  DONE;
+}")
+
+(define_insn "xmulsi3_highpart_internal"
+  [(set (match_operand:SI 0 "register_operand" "=h")
+       (truncate:SI
+        (match_operator:DI 5 "highpart_shift_operator"
+                           [(mult:DI (match_operator:DI 3 "extend_operator"
+                                                        [(match_operand:SI 1 "register_operand" "d")])
+                                     (match_operator:DI 4 "extend_operator"
+                                                        [(match_operand:SI 2 "register_operand" "d")]))
+                            (const_int 32)])))
+   (clobber (match_scratch:SI 6 "=l"))
+   (clobber (match_scratch:SI 7 "=a"))]
+  "GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mult\\t%1,%2\";
+  else
+    return \"multu\\t%1,%2\";
+}"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"  "1")])
                 (match_dup 0)))
    (clobber (match_scratch:SI 3 "=h"))
    (clobber (match_scratch:SI 4 "=a"))]
-  "TARGET_MAD || GENERATE_MADD"
-  "*
-{
-  if (TARGET_MAD)
-    return \"mad\\t%1,%2\";
-  else
-    return \"madd\\t%1,%2\";
-}"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")
-   (set_attr "length"   "1")])
-
-(define_insn "maddi"
-  [(set (match_operand:DI 0 "register_operand" "+x")
-       (plus:DI (mult:DI (sign_extend:DI
-                          (match_operand:SI 1 "register_operand" "d"))
-                         (sign_extend:DI
-                          (match_operand:SI 2 "register_operand" "d")))
-                (match_dup 0)))
-   (clobber (match_scratch:SI 3 "=a"))]
-  "TARGET_MAD && ! TARGET_64BIT"
-  "mad\\t%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")
-   (set_attr "length"   "1")])
-
-(define_insn "maddi_64bit"
-  [(set (match_operand:DI 0 "register_operand" "+a")
-       (plus:DI (mult:DI (sign_extend:DI
-                          (match_operand:SI 1 "register_operand" "d"))
-                         (sign_extend:DI
-                          (match_operand:SI 2 "register_operand" "d")))
-                (match_dup 0)))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=h"))]
-  "TARGET_MAD && TARGET_64BIT"
+  "TARGET_MAD"
   "mad\\t%1,%2"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"   "1")])
 
-(define_insn "umaddi"
+(define_insn "*mul_acc_di"
   [(set (match_operand:DI 0 "register_operand" "+x")
-       (plus:DI (mult:DI (zero_extend:DI
-                          (match_operand:SI 1 "register_operand" "d"))
-                         (zero_extend:DI
-                          (match_operand:SI 2 "register_operand" "d")))
+       (plus:DI (mult:DI (match_operator:DI 3 "extend_operator"
+                          [(match_operand:SI 1 "register_operand" "d")])
+                         (match_op_dup:DI 3
+                          [(match_operand:SI 2 "register_operand" "d")]))
                 (match_dup 0)))
-   (clobber (match_scratch:SI 3 "=a"))]
+   (clobber (match_scratch:SI 4 "=a"))]
   "TARGET_MAD && ! TARGET_64BIT"
-  "madu\\t%1,%2"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mad\\t%1,%2\";
+  else
+    return \"madu\\t%1,%2\";
+}"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"   "1")])
 
-(define_insn "umaddi_64bit"
+(define_insn "*mul_acc_64bit_di"
   [(set (match_operand:DI 0 "register_operand" "+a")
-       (plus:DI (mult:DI (zero_extend:DI
-                          (match_operand:SI 1 "register_operand" "d"))
-                         (zero_extend:DI
-                          (match_operand:SI 2 "register_operand" "d")))
+       (plus:DI (mult:DI (match_operator:DI 3 "extend_operator"
+                          [(match_operand:SI 1 "register_operand" "d")])
+                         (match_op_dup:DI 3
+                          [(match_operand:SI 2 "register_operand" "d")]))
                 (match_dup 0)))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=h"))]
+   (clobber (match_scratch:DI 4 "=l"))
+   (clobber (match_scratch:DI 5 "=h"))]
   "TARGET_MAD && TARGET_64BIT"
-  "madu\\t%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")
-   (set_attr "length"   "1")])
-
-(define_insn "madd3"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
-                         (match_operand:SI 2 "register_operand" "d"))
-                (match_operand:SI 3 "register_operand" "l")))
-   (clobber (match_scratch:SI 4 "=l"))
-   (clobber (match_scratch:SI 5 "=h"))
-   (clobber (match_scratch:SI 6 "=a"))]
-  "GENERATE_MADD"
-  "madd\\t%0,%1,%2"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"mad\\t%1,%2\";
+  else
+    return \"madu\\t%1,%2\";
+}"
   [(set_attr "type"    "imul")
    (set_attr "mode"    "SI")
    (set_attr "length"   "1")])