diff mbox

Update MIPS DSP madd, maddu, msub, msubu, mult, multu

Message ID 7C6479EB2BF52547AC332FD6034646DA3017F895@exchdb02.mips.com
State New
Headers show

Commit Message

Fu, Chao-Ying Oct. 29, 2010, 1:03 a.m. UTC
> > Looks good.  My main concern is that the patch as-is introduces
> > a dependency on bleeding-edge binutils.  That's not such a problem
> > for cases where the user has explicitly called a
> > __builtin_*() function
> > in rev1 code, because that simply didn't work before.  But it
> > is a problem
> > for cases where the compiler is automatically using these
> > instructions.
> > You'll get assembler errors when compiling ordinary C code,
> > which never
> > looks good.
> >
> > I think we need to add a configure-time check to see whether the
> > assembler has your patch.  There are quite a few existing examples
> > of this.  Then we should introduce a new macro such as:
> >
> >     ISA_HAS_DSP_MULT
> >
> > This macro can be defined to ISA_HAS_DSP if the assembler
> has your fix
> > and ISA_HAS_DSPR2 otherwise.
> >
>
>   I will update my patch to have a configure-time check and
> ues ISA_HAS_DSP_MULT.
> Thanks a lot!
>
  As you suggest, here is the revised patch.  These 6 instructions are moved to DSPr1, so that
the corresponding builtin-funcitons can be called when "-mdsp" is used.
The destination register may be hilo or four DSP accumulators, depending on
the register constraint "ka" that depends on ISA_HAS_DSP_MULT.
And ISA_HAS_DSP_MULT is based on HAVE_AS_DSP_REV1_MULT from configuration-time.
I restore the test of dspr2-MULT.c and dspr2-MULTU.c to use -mdspr2, since -mdspr2 definitely
can trigger the usage of all four accumulators.

  I lightly test it with the old assembler and the new assembler by running
"mips.exp" for the mips-sde-elf target (mips32r2).  No new failures.

  Ok to commit?  Thanks a lot!

Regards,
Chao-ying

gcc/ChangeLog
2010-10-28  Chao-ying Fu  <fu@mips.com>

        * configure.ac: Test assembler support for DSP Rev1 mult.
        * configure: Regenerate.
        * config.in: Regenerate.
        * config/mips/mips.h (ISA_HAS_DSP_MULT): New define.
        * config/mips/mips.c (mips_builtins): Move madd, maddu, msub, msubu,
        mult, multu from dspr2_32 to dsp_32.
        * config/mips/mips-dsp.md (mips_mult<u>, mips_madd<u>, mips_msub<u>):
        New define_expand patterns.
        * config/mips/constraints.md (ka): Update the constraint to test
        ISA_HAS_DSP_MULT instead of ISA_HAS_DSPR2.
        * config/mips/mips-dspr2.md (mips_madd<u>, mips_msub<u>, mips_mult,
        mips_multu): Delete.
        * config/mips/mips.md (<u>mulsidi3_32bit): Change target constraint to "ka".
        Remove !ISA_HAS_DSPR2.
        Emit the accumulator destination when ISA_HAS_DSP_MULT.
        (<u>msubsidi4): Test ISA_HAS_DSP.
        Emit the accumulator destination when ISA_HAS_DSP_MULT.
        (<u>maddsidi4): Likewise.

        * doc/extend.texi (MIPS DSP Built-in Functions): Move madd, maddu,
        msub, msubu, mult, multu built-in functions from DSP r2 to DSP r1.

gcc/testsuite/ChangeLog
2010-10-28  Chao-ying Fu  <fu@mips.com>

        * gcc.target/mips/mips32-dsp.c: Add tests for madd, maddu, msub,
        msubu, mult, multu.
        * gcc.target/mips/mips32-dsp-run.c: Likewise.

Comments

Richard Sandiford Oct. 30, 2010, 9:07 a.m. UTC | #1
"Fu, Chao-Ying" <fu@mips.com> writes:
>> > Looks good.  My main concern is that the patch as-is introduces
>> > a dependency on bleeding-edge binutils.  That's not such a problem
>> > for cases where the user has explicitly called a
>> > __builtin_*() function
>> > in rev1 code, because that simply didn't work before.  But it
>> > is a problem
>> > for cases where the compiler is automatically using these
>> > instructions.
>> > You'll get assembler errors when compiling ordinary C code,
>> > which never
>> > looks good.
>> >
>> > I think we need to add a configure-time check to see whether the
>> > assembler has your patch.  There are quite a few existing examples
>> > of this.  Then we should introduce a new macro such as:
>> >
>> >     ISA_HAS_DSP_MULT
>> >
>> > This macro can be defined to ISA_HAS_DSP if the assembler
>> has your fix
>> > and ISA_HAS_DSPR2 otherwise.
>> >
>>
>>   I will update my patch to have a configure-time check and
>> ues ISA_HAS_DSP_MULT.
>> Thanks a lot!
>>
>   As you suggest, here is the revised patch.  These 6 instructions are moved to DSPr1, so that
> the corresponding builtin-funcitons can be called when "-mdsp" is used.
> The destination register may be hilo or four DSP accumulators, depending on
> the register constraint "ka" that depends on ISA_HAS_DSP_MULT.
> And ISA_HAS_DSP_MULT is based on HAVE_AS_DSP_REV1_MULT from configuration-time.
> I restore the test of dspr2-MULT.c and dspr2-MULTU.c to use -mdspr2, since -mdspr2 definitely
> can trigger the usage of all four accumulators.

The problem with this is that the condition on the expander:

+(define_expand "mips_mult<u>"
+  [(set (match_operand:DI 0 "register_operand")
+       (mult:DI
+        (any_extend:DI (match_operand:SI 1 "register_operand"))
+        (any_extend:DI (match_operand:SI 2 "register_operand"))))]
+  "ISA_HAS_DSP && !TARGET_64BIT")

doesn't match the condition on the associated insn:

 (define_insn "<u>mulsidi3_32bit"
-  [(set (match_operand:DI 0 "register_operand" "=x")
+  [(set (match_operand:DI 0 "register_operand" "=ka")
        (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
                 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
-  "!TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DSPR2"
-  "mult<u>\t%1,%2"
+  "!TARGET_64BIT && !TARGET_FIX_R4000"
...

Note the !TARGET_FIX_R4000.  It might not make much sense, but there's
nothing stopping someone from using -mdsp and -mfix-r4000 together.
Although we _could_ either reject the combination or force MASK_FIX_R4000
to false, that would set a bad precendent.  In general, -mfix-* flags
should work "on top of" whatever ISA mode is selected.

However, I like your idea of making the builtin functions available in rev1
regardless of whether the assembler supports them, and falling back on the
single accumulator if necessary.  It seems reasonable to use:

  "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP)"

here, with a comment:

;; As well as being named patterns, these instructions are used by the
;; __builtin_mips_mult<u>() functions.  We must always make those functions
;; available if !TARGET_64BIT && ISA_HAS_DSP.

Also, now that you've merged the two mult define_insns (a good step,
thanks), there's no need for the mips_mult<u> expander.  Just add:

#define CODE_FOR_mips_mult CODE_FOR_mulsidi3_32bit
#define CODE_FOR_mips_multu CODE_FOR_umulsidi3_32bit

to the builtins code in mips.c.  Similarly, <u>maddsidi4 and
<u>msubsidi4 are now named patterns (which wasn't true when
the DSP code was originally added), so we can do the same
thing for mips_madd<u> and mips_msub<u>.

A similar problem (though not in this case a correctness problem)
occurs with:

-  "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2)"
+  "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSP)"

GENERATE_MADD_MSUB is defined as:

#define GENERATE_MADD_MSUB      (ISA_HAS_MADD_MSUB && !TUNE_74K)

yet the 74k is a DSP target.  The old condition could be justified
on the basis that, if you're tuning for the 74k but have all four
accumulators available, it's better to use these instructions anyway.
After the patch, we might use the instructions when tuning for the
74k and when only one accumulator is available, which is exactly
the case that GENERATE_MADD_MSUB was trying to avoid.

Still, I suppose -mtune=74k -mdsp, as opposed to -mtune=74k -mdspr2,
is probably a niche combination, and I can't think of a good way out.
I suppose we can just hope that anyone using that combination is
prepared to upgrade their binutils or live the possible drop in
performance.

So, let's go with the MADD_MSUB conditions in your patch, but add:

;; As well as being named patterns, these instructions are used by the
;; __builtin_mips_madd<u>() functions.  We must always make those functions
;; available if !TARGET_64BIT && ISA_HAS_DSP.
;;
;; This leads to a slight inconsistency.  We honor any tuning overrides
;; in GENERATE_MADD_MSUB for -mno-dsp, but always ignore them for -mdsp,
;; even if !ISA_HAS_DSP_MULT.

before <u>maddsidi4, and:

;; See the comment above <u>maddsidi4 for the relationship between
;; ISA_HAS_DSP and ISA_HAS_DSP_MULT.

above <u>msubsidi4.

Also, a minor nit, but let's call the macro HAVE_AS_DSPR1_MULT,
for consistency with -mdspr2, ISA_HAS_DSPR2, etc.

Richard
diff mbox

Patch

Index: gcc45/gcc/gcc/config/mips/mips.c
===================================================================
--- gcc45.orig/gcc/gcc/config/mips/mips.c       2010-10-28 16:08:27.236970000 -0700
+++ gcc45/gcc/gcc/config/mips/mips.c    2010-10-28 16:24:12.906976000 -0700
@@ -12928,17 +12928,17 @@  static const struct mips_builtin_descrip
   DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, dsp_32),
   DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, dsp_32),
   DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, dsp_32),
+  DIRECT_BUILTIN (madd, MIPS_DI_FTYPE_DI_SI_SI, dsp_32),
+  DIRECT_BUILTIN (maddu, MIPS_DI_FTYPE_DI_USI_USI, dsp_32),
+  DIRECT_BUILTIN (msub, MIPS_DI_FTYPE_DI_SI_SI, dsp_32),
+  DIRECT_BUILTIN (msubu, MIPS_DI_FTYPE_DI_USI_USI, dsp_32),
+  DIRECT_BUILTIN (mult, MIPS_DI_FTYPE_SI_SI, dsp_32),
+  DIRECT_BUILTIN (multu, MIPS_DI_FTYPE_USI_USI, dsp_32),

   /* The following are for the MIPS DSP ASE REV 2 (32-bit only).  */
   DIRECT_BUILTIN (dpa_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
   DIRECT_BUILTIN (dps_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
-  DIRECT_BUILTIN (madd, MIPS_DI_FTYPE_DI_SI_SI, dspr2_32),
-  DIRECT_BUILTIN (maddu, MIPS_DI_FTYPE_DI_USI_USI, dspr2_32),
-  DIRECT_BUILTIN (msub, MIPS_DI_FTYPE_DI_SI_SI, dspr2_32),
-  DIRECT_BUILTIN (msubu, MIPS_DI_FTYPE_DI_USI_USI, dspr2_32),
   DIRECT_BUILTIN (mulsa_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
-  DIRECT_BUILTIN (mult, MIPS_DI_FTYPE_SI_SI, dspr2_32),
-  DIRECT_BUILTIN (multu, MIPS_DI_FTYPE_USI_USI, dspr2_32),
   DIRECT_BUILTIN (dpax_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
   DIRECT_BUILTIN (dpsx_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
   DIRECT_BUILTIN (dpaqx_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32),
Index: gcc45/gcc/gcc/config/mips/mips-dsp.md
===================================================================
--- gcc45.orig/gcc/gcc/config/mips/mips-dsp.md  2010-10-28 16:08:27.369997000 -0700
+++ gcc45/gcc/gcc/config/mips/mips-dsp.md       2010-10-28 16:24:12.915975000 -0700
@@ -1181,3 +1181,25 @@ 
   "%*bposge%1\t%0%/"
   [(set_attr "type"    "branch")])

+(define_expand "mips_mult<u>"
+  [(set (match_operand:DI 0 "register_operand")
+       (mult:DI
+        (any_extend:DI (match_operand:SI 1 "register_operand"))
+        (any_extend:DI (match_operand:SI 2 "register_operand"))))]
+  "ISA_HAS_DSP && !TARGET_64BIT")
+
+(define_expand "mips_madd<u>"
+  [(set (match_operand:DI 0 "register_operand")
+       (plus:DI
+        (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
+                 (any_extend:DI (match_operand:SI 3 "register_operand")))
+        (match_operand:DI 1 "register_operand")))]
+  "ISA_HAS_DSP && !TARGET_64BIT")
+
+(define_expand "mips_msub<u>"
+  [(set (match_operand:DI 0 "register_operand")
+       (minus:DI
+        (match_operand:DI 1 "register_operand")
+        (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
+                 (any_extend:DI (match_operand:SI 3 "register_operand")))))]
+  "ISA_HAS_DSP && !TARGET_64BIT")
Index: gcc45/gcc/gcc/config/mips/constraints.md
===================================================================
--- gcc45.orig/gcc/gcc/config/mips/constraints.md       2010-10-28 16:08:28.110890000 -0700
+++ gcc45/gcc/gcc/config/mips/constraints.md    2010-10-28 16:24:12.919980000 -0700
@@ -86,8 +86,8 @@ 

 ;; Registers that can be used as the target of multiply-accumulate
 ;; instructions.  The core MIPS32 ISA provides a hi/lo madd,
-;; but the DSPr2 version allows any accumulator target.
-(define_register_constraint "ka" "ISA_HAS_DSPR2 ? ACC_REGS : MD_REGS")
+;; but the DSP version allows any accumulator target.
+(define_register_constraint "ka" "ISA_HAS_DSP_MULT ? ACC_REGS : MD_REGS")

 (define_constraint "kf"
   "@internal"
Index: gcc45/gcc/gcc/config/mips/mips-dspr2.md
===================================================================
--- gcc45.orig/gcc/gcc/config/mips/mips-dspr2.md        2010-10-28 16:08:28.114896000 -0700
+++ gcc45/gcc/gcc/config/mips/mips-dspr2.md     2010-10-28 16:24:12.948997000 -0700
@@ -224,22 +224,6 @@ 
   [(set_attr "type"    "imadd")
    (set_attr "mode"    "SI")])

-(define_expand "mips_madd<u>"
-  [(set (match_operand:DI 0 "register_operand")
-       (plus:DI
-        (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
-                 (any_extend:DI (match_operand:SI 3 "register_operand")))
-        (match_operand:DI 1 "register_operand")))]
-  "ISA_HAS_DSPR2 && !TARGET_64BIT")
-
-(define_expand "mips_msub<u>"
-  [(set (match_operand:DI 0 "register_operand")
-       (minus:DI
-        (match_operand:DI 1 "register_operand")
-        (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
-                 (any_extend:DI (match_operand:SI 3 "register_operand")))))]
-  "ISA_HAS_DSPR2 && !TARGET_64BIT")
-
 (define_insn "mulv2hi3"
   [(parallel
     [(set (match_operand:V2HI 0 "register_operand" "=d")
@@ -320,26 +304,6 @@ 
   [(set_attr "type"    "imadd")
    (set_attr "mode"    "SI")])

-(define_insn "mips_mult"
-  [(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"))))]
-  "ISA_HAS_DSPR2 && !TARGET_64BIT"
-  "mult\t%q0,%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")])
-
-(define_insn "mips_multu"
-  [(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"))))]
-  "ISA_HAS_DSPR2 && !TARGET_64BIT"
-  "multu\t%q0,%1,%2"
-  [(set_attr "type"    "imul")
-   (set_attr "mode"    "SI")])
-
 (define_insn "mips_precr_qb_ph"
   [(set (match_operand:V4QI 0 "register_operand" "=d")
        (unspec:V4QI [(match_operand:V2HI 1 "reg_or_0_operand" "dYG")
Index: gcc45/gcc/gcc/config/mips/mips.md
===================================================================
--- gcc45.orig/gcc/gcc/config/mips/mips.md      2010-10-28 16:08:28.195880000 -0700
+++ gcc45/gcc/gcc/config/mips/mips.md   2010-10-28 17:33:26.766662000 -0700
@@ -1732,11 +1732,16 @@ 
 })

 (define_insn "<u>mulsidi3_32bit"
-  [(set (match_operand:DI 0 "register_operand" "=x")
+  [(set (match_operand:DI 0 "register_operand" "=ka")
        (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
                 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
-  "!TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DSPR2"
-  "mult<u>\t%1,%2"
+  "!TARGET_64BIT && !TARGET_FIX_R4000"
+{
+  if (ISA_HAS_DSP_MULT)
+    return "mult<u>\t%q0,%1,%2";
+  else
+    return "mult<u>\t%1,%2";
+}
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])

@@ -1863,9 +1868,9 @@ 
           (mult:DI
              (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
              (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
-  "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2)"
+  "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSP)"
 {
-  if (ISA_HAS_DSPR2)
+  if (ISA_HAS_DSP_MULT)
     return "msub<u>\t%q0,%1,%2";
   else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB)
     return "msub<u>\t%1,%2";
@@ -2042,12 +2047,12 @@ 
         (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
                  (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
         (match_operand:DI 3 "register_operand" "0")))]
-  "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2)
+  "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSP)
    && !TARGET_64BIT"
 {
   if (TARGET_MAD)
     return "mad<u>\t%1,%2";
-  else if (ISA_HAS_DSPR2)
+  else if (ISA_HAS_DSP_MULT)
     return "madd<u>\t%q0,%1,%2";
   else if (GENERATE_MADD_MSUB || TARGET_MIPS5500)
     return "madd<u>\t%1,%2";
Index: gcc45/gcc/gcc/testsuite/gcc.target/mips/mips32-dsp.c
===================================================================
--- gcc45.orig/gcc/gcc/testsuite/gcc.target/mips/mips32-dsp.c   2010-10-28 16:08:29.270787000 -0700
+++ gcc45/gcc/gcc/testsuite/gcc.target/mips/mips32-dsp.c        2010-10-28 16:24:13.004979000 -0700
@@ -92,6 +92,12 @@ 
 /* { dg-final { scan-assembler "lhx?" } } */
 /* { dg-final { scan-assembler "lwx?" } } */
 /* { dg-final { scan-assembler "bposge32" } } */
+/* { dg-final { scan-assembler "madd" } } */
+/* { dg-final { scan-assembler "maddu" } } */
+/* { dg-final { scan-assembler "msub" } } */
+/* { dg-final { scan-assembler "msubu" } } */
+/* { dg-final { scan-assembler "mult" } } */
+/* { dg-final { scan-assembler "multu" } } */

 #include <stdlib.h>
 #include <stdio.h>
@@ -101,6 +107,7 @@  typedef short v2q15 __attribute__ ((vect

 typedef int q31;
 typedef int i32;
+typedef unsigned int ui32;
 typedef long long a64;

 NOMIPS16 void test_MIPS_DSP (void);
@@ -150,6 +157,7 @@  NOMIPS16 void test_MIPS_DSP ()
   v2q15 v2q15_a,v2q15_b,v2q15_c,v2q15_r,v2q15_s;
   q31 q31_a,q31_b,q31_c,q31_r,q31_s;
   i32 i32_a,i32_b,i32_c,i32_r,i32_s;
+  ui32 ui32_a,ui32_b,ui32_c;
   a64 a64_a,a64_b,a64_c,a64_r,a64_s;

   void *ptr_a;
@@ -1088,5 +1096,63 @@  NOMIPS16 void test_MIPS_DSP ()
   i32_r = __builtin_mips_bposge32 ();
   if (i32_r != i32_s)
     abort ();
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  i32_b = 0x80000000;
+  i32_c = 0x11112222;
+  a64_s = 0xF7776EEF12345678LL;
+  a64_r = __builtin_mips_madd (a64_a, i32_b, i32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  ui32_b = 0x80000000;
+  ui32_c = 0x11112222;
+  a64_s = 0x0888911112345678LL;
+  a64_r = __builtin_mips_maddu (a64_a, ui32_b, ui32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  i32_b = 0x80000000;
+  i32_c = 0x11112222;
+  a64_s = 0x0888911112345678LL;
+  a64_r = __builtin_mips_msub (a64_a, i32_b, i32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  ui32_b = 0x80000000;
+  ui32_c = 0x11112222;
+  a64_s = 0xF7776EEF12345678LL;
+  a64_r = __builtin_mips_msubu (a64_a, ui32_b, ui32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  i32_a = 0x80000000;
+  i32_b = 0x11112222;
+  a64_s = 0xF7776EEF00000000LL;
+  a64_r = __builtin_mips_mult (i32_a, i32_b);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  ui32_a = 0x80000000;
+  ui32_b = 0x11112222;
+  a64_s = 0x888911100000000LL;
+  a64_r = __builtin_mips_multu (ui32_a, ui32_b);
+  if (a64_r != a64_s)
+    abort ();
+#endif
 }

Index: gcc45/gcc/gcc/testsuite/gcc.target/mips/mips32-dsp-run.c
===================================================================
--- gcc45.orig/gcc/gcc/testsuite/gcc.target/mips/mips32-dsp-run.c       2010-10-28 16:08:29.607711000 -0700
+++ gcc45/gcc/gcc/testsuite/gcc.target/mips/mips32-dsp-run.c    2010-10-28 16:24:13.032984000 -0700
@@ -10,6 +10,7 @@  typedef short v2q15 __attribute__ ((vect

 typedef int q31;
 typedef int i32;
+typedef unsigned int ui32;
 typedef long long a64;

 NOMIPS16 void test_MIPS_DSP (void);
@@ -59,6 +60,7 @@  NOMIPS16 void test_MIPS_DSP ()
   v2q15 v2q15_a,v2q15_b,v2q15_c,v2q15_r,v2q15_s;
   q31 q31_a,q31_b,q31_c,q31_r,q31_s;
   i32 i32_a,i32_b,i32_c,i32_r,i32_s;
+  ui32 ui32_a,ui32_b,ui32_c;
   a64 a64_a,a64_b,a64_c,a64_r,a64_s;

   void *ptr_a;
@@ -997,5 +999,63 @@  NOMIPS16 void test_MIPS_DSP ()
   i32_r = __builtin_mips_bposge32 ();
   if (i32_r != i32_s)
     abort ();
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  i32_b = 0x80000000;
+  i32_c = 0x11112222;
+  a64_s = 0xF7776EEF12345678LL;
+  a64_r = __builtin_mips_madd (a64_a, i32_b, i32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  ui32_b = 0x80000000;
+  ui32_c = 0x11112222;
+  a64_s = 0x0888911112345678LL;
+  a64_r = __builtin_mips_maddu (a64_a, ui32_b, ui32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  i32_b = 0x80000000;
+  i32_c = 0x11112222;
+  a64_s = 0x0888911112345678LL;
+  a64_r = __builtin_mips_msub (a64_a, i32_b, i32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  ui32_b = 0x80000000;
+  ui32_c = 0x11112222;
+  a64_s = 0xF7776EEF12345678LL;
+  a64_r = __builtin_mips_msubu (a64_a, ui32_b, ui32_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  i32_a = 0x80000000;
+  i32_b = 0x11112222;
+  a64_s = 0xF7776EEF00000000LL;
+  a64_r = __builtin_mips_mult (i32_a, i32_b);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  ui32_a = 0x80000000;
+  ui32_b = 0x11112222;
+  a64_s = 0x888911100000000LL;
+  a64_r = __builtin_mips_multu (ui32_a, ui32_b);
+  if (a64_r != a64_s)
+    abort ();
+#endif
 }

Index: gcc45/gcc/gcc/doc/extend.texi
===================================================================
--- gcc45.orig/gcc/gcc/doc/extend.texi  2010-10-28 16:08:30.148696000 -0700
+++ gcc45/gcc/gcc/doc/extend.texi       2010-10-28 16:24:13.113975000 -0700
@@ -9628,6 +9628,12 @@  i32 __builtin_mips_lbux (void *, i32)
 i32 __builtin_mips_lhx (void *, i32)
 i32 __builtin_mips_lwx (void *, i32)
 i32 __builtin_mips_bposge32 (void)
+a64 __builtin_mips_madd (a64, i32, i32);
+a64 __builtin_mips_maddu (a64, ui32, ui32);
+a64 __builtin_mips_msub (a64, i32, i32);
+a64 __builtin_mips_msubu (a64, ui32, ui32);
+a64 __builtin_mips_mult (i32, i32);
+a64 __builtin_mips_multu (ui32, ui32);
 @end smallexample

 The following built-in functions map directly to a particular MIPS DSP REV 2
@@ -9647,18 +9653,12 @@  i32 __builtin_mips_cmpgdu_lt_qb (v4i8, v
 i32 __builtin_mips_cmpgdu_le_qb (v4i8, v4i8);
 a64 __builtin_mips_dpa_w_ph (a64, v2i16, v2i16);
 a64 __builtin_mips_dps_w_ph (a64, v2i16, v2i16);
-a64 __builtin_mips_madd (a64, i32, i32);
-a64 __builtin_mips_maddu (a64, ui32, ui32);
-a64 __builtin_mips_msub (a64, i32, i32);
-a64 __builtin_mips_msubu (a64, ui32, ui32);
 v2i16 __builtin_mips_mul_ph (v2i16, v2i16);
 v2i16 __builtin_mips_mul_s_ph (v2i16, v2i16);
 q31 __builtin_mips_mulq_rs_w (q31, q31);
 v2q15 __builtin_mips_mulq_s_ph (v2q15, v2q15);
 q31 __builtin_mips_mulq_s_w (q31, q31);
 a64 __builtin_mips_mulsa_w_ph (a64, v2i16, v2i16);
-a64 __builtin_mips_mult (i32, i32);
-a64 __builtin_mips_multu (ui32, ui32);
 v4i8 __builtin_mips_precr_qb_ph (v2i16, v2i16);
 v2i16 __builtin_mips_precr_sra_ph_w (i32, i32, imm0_31);
 v2i16 __builtin_mips_precr_sra_r_ph_w (i32, i32, imm0_31);
Index: gcc45/gcc/gcc/configure
===================================================================
--- gcc45.orig/gcc/gcc/configure        2010-10-28 16:08:30.257698000 -0700
+++ gcc45/gcc/gcc/configure     2010-10-28 17:38:44.092817000 -0700
@@ -24391,6 +24391,45 @@  $as_echo "#define HAVE_AS_DTPRELWORD 1"

 fi

+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for DSP Rev1 mult with four accumulators support" >&5
+$as_echo_n "checking assembler for DSP Rev1 mult with four accumulators support... " >&6; }
+if test "${gcc_cv_as_mips_dsp_rev1_mult+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_mips_dsp_rev1_mult=no
+  if test x$gcc_cv_as != x; then
+    echo '     .set    mips32r2
+       .set    nodspr2
+       .set    dsp
+       madd    $ac3,$4,$5
+       maddu   $ac3,$4,$5
+       msub    $ac3,$4,$5
+       msubu   $ac3,$4,$5
+       mult    $ac3,$4,$5
+       multu   $ac3,$4,$5' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+       gcc_cv_as_mips_dsp_rev1_mult=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_mips_dsp_rev1_mult" >&5
+$as_echo "$gcc_cv_as_mips_dsp_rev1_mult" >&6; }
+if test $gcc_cv_as_mips_dsp_rev1_mult = yes; then
+
+$as_echo "#define HAVE_AS_DSP_REV1_MULT 1" >>confdefs.h
+
+fi
+
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker for explicit JALR relocation" >&5
 $as_echo_n "checking assembler and linker for explicit JALR relocation... " >&6; }
     gcc_cv_as_ld_jalr_reloc=no
Index: gcc45/gcc/gcc/configure.ac
===================================================================
--- gcc45.orig/gcc/gcc/configure.ac     2010-10-28 16:08:30.252704000 -0700
+++ gcc45/gcc/gcc/configure.ac  2010-10-28 17:38:36.772463000 -0700
@@ -3658,6 +3658,20 @@  x:
       [AC_DEFINE(HAVE_AS_DTPRELWORD, 1,
          [Define if your assembler supports .dtprelword.])])

+    gcc_GAS_CHECK_FEATURE([DSP Rev1 mult with four accumulators support],
+      gcc_cv_as_mips_dsp_rev1_mult,,,
+[      .set    mips32r2
+       .set    nodspr2
+       .set    dsp
+       madd    $ac3,$4,$5
+       maddu   $ac3,$4,$5
+       msub    $ac3,$4,$5
+       msubu   $ac3,$4,$5
+       mult    $ac3,$4,$5
+       multu   $ac3,$4,$5],,
+      [AC_DEFINE(HAVE_AS_DSP_REV1_MULT, 1,
+         [Define if your assembler supports DSP Rev1 mult.])])
+
     AC_MSG_CHECKING(assembler and linker for explicit JALR relocation)
     gcc_cv_as_ld_jalr_reloc=no
     if test $gcc_cv_as_mips_explicit_relocs = yes; then
Index: gcc45/gcc/gcc/config/mips/mips.h
===================================================================
--- gcc45.orig/gcc/gcc/config/mips/mips.h       2010-10-28 16:08:28.382894000 -0700
+++ gcc45/gcc/gcc/config/mips/mips.h    2010-10-28 16:24:13.376885000 -0700
@@ -180,6 +180,13 @@  enum mips_code_readable_setting {
 #define TARGET_WRITABLE_EH_FRAME (flag_pic && TARGET_SHARED)
 #endif

+/* Test the assembler to set ISA_HAS_DSP_MULT to DSP Rev 1 or 2.  */
+#ifdef HAVE_AS_DSP_REV1_MULT
+#define ISA_HAS_DSP_MULT ISA_HAS_DSP
+#else
+#define ISA_HAS_DSP_MULT ISA_HAS_DSPR2
+#endif
+
 /* Generate mips16 code */
 #define TARGET_MIPS16          ((target_flags & MASK_MIPS16) != 0)
 /* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */
Index: gcc45/gcc/gcc/config.in
===================================================================
--- gcc45.orig/gcc/gcc/config.in        2010-10-28 16:08:30.333700000 -0700
+++ gcc45/gcc/gcc/config.in     2010-10-28 16:24:13.421892000 -0700
@@ -229,6 +229,12 @@ 
 #endif


+/* Define if your assembler supports DSP Rev1 mult. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DSP_REV1_MULT
+#endif
+
+
 /* Define if your assembler supports .dtprelword. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_DTPRELWORD