diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md
index 5a5694f3f9e..d71ad95aa40 100644
--- a/gcc/config/mips/mips-dsp.md
+++ b/gcc/config/mips/mips-dsp.md
@@ -1152,8 +1152,21 @@
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "ISA_HAS_DSP"
-  "%*bposge%1\t%0%/"
-  [(set_attr "type"	"branch")])
+{
+  if (TARGET_DSPR3 && TARGET_CB_MAYBE)
+    return "%*bposge%1%:\t%0";
+  else
+    return "%*bposge%1\t%0%/";
+}
+  [(set_attr "type"	"branch")
+   (set (attr "compact_form") (if_then_else (match_test "TARGET_DSPR3
+							 && TARGET_CB_MAYBE")
+					      (const_string "maybe")
+					      (const_string "never")))
+   (set (attr "hazard") (if_then_else (match_test "TARGET_DSPR3
+						   && TARGET_CB_MAYBE")
+					      (const_string "forbidden_slot")
+					      (const_string "none")))])
 
 (define_expand "mips_madd<u>"
   [(set (match_operand:DI 0 "register_operand")
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index f1a1842b815..c13db20fdd9 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -5822,7 +5822,12 @@ mips_output_move (rtx dest, rtx src)
 
 	  /* Moves to HI are handled by special .md insns.  */
 	  if (REGNO (dest) == LO_REGNUM)
-	    return "mtlo\t%z1";
+	    {
+	      if (ISA_HAS_MULT)
+		return "mtlo\t%z1";
+	      else
+		return "mtlo\t%z1,$ac0";
+	    }
 
 	  if (DSP_ACC_REG_P (REGNO (dest)))
 	    {
@@ -5868,7 +5873,10 @@ mips_output_move (rtx dest, rtx src)
 		 -mfix-vr4130.  */
 	      if (ISA_HAS_MACCHI)
 		return dbl_p ? "dmacc\t%0,%.,%." : "macc\t%0,%.,%.";
-	      return "mflo\t%0";
+	      if (ISA_HAS_MULT)
+		return "mflo\t%0";
+	      else
+		return "mflo\t%0,$ac0";
 	    }
 
 	  if (DSP_ACC_REG_P (REGNO (src)))
@@ -21039,7 +21047,7 @@ mips_mult_zero_zero_cost (struct mips_sim *state, bool setting)
 static void
 mips_set_fast_mult_zero_zero_p (struct mips_sim *state)
 {
-  if (TARGET_MIPS16 || !ISA_HAS_HILO)
+  if (TARGET_MIPS16 || (!ISA_HAS_HILO && !TARGET_DSP))
     /* No MTLO or MTHI available for MIPS16. Also, when there are no HI or LO
        registers then there is no reason to zero them, arbitrarily choose to
        say that "MULT $0,$0" would be faster.  */
@@ -23115,6 +23123,12 @@ mips_option_override (void)
       target_flags |= MASK_LOONGSON_EXT;
     }
 
+  if (TARGET_DSPR3)
+    {
+      TARGET_DSP = true;
+      TARGET_DSPR2 = true;
+    }
+
   /* .eh_frame addresses should be the same width as a C pointer.
      Most MIPS ABIs support only one pointer size, so the assembler
      will usually know exactly how big an .eh_frame address is.
@@ -23316,7 +23330,7 @@ mips_conditional_register_usage (void)
   else
     accessible_reg_set &= ~reg_class_contents[DSP_ACC_REGS];
 
-  if (!ISA_HAS_HILO)
+  if (!ISA_HAS_HILO && !ISA_HAS_DSP)
     accessible_reg_set &= ~reg_class_contents[MD_REGS];
 
   if (!TARGET_HARD_FLOAT)
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 2912287a711..b30cc7a46b3 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -538,6 +538,11 @@ struct mips_cpu_info {
 	      builtin_define ("__mips_dspr2");				\
 	      builtin_define ("__mips_dsp_rev=2");			\
 	    }								\
+	  else if (TARGET_DSPR3)					\
+	    {								\
+	      builtin_define ("__mips_dspr3");				\
+	      builtin_define ("__mips_dsp_rev=3");			\
+	    }								\
 	  else								\
 	    builtin_define ("__mips_dsp_rev=1");			\
 	}								\
@@ -1536,6 +1541,7 @@ struct mips_cpu_info {
 %{mdmx} %{mno-mdmx:-no-mdmx} \
 %{mdsp} %{mno-dsp} \
 %{mdspr2} %{mno-dspr2} \
+%{mdspr3} %{mno-dspr3} \
 %{mmcu} %{mno-mcu} \
 %{meva} %{mno-eva} \
 %{mvirt} %{mno-virt} \
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 700b46c955e..516596c4345 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2167,7 +2167,7 @@
   [(set (match_operand:DI 0 "muldiv_target_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_DSP) && ISA_HAS_MULT"
+  "!TARGET_64BIT && ((!TARGET_FIX_R4000 && ISA_HAS_MULT) || ISA_HAS_DSP)"
 {
   if (ISA_HAS_DSP_MULT)
     return "mult<u>\t%q0,%1,%2";
@@ -5643,7 +5643,8 @@
 	(unspec:GPR [(match_operand:HILO 1 "hilo_operand" "x")]
 		    UNSPEC_MFHI))]
   ""
-  { return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." : "mfhi\t%0"; }
+  { return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." :
+	                       ISA_HAS_MULT ? "mfhi\t%0" : "mfhi\t%0,$ac0"; }
   [(set_attr "type" "mfhi")
    (set_attr "mode" "<GPR:MODE>")])
 
@@ -5656,7 +5657,12 @@
 		      (match_operand:GPR 2 "register_operand" "l")]
 		     UNSPEC_MTHI))]
   ""
-  "mthi\t%z1"
+  {
+    if (ISA_HAS_MULT)
+      return "mthi\t%z1";
+    else
+      return "mthi\t%z1, $ac0";
+  }
   [(set_attr "type" "mthi")
    (set_attr "mode" "SI")])
 
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 2e647d703b4..08bcf8143ee 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -120,9 +120,13 @@ Target Var(TARGET_DSP)
 Use MIPS-DSP instructions.
 
 mdspr2
-Target Var(TARGET_DSPR2) Condition(MIPS_SUPPORT_DSP)
+Target Var(TARGET_DSPR2) Condition({defined (MIPS_SUPPORT_DSP) && !defined (NANOMIPS_SUPPORT)})
 Use MIPS-DSP REV 2 instructions.
 
+mdspr3
+Target Var(TARGET_DSPR3) Condition({defined (MIPS_SUPPORT_DSP) && defined (NANOMIPS_SUPPORT)})
+Use MIPS-DSP Rev 3 instructions.
+
 mdebug
 Target Var(TARGET_DEBUG_MODE) Undocumented Condition(MIPS_SUPPORT_LEGACY)
 
diff --git a/gcc/testsuite/gcc.target/nanomips/dpaq_sa_l_w.c b/gcc/testsuite/gcc.target/nanomips/dpaq_sa_l_w.c
new file mode 100644
index 00000000000..4fa49bdf2d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/dpaq_sa_l_w.c
@@ -0,0 +1,51 @@
+/* { dg-do compile { target { fixed_point } } } */
+/* This test requires widening_mul */
+/* { dg-options "-mgp32 -mdspr3 -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tdpaq_sa.l.w\t\\\$ac" 3 } } */
+
+_Sat long long _Fract
+f1 (_Sat long _Fract x, _Sat long _Fract y, _Sat long long _Fract z)
+{
+  return (_Sat long long _Fract) x * y + z;
+}
+
+_Sat long long _Fract
+f2 (_Sat long _Fract x, _Sat long _Fract y, _Sat long long _Fract z)
+{
+  return z + (_Sat long long _Fract) y * x;
+}
+
+_Sat long long _Fract
+f3 (_Sat long _Fract x, _Sat long _Fract y, _Sat long long _Fract z)
+{
+  _Sat long long _Fract t = (_Sat long long _Fract) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z = t + z; /* Need to put z at the end.  GCC does not swap operands to
+		  match the ssmadd pattern, because types are saturating.  */
+  return z;
+}
+
+long long _Fract
+f4 (long _Fract x, long _Fract y, long long _Fract z)
+{
+  return (long long _Fract) x * y + z;
+}
+
+long long _Fract
+f5 (long _Fract x, long _Fract y, long long _Fract z)
+{
+  return z + (long long _Fract) y * x;
+}
+
+long long _Fract
+f6 (long _Fract x, long _Fract y, long long _Fract z)
+{
+  long long _Fract t = (long long _Fract) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z = t + z; /* Need to put z at the end.  GCC does not swap operands to
+		  match the ssmadd pattern, because types are saturating.  */
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/dpsq_sa_l_w.c b/gcc/testsuite/gcc.target/nanomips/dpsq_sa_l_w.c
new file mode 100644
index 00000000000..b6632f07816
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/dpsq_sa_l_w.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { fixed_point } } } */
+/* This test requires widening_mul */
+/* { dg-options "-mgp32 -mdspr3 -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tdpsq_sa.l.w\t\\\$ac" 2 } } */
+
+_Sat long long _Fract
+f1 (_Sat long _Fract x, _Sat long _Fract y, _Sat long long _Fract z)
+{
+  return z - (_Sat long long _Fract) x * y;
+}
+
+_Sat long long _Fract
+f2 (_Sat long _Fract x, _Sat long _Fract y, _Sat long long _Fract z)
+{
+  _Sat long long _Fract t = (_Sat long long _Fract) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z -= t;
+  return z;
+}
+
+long long _Fract
+f3 (long _Fract x, long _Fract y, long long _Fract z)
+{
+  return z - (long long _Fract) x * y;
+}
+
+long long _Fract
+f4 (long _Fract x, long _Fract y, long long _Fract z)
+{
+  long long _Fract t = (long long _Fract) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z -= t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/dsp-ctrl.c b/gcc/testsuite/gcc.target/nanomips/dsp-ctrl.c
new file mode 100644
index 00000000000..05df69bd9b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/dsp-ctrl.c
@@ -0,0 +1,69 @@
+/* { dg-do run } */
+/* { dg-options "-mdspr3 -mgp32" } */
+
+extern void abort (void);
+extern void exit (int);
+
+void __attribute__ ((noinline))
+test1 (int i)
+{
+  __builtin_mips_wrdsp (i, 63);
+}
+
+void __attribute__ ((noinline))
+test2 ()
+{
+  long long a = 0;
+  volatile int tmp = __builtin_mips_extpdp (a, 3);
+}
+
+void __attribute__ ((noinline))
+test3 (int i)
+{
+  long long a = 0;
+  volatile int tmp = __builtin_mips_extpdp (a, i);
+}
+
+void __attribute__ ((noinline))
+test4 ()
+{
+  long long a = 0;
+  int i = 0;
+  volatile long long tmp = __builtin_mips_mthlip (a, i);
+}
+
+int
+main ()
+{
+  int cntl;
+
+  /* Test 1: wrdsp */
+  __builtin_mips_wrdsp (0,63);
+  test1 (63);
+  cntl = __builtin_mips_rddsp (63);
+  if (cntl != 63)
+    abort ();
+
+  /* Test 2: extpdp */
+  __builtin_mips_wrdsp (63,63);
+  test2 ();
+  cntl = __builtin_mips_rddsp (63);
+  if (cntl != 59)
+    abort ();
+
+  /* Test 3: extpdpv */
+  __builtin_mips_wrdsp (63,63);
+  test3 (10);
+  cntl = __builtin_mips_rddsp (63);
+  if (cntl != 52)
+    abort ();
+
+  /* Test 4: mthlip */
+  __builtin_mips_wrdsp (8,63);
+  test4 ();
+  cntl = __builtin_mips_rddsp (63);
+  if (cntl != 40)
+    abort ();
+
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/dsp-lhxs.c b/gcc/testsuite/gcc.target/nanomips/dsp-lhxs.c
new file mode 100644
index 00000000000..e673d2b2491
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/dsp-lhxs.c
@@ -0,0 +1,11 @@
+/* Test MIPS32 DSP LHX instruction */
+/* { dg-do compile } */
+/* { dg-options "-mgp32 -mdspr3" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+/* { dg-final { scan-assembler "\tlhxs\t" } } */
+
+signed short test (signed short *a, int index)
+{
+  return a[index];
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/dsp-no-lhx.c b/gcc/testsuite/gcc.target/nanomips/dsp-no-lhx.c
new file mode 100644
index 00000000000..6a82bf9a85e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/dsp-no-lhx.c
@@ -0,0 +1,11 @@
+/* Test MIPS32 DSP LHX instruction */
+/* { dg-do compile } */
+/* { dg-options "-mgp32 -mdspr3" } */
+
+/* { dg-final { scan-assembler-not "\tlhx\t" } } */
+/* { dg-final { scan-assembler-not "\tlhxs\t" } } */
+
+unsigned short test (unsigned short *a, int index)
+{
+  return a[index];
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/fixed-scalar-type.c b/gcc/testsuite/gcc.target/nanomips/fixed-scalar-type.c
new file mode 100644
index 00000000000..8c1e8be9380
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/fixed-scalar-type.c
@@ -0,0 +1,218 @@
+/* Test scalar fixed-point instructions */
+/* { dg-do compile { target { fixed_point } } } */
+/* { dg-options "-mdspr2" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\taddu\t" 10 } } */
+/* { dg-final { scan-assembler-times "\tsubu\t" 10 } } */
+/* { dg-final { scan-assembler "\taddu_s.qb\t" } } */
+/* { dg-final { scan-assembler-times "\taddu_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\taddq_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\taddq_s.w\t" 2 } } */
+/* { dg-final { scan-assembler "\tsubu_s.qb\t" } } */
+/* { dg-final { scan-assembler-times "\tsubu_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tsubq_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tsubq_s.w\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmulq_rs.ph\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmulq_rs.w\t" 1 } } */
+
+short _Fract non_sat_test1 (short _Fract a, short _Fract b)
+{
+  return a + b;
+}
+
+_Fract non_sat_test2 (_Fract a, _Fract b)
+{
+  return a + b;
+}
+
+long _Fract non_sat_test3 (long _Fract a, long _Fract b)
+{
+  return a + b;
+}
+
+unsigned short _Fract non_sat_test4 (unsigned short _Fract a,
+				     unsigned short _Fract b)
+{
+  return a + b;
+}
+
+unsigned _Fract non_sat_test5 (unsigned _Fract a, unsigned _Fract b)
+{
+  return a + b;
+}
+
+unsigned long _Fract non_sat_test6 (unsigned long _Fract a,
+				    unsigned long _Fract b)
+{
+  return a + b;
+}
+
+short _Accum non_sat_test7 (short _Accum a, short _Accum b)
+{
+  return a + b;
+}
+
+_Accum non_sat_test8 (_Accum a, _Accum b)
+{
+  return a + b;
+}
+
+unsigned short _Accum non_sat_test9 (unsigned short _Accum a,
+				     unsigned short _Accum b)
+{
+  return a + b;
+}
+
+unsigned _Accum non_sat_test10 (unsigned _Accum a, unsigned _Accum b)
+{
+  return a + b;
+}
+
+short _Fract non_sat_test11 (short _Fract a, short _Fract b)
+{
+  return a - b;
+}
+
+_Fract non_sat_test12 (_Fract a, _Fract b)
+{
+  return a - b;
+}
+
+long _Fract non_sat_test13 (long _Fract a, long _Fract b)
+{
+  return a - b;
+}
+
+unsigned short _Fract non_sat_test14 (unsigned short _Fract a,
+				      unsigned short _Fract b)
+{
+  return a - b;
+}
+
+unsigned _Fract non_sat_test15 (unsigned _Fract a, unsigned _Fract b)
+{
+  return a - b;
+}
+
+unsigned long _Fract non_sat_test16 (unsigned long _Fract a,
+				     unsigned long _Fract b)
+{
+  return a - b;
+}
+
+short _Accum non_sat_test17 (short _Accum a, short _Accum b)
+{
+  return a - b;
+}
+
+_Accum non_sat_test18 (_Accum a, _Accum b)
+{
+  return a - b;
+}
+
+unsigned short _Accum non_sat_test19 (unsigned short _Accum a,
+				      unsigned short _Accum b)
+{
+  return a - b;
+}
+
+unsigned _Accum non_sat_test20 (unsigned _Accum a, unsigned _Accum b)
+{
+  return a - b;
+}
+
+_Sat unsigned short _Fract test1 (_Sat unsigned short _Fract a,
+					   _Sat unsigned short _Fract b)
+{
+  return a + b;
+}
+
+_Sat unsigned _Fract test2 (_Sat unsigned  _Fract a,
+				     _Sat unsigned _Fract b)
+{
+  return a + b;
+}
+
+_Sat unsigned short _Accum test3 (_Sat unsigned short _Accum a,
+					   _Sat unsigned short _Accum b)
+{
+  return a + b;
+}
+
+_Sat _Fract test4 (_Sat _Fract a, _Sat _Fract b)
+{
+  return a + b;
+}
+
+_Sat long _Fract test5 (_Sat long _Fract a, _Sat long _Fract b)
+{
+  return a + b;
+}
+
+_Sat short _Accum test6 (_Sat short _Accum a, _Sat short _Accum b)
+{
+  return a + b;
+}
+
+_Sat _Accum test7 (_Sat _Accum a, _Sat _Accum b)
+{
+  return a + b;
+}
+
+_Sat unsigned short _Fract test8 (_Sat unsigned short _Fract a,
+					   _Sat unsigned short _Fract b)
+{
+  return a - b;
+}
+
+_Sat unsigned _Fract test9 (_Sat unsigned  _Fract a,
+				     _Sat unsigned _Fract b)
+{
+  return a - b;
+}
+
+_Sat unsigned short _Accum test10 (_Sat unsigned short _Accum a,
+					    _Sat unsigned short _Accum b)
+{
+  return a - b;
+}
+
+_Sat _Fract test11 (_Sat _Fract a, _Sat _Fract b)
+{
+  return a - b;
+}
+
+_Sat long _Fract test12 (_Sat long _Fract a, _Sat long _Fract b)
+{
+  return a - b;
+}
+
+_Sat short _Accum test13 (_Sat short _Accum a, _Sat short _Accum b)
+{
+  return a - b;
+}
+
+_Sat _Accum test14 (_Sat _Accum a, _Sat _Accum b)
+{
+  return a - b;
+}
+
+_Sat _Fract test15 (_Sat _Fract a, _Sat _Fract b)
+{
+  return a * b;
+}
+
+_Sat long _Fract test16 (_Sat long _Fract a, _Sat long _Fract b)
+{
+  return a * b;
+}
+
+_Fract test17 (_Fract a, _Fract b)
+{
+  return a * b;
+}
+
+long _Fract test18 (long _Fract a, long _Fract b)
+{
+  return a * b;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/fixed-vector-type.c b/gcc/testsuite/gcc.target/nanomips/fixed-vector-type.c
new file mode 100644
index 00000000000..d493372682e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/fixed-vector-type.c
@@ -0,0 +1,133 @@
+/* Test vector fixed-point instructions */
+/* { dg-do compile { target { fixed_point } } } */
+/* { dg-options "-mdspr2" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\taddq_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tsubq_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\taddu_s.qb\t" 1 } } */
+/* { dg-final { scan-assembler-times "\taddu_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tsubu_s.qb\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tsubu_s.ph\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmulq_rs.ph\t" 1 } } */
+
+typedef _Sat unsigned short _Fract sat_v4uqq __attribute__ ((vector_size(4)));
+typedef _Sat unsigned _Fract sat_v2uhq __attribute__ ((vector_size(4)));
+typedef _Sat unsigned short _Accum sat_v2uha __attribute__ ((vector_size(4)));
+typedef _Sat _Fract sat_v2hq __attribute__ ((vector_size(4)));
+typedef _Sat short _Accum sat_v2ha __attribute__ ((vector_size(4)));
+
+typedef unsigned short _Fract v4uqq __attribute__ ((vector_size(4)));
+typedef unsigned _Fract v2uhq __attribute__ ((vector_size(4)));
+typedef unsigned short _Accum v2uha __attribute__ ((vector_size(4)));
+typedef _Fract v2hq __attribute__ ((vector_size(4)));
+typedef short _Accum v2ha __attribute__ ((vector_size(4)));
+
+sat_v2hq test1 (sat_v2hq a, sat_v2hq b)
+{
+  return a + b;
+}
+
+sat_v2ha test2 (sat_v2ha a, sat_v2ha b)
+{
+  return a + b;
+}
+
+sat_v2hq test3 (sat_v2hq a, sat_v2hq b)
+{
+  return a - b;
+}
+
+sat_v2ha test4 (sat_v2ha a, sat_v2ha b)
+{
+  return a - b;
+}
+
+sat_v4uqq test5 (sat_v4uqq a, sat_v4uqq b)
+{
+  return a + b;
+}
+
+sat_v2uhq test6 (sat_v2uhq a, sat_v2uhq b)
+{
+  return a + b;
+}
+
+sat_v2uha test7 (sat_v2uha a, sat_v2uha b)
+{
+  return a + b;
+}
+
+sat_v4uqq test8 (sat_v4uqq a, sat_v4uqq b)
+{
+  return a - b;
+}
+
+sat_v2uhq test9 (sat_v2uhq a, sat_v2uhq b)
+{
+  return a - b;
+}
+
+sat_v2uha test10 (sat_v2uha a, sat_v2uha b)
+{
+  return a - b;
+}
+
+sat_v2hq test11 (sat_v2hq a, sat_v2hq b)
+{
+  return a * b;
+}
+
+v2hq test12 (v2hq a, v2hq b)
+{
+  return a + b;
+}
+
+v2hq test13 (v2hq a, v2hq b)
+{
+  return a - b;
+}
+
+v2hq test14 (v2hq a, v2hq b)
+{
+  return a * b;
+}
+
+v2ha test15 (v2ha a, v2ha b)
+{
+  return a + b;
+}
+
+v2ha test16 (v2ha a, v2ha b)
+{
+  return a - b;
+}
+
+v4uqq test17 (v4uqq a, v4uqq b)
+{
+  return a + b;
+}
+
+v4uqq test18 (v4uqq a, v4uqq b)
+{
+  return a - b;
+}
+
+v2uhq test19 (v2uhq a, v2uhq b)
+{
+  return a + b;
+}
+
+v2uhq test20 (v2uhq a, v2uhq b)
+{
+  return a - b;
+}
+
+v2uha test21 (v2uha a, v2uha b)
+{
+  return a + b;
+}
+
+v2uha test22 (v2uha a, v2uha b)
+{
+  return a - b;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/madd-4.c b/gcc/testsuite/gcc.target/nanomips/madd-4.c
new file mode 100644
index 00000000000..6a31b79f16a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/madd-4.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* This test requires widening_mul */
+/* { dg-options "-mdspr3 -mgp32 -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tmadd\t\\\$ac" 3 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+  return (long long) x * y + z;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+  return z + (long long) y * x;
+}
+
+long long
+f3 (int x, int y, long long z)
+{
+  long long t = (long long) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/maddu-3.c b/gcc/testsuite/gcc.target/nanomips/maddu-3.c
new file mode 100644
index 00000000000..7ec312ce743
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/maddu-3.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* This test requires widening_mul */
+/* { dg-options "(HAS_MADD) -mgp32 -fexpensive-optimizations -mdspr3" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tmaddu\t" 3 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
+ull
+f3 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/maddu-4.c b/gcc/testsuite/gcc.target/nanomips/maddu-4.c
new file mode 100644
index 00000000000..89a91fb6a12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/maddu-4.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* This test requires widening_mul */
+/* { dg-options "-mdspr3 -mgp32 -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tmaddu\t\\\$ac" 3 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
+ull
+f3 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/mips-prepend-1.c b/gcc/testsuite/gcc.target/nanomips/mips-prepend-1.c
new file mode 100644
index 00000000000..cab88637a76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/mips-prepend-1.c
@@ -0,0 +1,8 @@
+/* { dg-options "-mdspr3" } */
+/* { dg-final { scan-assembler "prepend\[^\n\]*,10" } } */
+
+int
+foo (int x, int y)
+{
+  return __builtin_mips_prepend (x, y, 42);
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/mips32-dsp-run.c b/gcc/testsuite/gcc.target/nanomips/mips32-dsp-run.c
new file mode 100644
index 00000000000..dd189bf99cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/mips32-dsp-run.c
@@ -0,0 +1,1063 @@
+/* Test MIPS32 DSP instructions */
+/* { dg-do run } */
+/* { dg-options "-march=32r6 -mdspr3 (REQUIRES_STDLIB)" } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef signed char v4i8 __attribute__ ((vector_size(4)));
+typedef short v2q15 __attribute__ ((vector_size(4)));
+
+typedef int q31;
+typedef int i32;
+typedef unsigned int ui32;
+typedef long long a64;
+
+void test_MIPS_DSP (void);
+
+char array[100];
+int little_endian;
+
+int main ()
+{
+  int i;
+
+  union { long long ll; int i[2]; } endianness_test;
+  endianness_test.ll = 1;
+  little_endian = endianness_test.i[0];
+
+  for (i = 0; i < 100; i++)
+    array[i] = i;
+
+  test_MIPS_DSP ();
+
+  exit (0);
+}
+
+v2q15 add_v2q15 (v2q15 a, v2q15 b)
+{
+  return __builtin_mips_addq_ph (a, b);
+}
+
+v4i8 add_v4i8 (v4i8 a, v4i8 b)
+{
+  return __builtin_mips_addu_qb (a, b);
+}
+
+v2q15 sub_v2q15 (v2q15 a, v2q15 b)
+{
+  return __builtin_mips_subq_ph (a, b);
+}
+
+v4i8 sub_v4i8 (v4i8 a, v4i8 b)
+{
+  return __builtin_mips_subu_qb (a, b);
+}
+
+void test_MIPS_DSP ()
+{
+  v4i8 v4i8_a,v4i8_b,v4i8_c,v4i8_r,v4i8_s;
+  v2q15 v2q15_a,v2q15_b,v2q15_c,v2q15_r,v2q15_s;
+  q31 q31_a,q31_b,q31_c,q31_r,q31_s;
+  /* To protect the multiplication-related tests from being optimized
+     at compile time.  */
+  volatile i32 i32_a,i32_b,i32_c,i32_r,i32_s;
+  volatile ui32 ui32_a,ui32_b,ui32_c;
+  a64 a64_a,a64_b,a64_c,a64_r,a64_s;
+
+  void *ptr_a;
+  int r,s;
+  long long lr,ls;
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x81bd, 0x6789};
+  v2q15_r = add_v2q15 (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x7fff, 0x6789};
+  v2q15_r = __builtin_mips_addq_s_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_b = 0x71234567;
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_addq_s_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0xf1, 0xbd, 0x67, 0x89};
+  v4i8_r = add_v4i8 (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0xff, 0xbd, 0x67, 0x89};
+  v4i8_r = __builtin_mips_addu_s_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0xa2ab, 0x4567};
+  v2q15_r = sub_v2q15 (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x8000, 0x4567};
+  v2q15_r = __builtin_mips_subq_s_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_b = 0x71234567;
+  q31_s = 0xfedcba99;
+  q31_r = __builtin_mips_subq_s_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0xf3, 0xab, 0x45, 0x67};
+  v4i8_r = sub_v4i8 (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0x0, 0x0, 0x45, 0x67};
+  v4i8_r = __builtin_mips_subu_s_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0xf5678900;
+  i32_b = 0x7abcdef0;
+  i32_s = 0x702467f0;
+  i32_r = __builtin_mips_addsc (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x75678900;
+  i32_b = 0x7abcdef0;
+  i32_s = 0xf02467f1;
+  i32_r = __builtin_mips_addwc (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0;
+  i32_b = 0x00000901;
+  i32_s = 9;
+  i32_r = __builtin_mips_modsub (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  i32_s = 0x1f4;
+  i32_r = __builtin_mips_raddu_w_qb (v4i8_a);
+  if (i32_r != i32_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x8134};
+  v2q15_s = (v2q15) {0x7fff, 0x7ecc};
+  v2q15_r = __builtin_mips_absq_s_ph (v2q15_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = (q31) 0x80000000;
+  q31_s = (q31) 0x7fffffff;
+  q31_r = __builtin_mips_absq_s_w (q31_a);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x9999, 0x5612};
+  v2q15_b = (v2q15) {0x5612, 0x3333};
+  if (little_endian)
+    v4i8_s = (v4i8) {0x56, 0x33, 0x99, 0x56};
+  else
+    v4i8_s = (v4i8) {0x99, 0x56, 0x56, 0x33};
+  v4i8_r = __builtin_mips_precrq_qb_ph (v2q15_a, v2q15_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x12348678;
+  q31_b = 0x44445555;
+  if (little_endian)
+    v2q15_s = (v2q15) {0x4444, 0x1234};
+  else
+    v2q15_s = (v2q15) {0x1234, 0x4444};
+  v2q15_r = __builtin_mips_precrq_ph_w (q31_a, q31_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x12348678;
+  q31_b = 0x44445555;
+  if (little_endian)
+    v2q15_s = (v2q15) {0x4444, 0x1235};
+  else
+    v2q15_s = (v2q15) {0x1235, 0x4444};
+  v2q15_r = __builtin_mips_precrq_rs_ph_w (q31_a, q31_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x9999, 0x5612};
+  v2q15_b = (v2q15) {0x5612, 0x3333};
+  if (little_endian)
+    v4i8_s = (v4i8) {0xac, 0x66, 0x00, 0xac};
+  else
+    v4i8_s = (v4i8) {0x00, 0xac, 0xac, 0x66};
+  v4i8_r = __builtin_mips_precrqu_s_qb_ph (v2q15_a, v2q15_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3589, 0x4444};
+  if (little_endian)
+    q31_s = 0x44440000;
+  else
+    q31_s = 0x35890000;
+  q31_r = __builtin_mips_preceq_w_phl (v2q15_a);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3589, 0x4444};
+  if (little_endian)
+    q31_s = 0x35890000;
+  else
+    q31_s = 0x44440000;
+  q31_r = __builtin_mips_preceq_w_phr (v2q15_a);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  else
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  v2q15_r = __builtin_mips_precequ_ph_qbl (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  else
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  v2q15_r = __builtin_mips_precequ_ph_qbr (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  else
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  v2q15_r = __builtin_mips_precequ_ph_qbla (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  else
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  v2q15_r = __builtin_mips_precequ_ph_qbra (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x56, 0x33};
+  else
+    v2q15_s = (v2q15) {0x12, 0x56};
+  v2q15_r = __builtin_mips_preceu_ph_qbl (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x12, 0x56};
+  else
+    v2q15_s = (v2q15) {0x56, 0x33};
+  v2q15_r = __builtin_mips_preceu_ph_qbr (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x99, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x99, 0x33};
+  else
+    v2q15_s = (v2q15) {0x12, 0x56};
+  v2q15_r = __builtin_mips_preceu_ph_qbla (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x99, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x12, 0x56};
+  else
+    v2q15_s = (v2q15) {0x99, 0x33};
+  v2q15_r = __builtin_mips_preceu_ph_qbra (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_s = (v4i8) {0xc8, 0xd0, 0x58, 0xe0};
+  v4i8_r = __builtin_mips_shll_qb (v4i8_a, 2);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  i32_b = 1;
+  v4i8_s = (v4i8) {0xe4, 0x68, 0xac, 0xf0};
+  v4i8_r = __builtin_mips_shll_qb (v4i8_a, i32_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d0, 0x59e0};
+  v2q15_r = __builtin_mips_shll_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 1;
+  v2q15_s = (v2q15) {0x2468, 0xacf0};
+  v2q15_r = __builtin_mips_shll_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d0, 0x7fff};
+  v2q15_r = __builtin_mips_shll_s_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 1;
+  v2q15_s = (v2q15) {0x2468, 0x7fff};
+  v2q15_r = __builtin_mips_shll_s_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_shll_s_w (q31_a, 2);
+  if (q31_r != q31_s)
+    abort ();
+
+  q31_a = 0x70000000;
+  i32_b = 1;
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_shll_s_w (q31_a, i32_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_s = (v4i8) {0x3c, 0xd, 0x15, 0x1e};
+  v4i8_r = __builtin_mips_shrl_qb (v4i8_a, 2);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  i32_b = 1;
+  v4i8_s = (v4i8) {0x79, 0x1a, 0x2b, 0x3c};
+  v4i8_r = __builtin_mips_shrl_qb (v4i8_a, i32_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d, 0x159e};
+  v2q15_r = __builtin_mips_shra_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 1;
+  v2q15_s = (v2q15) {0x91a, 0x2b3c};
+  v2q15_r = __builtin_mips_shra_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d, 0x159e};
+  v2q15_r = __builtin_mips_shra_r_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 3;
+  v2q15_s = (v2q15) {0x247, 0xacf};
+  v2q15_r = __builtin_mips_shra_r_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_s = 0x1c000000;
+  q31_r = __builtin_mips_shra_r_w (q31_a, 2);
+  if (q31_r != q31_s)
+    abort ();
+
+  q31_a = 0x70000004;
+  i32_b = 3;
+  q31_s = 0x0e000001;
+  q31_r = __builtin_mips_shra_r_w (q31_a, i32_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x1, 0x2, 0x3, 0x4};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  if (little_endian)
+    v2q15_s = (v2q15) {0xffff, 0x4444};
+  else
+    v2q15_s = (v2q15) {0x6f89, 0x2222};
+  v2q15_r = __builtin_mips_muleu_s_ph_qbl (v4i8_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x1, 0x2, 0x3, 0x4};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x6f89, 0x2222};
+  else
+    v2q15_s = (v2q15) {0xffff, 0x4444};
+  v2q15_r = __builtin_mips_muleu_s_ph_qbr (v4i8_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x0fdd, 0x0b87};
+  v2q15_r = __builtin_mips_mulq_rs_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x8000};
+  v2q15_b = (v2q15) {0x8000, 0x8000};
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_muleq_s_w_phl (v2q15_a, v2q15_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x8000};
+  v2q15_b = (v2q15) {0x8000, 0x8000};
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_muleq_s_w_phr (v2q15_a, v2q15_b);
+  if (q31_r != q31_s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x22222f27;
+  else
+    a64_s = 0x222238d9;
+  a64_r = __builtin_mips_dpau_h_qbl (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x222238d9;
+  else
+    a64_s = 0x22222f27;
+  a64_r = __builtin_mips_dpau_h_qbr (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x2221f2fb;
+  else
+    a64_s = 0x2221e949;
+  a64_r = __builtin_mips_dpsu_h_qbl (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x2221e949;
+  else
+    a64_s = 0x2221f2fb;
+  a64_r = __builtin_mips_dpsu_h_qbr (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x5678};
+  v2q15_c = (v2q15) {0x8000, 0x1111};
+  a64_s = 0x8b877d00;
+  a64_r = __builtin_mips_dpaq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x5678};
+  v2q15_c = (v2q15) {0x8000, 0x1111};
+  a64_s = 0xffffffff7478a522LL;
+  a64_r = __builtin_mips_dpsq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x5678};
+  v2q15_c = (v2q15) {0x8000, 0x1111};
+  if (little_endian)
+    a64_s = 0xffffffff8b877d02LL;
+  else
+    a64_s = 0x7478a520;
+  a64_r = __builtin_mips_mulsaq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  q31_b = 0x80000000;
+  q31_c = 0x80000000;
+  a64_s = 0x7fffffffffffffffLL;
+  a64_r = __builtin_mips_dpaq_sa_l_w (a64_a, q31_b, q31_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  q31_b = 0x80000000;
+  q31_c = 0x80000000;
+  a64_s = 0x8000000000001112LL;
+  a64_r = __builtin_mips_dpsq_sa_l_w (a64_a, q31_b, q31_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x1115;
+  else
+    a64_s = 0x80001110;
+  a64_r = __builtin_mips_maq_s_w_phl (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x80001110;
+  else
+    a64_s = 0x1115;
+  a64_r = __builtin_mips_maq_s_w_phr (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x1115;
+  else
+    a64_s = 0x7fffffff;
+  a64_r = __builtin_mips_maq_sa_w_phl (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x7fffffff;
+  else
+    a64_s = 0x1115;
+  a64_r = __builtin_mips_maq_sa_w_phr (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+  i32_a = 0x12345678;
+  i32_s = 0x00001e6a;
+  i32_r = __builtin_mips_bitrev (i32_a);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x00000208; // pos is 8, size is 4
+  __builtin_mips_wrdsp (i32_a, 31);
+  i32_a = 0x12345678;
+  i32_b = 0x87654321;
+  i32_s = 0x12345178;
+  i32_r = __builtin_mips_insv (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_s = (v4i8) {1, 1, 1, 1};
+  v4i8_r = __builtin_mips_repl_qb (1);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 99;
+  v4i8_s = (v4i8) {99, 99, 99, 99};
+  v4i8_r = __builtin_mips_repl_qb (i32_a);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_s = (v2q15) {30, 30};
+  v2q15_r = __builtin_mips_repl_ph (30);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x5612;
+  v2q15_s = (v2q15) {0x5612, 0x5612};
+  v2q15_r = __builtin_mips_repl_ph (i32_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x03000000;
+  else
+    i32_s = 0x0c000000;
+  __builtin_mips_cmpu_eq_qb (v4i8_a, v4i8_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x04000000;
+  else
+    i32_s = 0x02000000;
+  __builtin_mips_cmpu_lt_qb (v4i8_a, v4i8_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x07000000;
+  else
+    i32_s = 0x0e000000;
+  __builtin_mips_cmpu_le_qb (v4i8_a, v4i8_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x3;
+  else
+    i32_s = 0xc;
+  i32_r=__builtin_mips_cmpgu_eq_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x4;
+  else
+    i32_s = 0x2;
+  i32_r = __builtin_mips_cmpgu_lt_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x7;
+  else
+    i32_s = 0xe;
+  i32_r = __builtin_mips_cmpgu_le_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  __builtin_mips_wrdsp (0,31); // Clear all condition code bits.
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  if (little_endian)
+    i32_s = 0x01000000;
+  else
+    i32_s = 0x02000000;
+  __builtin_mips_cmp_eq_ph (v2q15_a, v2q15_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  if (little_endian)
+    i32_s = 0x02000000;
+  else
+    i32_s = 0x01000000;
+  __builtin_mips_cmp_lt_ph (v2q15_a, v2q15_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  i32_s = 0x03000000;
+  __builtin_mips_cmp_le_ph (v2q15_a, v2q15_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0a000000; // cc: 0000 1010
+  __builtin_mips_wrdsp (i32_a, 31);
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x21, 0x43, 0x65, 0x87};
+  if (little_endian)
+    v4i8_s = (v4i8) {0x21, 0x34, 0x65, 0x78};
+  else
+    v4i8_s = (v4i8) {0x12, 0x43, 0x56, 0x87};
+  v4i8_r = __builtin_mips_pick_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x02000000; // cc: 0000 0010
+  __builtin_mips_wrdsp (i32_a, 31);
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x2143, 0x6587};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x2143, 0x5678};
+  else
+    v2q15_s = (v2q15) {0x1234, 0x6587};
+  v2q15_r = __builtin_mips_pick_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x7856, 0x1234};
+  else
+    v2q15_s = (v2q15) {0x5678, 0x1234};
+  v2q15_r = __builtin_mips_packrl_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x1234567887654321LL;
+  i32_s = 0x88765432;
+  i32_r = __builtin_mips_extr_w (a64_a, 4);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887658321LL;
+  i32_s = 0x56788766;
+  i32_r = __builtin_mips_extr_r_w (a64_a, 16);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x12345677fffffff8LL;
+  i32_s = 0x7fffffff;
+  i32_r = __builtin_mips_extr_rs_w (a64_a, 4);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887658321LL;
+  i32_s = 0x7fff;
+  i32_r = __builtin_mips_extr_s_h (a64_a, 16);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x0000007887658321LL;
+  i32_b = 24;
+  i32_s = 0x7887;
+  i32_r = __builtin_mips_extr_s_h (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887654321LL;
+  i32_b = 4;
+  i32_s = 0x88765432;
+  i32_r = __builtin_mips_extr_w (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887658321LL;
+  i32_b = 16;
+  i32_s = 0x56788766;
+  i32_r = __builtin_mips_extr_r_w (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x12345677fffffff8LL;
+  i32_b = 4;
+  i32_s = 0x7fffffff;
+  i32_r = __builtin_mips_extr_rs_w (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_s = 8;
+  i32_r = __builtin_mips_extp (a64_a, 3); // extract 4 bits
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_b = 7; // size is 8. NOTE!! we should use 7
+  i32_s = 0x87;
+  i32_r = __builtin_mips_extp (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_s = 8;
+  i32_r = __builtin_mips_extpdp (a64_a, 3); // extract 4 bits
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_s = 0x0000021b; // pos is 27
+  i32_r = __builtin_mips_rddsp (31);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_b = 11; // size is 12. NOTE!!! We should use 11
+  i32_s = 0x876;
+  i32_r = __builtin_mips_extpdp (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_s = 0x00000213; // pos is 19
+  i32_r = __builtin_mips_rddsp (31);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887654321LL;
+  a64_s = 0x0012345678876543LL;
+  a64_r = __builtin_mips_shilo (a64_a, 8);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x1234567887654321LL;
+  i32_b = -16;
+  a64_s = 0x5678876543210000LL;
+  a64_r = __builtin_mips_shilo (a64_a, i32_b);
+  if (a64_r != a64_s)
+    abort ();
+
+  i32_a = 0x0;
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_b = 0x11112222;
+  a64_s = 0x8765432111112222LL;
+  a64_r = __builtin_mips_mthlip (a64_a, i32_b);
+  if (a64_r != a64_s)
+    abort ();
+  i32_s = 32;
+  i32_r = __builtin_mips_rddsp (31);
+  if (i32_r != i32_s)
+    abort ();
+#endif
+
+  i32_a = 0x1357a468;
+  __builtin_mips_wrdsp (i32_a, 63);
+  i32_s = 0x03572428;
+  i32_r = __builtin_mips_rddsp (63);
+  if (i32_r != i32_s)
+    abort ();
+
+  ptr_a = &array;
+  i32_b = 37;
+  i32_s = 37;
+  i32_r = __builtin_mips_lbux (ptr_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  ptr_a = &array;
+  i32_b = 38;
+  if (little_endian)
+    i32_s = 0x2726;
+  else
+    i32_s = 0x2627;
+  i32_r = __builtin_mips_lhx (ptr_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  ptr_a = &array;
+  i32_b = 40;
+  if (little_endian)
+    i32_s = 0x2b2a2928;
+  else
+    i32_s = 0x28292a2b;
+  i32_r = __builtin_mips_lwx (ptr_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+/*  i32_a = 0x00000220; // pos is 32, size is 4
+  __builtin_mips_wrdsp (i32_a, 63);
+  i32_s = 1;
+  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
+}
+
diff --git a/gcc/testsuite/gcc.target/nanomips/mips32-dspr2.c b/gcc/testsuite/gcc.target/nanomips/mips32-dspr2.c
new file mode 100644
index 00000000000..260936bf9ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/mips32-dspr2.c
@@ -0,0 +1,541 @@
+/* Test MIPS32 DSP REV 2 instructions */
+/* { dg-do run } */
+/* { dg-options "-mdspr3" } */
+
+typedef signed char v4q7 __attribute__ ((vector_size(4)));
+typedef signed char v4i8 __attribute__ ((vector_size(4)));
+typedef short v2q15 __attribute__ ((vector_size(4)));
+typedef short v2i16 __attribute__ ((vector_size(4)));
+typedef int q31;
+typedef int i32;
+typedef unsigned int ui32;
+typedef long long a64;
+
+void abort (void);
+
+void test_MIPS_DSPR2 (void);
+
+int little_endian;
+
+int main ()
+{
+  union { long long ll; int i[2]; } endianness_test;
+  endianness_test.ll = 1;
+  little_endian = endianness_test.i[0];
+
+  test_MIPS_DSPR2 ();
+
+  return 0;
+}
+
+void test_MIPS_DSPR2 ()
+{
+  v4q7 v4q7_a,v4q7_b,v4q7_c,v4q7_r,v4q7_s;
+  v4i8 v4i8_a,v4i8_b,v4i8_c,v4i8_r,v4i8_s;
+  v2q15 v2q15_a,v2q15_b,v2q15_c,v2q15_r,v2q15_s;
+  v2i16 v2i16_a,v2i16_b,v2i16_c,v2i16_r,v2i16_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,ui32_r,ui32_s;
+  a64 a64_a,a64_b,a64_c,a64_r,a64_s;
+
+  int r,s;
+
+  v4q7_a = (v4i8) {0x81, 0xff, 0x80, 0x23};
+  v4q7_s = (v4i8) {0x7f, 0x01, 0x7f, 0x23};
+  v4q7_r = __builtin_mips_absq_s_qb (v4q7_a);
+  r = (int) v4q7_r;
+  s = (int) v4q7_s;
+  if (r != s)
+    abort ();
+
+  v2i16_a = (v2i16) {0xffff, 0x2468};
+  v2i16_b = (v2i16) {0x1234, 0x1111};
+  v2i16_s = (v2i16) {0x1233, 0x3579};
+  v2i16_r = __builtin_mips_addu_ph (v2i16_a, v2i16_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  v2i16_a = (v2i16) {0xffff, 0x2468};
+  v2i16_b = (v2i16) {0x1234, 0x1111};
+  v2i16_s = (v2i16) {0xffff, 0x3579};
+  v2i16_r = __builtin_mips_addu_s_ph (v2i16_a, v2i16_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x11, 0x22, 0x33, 0xff};
+  v4i8_b = (v4i8) {0x11, 0x33, 0x99, 0xff};
+  v4i8_s = (v4i8) {0x11, 0x2a, 0x66, 0xff};
+  v4i8_r = __builtin_mips_adduh_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x11, 0x22, 0x33, 0xff};
+  v4i8_b = (v4i8) {0x11, 0x33, 0x99, 0xff};
+  v4i8_s = (v4i8) {0x11, 0x2b, 0x66, 0xff};
+  v4i8_r = __builtin_mips_adduh_r_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x12345678;
+  i32_b = 0x87654321;
+  i32_s = 0x56784321;
+  i32_r = __builtin_mips_append (i32_a, i32_b, 16);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x12345678;
+  i32_b = 0x87654321;
+  i32_s = 0x78876543;
+  i32_r = __builtin_mips_balign (i32_a, i32_b, 3);
+  if (i32_r != i32_s)
+    abort ();
+
+  __builtin_mips_wrdsp (0, 63);
+  v4i8_a = (v4i8) {0x11, 0x22, 0x33, 0x44};
+  v4i8_b = (v4i8) {0x11, 0x33, 0x33, 0x44};
+  if (little_endian)
+    i32_s = 0xd;
+  else
+    i32_s = 0xb;
+  i32_r = __builtin_mips_cmpgdu_eq_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+  i32_r = __builtin_mips_rddsp (16);
+  if (little_endian)
+    i32_s = 0x0d000000;
+  else
+    i32_s = 0x0b000000;
+  if (i32_r != i32_s)
+    abort ();
+
+  __builtin_mips_wrdsp (0, 63);
+  v4i8_a = (v4i8) {0x11, 0x22, 0x33, 0x44};
+  v4i8_b = (v4i8) {0x11, 0x33, 0x33, 0x44};
+  if (little_endian)
+    i32_s = 0x2;
+  else
+    i32_s = 0x4;
+  i32_r = __builtin_mips_cmpgdu_lt_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+  i32_r = __builtin_mips_rddsp (16);
+  if (little_endian)
+    i32_s = 0x02000000;
+  else
+    i32_s = 0x04000000;
+  if (i32_r != i32_s)
+    abort ();
+
+  __builtin_mips_wrdsp (0, 63);
+  v4i8_a = (v4i8) {0x11, 0x22, 0x33, 0x54};
+  v4i8_b = (v4i8) {0x11, 0x33, 0x33, 0x44};
+  if (little_endian)
+    i32_s = 0x7;
+  else
+    i32_s = 0xe;
+  i32_r = __builtin_mips_cmpgdu_le_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+  i32_r = __builtin_mips_rddsp (16);
+  if (little_endian)
+    i32_s = 0x07000000;
+  else
+    i32_s = 0x0e000000;
+  if (i32_r != i32_s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  v2i16_b = (v2i16) {0xffff, 0x1555};
+  v2i16_c = (v2i16) {0x1234, 0x3322};
+  a64_s = 0x1677088e;
+  a64_r = __builtin_mips_dpa_w_ph (a64_a, v2i16_b, v2i16_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x12345678;
+  v2i16_b = (v2i16) {0xffff, 0x1555};
+  v2i16_c = (v2i16) {0x1234, 0x3322};
+  a64_s = 0x0df1a462;
+  a64_r = __builtin_mips_dps_w_ph (a64_a, v2i16_b, v2i16_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#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
+
+  v2i16_a = (v2i16) {0xffff, 0x2468};
+  v2i16_b = (v2i16) {0x1234, 0x1111};
+  v2i16_s = (v2i16) {0xedcc, 0x52e8};
+  v2i16_r = __builtin_mips_mul_ph (v2i16_a, v2i16_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  v2i16_a = (v2i16) {0x8000, 0x7fff};
+  v2i16_b = (v2i16) {0x1234, 0x1111};
+  v2i16_s = (v2i16) {0x8000, 0x7fff};
+  v2i16_r = __builtin_mips_mul_s_ph (v2i16_a, v2i16_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x80000000;
+  q31_b = 0x80000000; 
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_mulq_rs_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0xffff, 0x8000};
+  v2q15_b = (v2q15) {0x1111, 0x8000};
+  v2q15_s = (v2q15) {0xffff, 0x7fff};
+  v2q15_r = __builtin_mips_mulq_s_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x00000002;
+  q31_b = 0x80000000; 
+  q31_s = 0xfffffffe;
+  q31_r = __builtin_mips_mulq_s_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x19848419;
+  v2i16_b = (v2i16) {0xffff, 0x8000};
+  v2i16_c = (v2i16) {0x1111, 0x8000};
+  if (little_endian)
+    a64_s = 0x5984952a;
+  else
+    a64_s = 0xffffffffd9847308LL;
+  a64_r = __builtin_mips_mulsa_w_ph (a64_a, v2i16_b, v2i16_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
+
+  v2i16_a = (v2i16) {0x1234, 0x5678};
+  v2i16_b = (v2i16) {0x2233, 0x5566};
+  if (little_endian)
+    v4i8_s = (v4i8) {0x33, 0x66, 0x34, 0x78};
+  else
+    v4i8_s = (v4i8) {0x34, 0x78, 0x33, 0x66};
+  v4i8_r = __builtin_mips_precr_qb_ph (v2i16_a, v2i16_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x12345678;
+  i32_b = 0x33334444;
+  if (little_endian)
+    v2i16_s = (v2i16) {0x3444, 0x4567};
+  else
+    v2i16_s = (v2i16) {0x4567, 0x3444};
+  v2i16_r = __builtin_mips_precr_sra_ph_w (i32_a, i32_b, 4);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x12345678;
+  i32_b = 0x33334444;
+  if (little_endian)
+    v2i16_s = (v2i16) {0x3444, 0x4568};
+  else
+    v2i16_s = (v2i16) {0x4568, 0x3444};
+  v2i16_r = __builtin_mips_precr_sra_r_ph_w (i32_a, i32_b, 4);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x12345678;
+  i32_b = 0x87654321;
+  i32_s = 0x43211234;
+  i32_r = __builtin_mips_prepend (i32_a, i32_b, 16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x45, 0x77, 0x99};
+  v4i8_s = (v4i8) {0x9, 0x22, 0x3b, 0xcc};
+  v4i8_r = __builtin_mips_shra_qb (v4i8_a, 1);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x45, 0x77, 0x99};
+  v4i8_s = (v4i8) {0x9, 0x23, 0x3c, 0xcd};
+  v4i8_r = __builtin_mips_shra_r_qb (v4i8_a, 1);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_b = 1;  
+  v4i8_a = (v4i8) {0x12, 0x45, 0x77, 0x99};
+  v4i8_s = (v4i8) {0x9, 0x22, 0x3b, 0xcc};
+  v4i8_r = __builtin_mips_shra_qb (v4i8_a, i32_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_b = 1;  
+  v4i8_a = (v4i8) {0x12, 0x45, 0x77, 0x99};
+  v4i8_s = (v4i8) {0x9, 0x23, 0x3c, 0xcd};
+  v4i8_r = __builtin_mips_shra_r_qb (v4i8_a, i32_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2i16_a = (v2i16) {0x1357, 0x2468};
+  v2i16_s = (v2i16) {0x0135, 0x0246};
+  v2i16_r = __builtin_mips_shrl_ph (v2i16_a, 4);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  i32_b = 8;
+  v2i16_a = (v2i16) {0x1357, 0x2468};
+  v2i16_s = (v2i16) {0x0013, 0x0024};
+  v2i16_r = __builtin_mips_shrl_ph (v2i16_a, i32_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  v2i16_a = (v2i16) {0x1357, 0x4455};
+  v2i16_b = (v2i16) {0x3333, 0x4444};
+  v2i16_s = (v2i16) {0xe024, 0x0011};
+  v2i16_r = __builtin_mips_subu_ph (v2i16_a, v2i16_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  v2i16_a = (v2i16) {0x1357, 0x4455};
+  v2i16_b = (v2i16) {0x3333, 0x4444};
+  v2i16_s = (v2i16) {0x0000, 0x0011};
+  v2i16_r = __builtin_mips_subu_s_ph (v2i16_a, v2i16_b);
+  r = (int) v2i16_r;
+  s = (int) v2i16_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x33 ,0x44, 0x55, 0x66};
+  v4i8_b = (v4i8) {0x99 ,0x15, 0x85, 0xff};
+  v4i8_s = (v4i8) {0xcd ,0x17, 0xe8, 0xb3};
+  v4i8_r = __builtin_mips_subuh_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x33 ,0x44, 0x55, 0x66};
+  v4i8_b = (v4i8) {0x99 ,0x15, 0x85, 0xff};
+  v4i8_s = (v4i8) {0xcd ,0x18, 0xe8, 0xb4};
+  v4i8_r = __builtin_mips_subuh_r_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3334, 0x4444};
+  v2q15_b = (v2q15) {0x1111, 0x2222};
+  v2q15_s = (v2q15) {0x2222, 0x3333};
+  v2q15_r = __builtin_mips_addqh_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3334, 0x4444};
+  v2q15_b = (v2q15) {0x1111, 0x2222};
+  v2q15_s = (v2q15) {0x2223, 0x3333};
+  v2q15_r = __builtin_mips_addqh_r_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x11111112;
+  q31_b = 0x99999999;
+  q31_s = 0xd5555555;
+  q31_r = __builtin_mips_addqh_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  q31_a = 0x11111112;
+  q31_b = 0x99999999;
+  q31_s = 0xd5555556;
+  q31_r = __builtin_mips_addqh_r_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3334, 0x4444};
+  v2q15_b = (v2q15) {0x1111, 0x2222};
+  v2q15_s = (v2q15) {0x1111, 0x1111};
+  v2q15_r = __builtin_mips_subqh_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3334, 0x4444};
+  v2q15_b = (v2q15) {0x1111, 0x2222};
+  v2q15_s = (v2q15) {0x1112, 0x1111};
+  v2q15_r = __builtin_mips_subqh_r_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x11111112;
+  q31_b = 0x99999999;
+  q31_s = 0x3bbbbbbc;
+  q31_r = __builtin_mips_subqh_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  q31_a = 0x11111112;
+  q31_b = 0x99999999;
+  q31_s = 0x3bbbbbbd;
+  q31_r = __builtin_mips_subqh_r_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x1111222212345678LL;
+  v2i16_b = (v2i16) {0x1, 0x2};
+  v2i16_c = (v2i16) {0x3, 0x4};
+  a64_s = 0x1111222212345682LL;
+  a64_r = __builtin_mips_dpax_w_ph (a64_a, v2i16_b, v2i16_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x9999111112345678LL;
+  v2i16_b = (v2i16) {0x1, 0x2};
+  v2i16_c = (v2i16) {0x3, 0x4};
+  a64_s = 0x999911111234566eLL;
+  a64_r = __builtin_mips_dpsx_w_ph (a64_a, v2i16_b, v2i16_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x70000000;
+  v2q15_b = (v2q15) {0x4000, 0x2000};
+  v2q15_c = (v2q15) {0x2000, 0x4000};
+  a64_s = 0x98000000;
+  a64_r = __builtin_mips_dpaqx_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x70000000;
+  v2q15_b = (v2q15) {0x4000, 0x2000};
+  v2q15_c = (v2q15) {0x2000, 0x4000};
+  a64_s = 0x7fffffff;
+  a64_r = __builtin_mips_dpaqx_sa_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0x70000000;
+  v2q15_b = (v2q15) {0x4000, 0x2000};
+  v2q15_c = (v2q15) {0x2000, 0x4000};
+  a64_s = 0x48000000;
+  a64_r = __builtin_mips_dpsqx_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+#ifndef __mips64
+  a64_a = 0xFFFFFFFF80000000LL;
+  v2q15_b = (v2q15) {0x4000, 0x2000};
+  v2q15_c = (v2q15) {0x2000, 0x4000};
+  a64_s = 0xFFFFFFFF80000000LL;
+  a64_r = __builtin_mips_dpsqx_sa_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/msub-4.c b/gcc/testsuite/gcc.target/nanomips/msub-4.c
new file mode 100644
index 00000000000..e5845e6cab5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/msub-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* This test requires widening_mul */
+/* { dg-options "-mdspr3 -mgp32 -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tmsub\t\\\$ac" 2 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+  return z - (long long) y * x;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+  long long t = (long long) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z -= t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/msubu-4.c b/gcc/testsuite/gcc.target/nanomips/msubu-4.c
new file mode 100644
index 00000000000..a8e13dc5c0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/msubu-4.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* This test requires widening_mul */
+/* { dg-options "-mdspr3 -mgp32 -fexpensive-optimizations" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tmsubu\t\\\$ac" 2 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return z - (ull) y * x;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z -= t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/nanomips-dsp-accinit-2.c b/gcc/testsuite/gcc.target/nanomips/nanomips-dsp-accinit-2.c
new file mode 100644
index 00000000000..6f31f4ee813
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/nanomips-dsp-accinit-2.c
@@ -0,0 +1,23 @@
+/* { dg-options "-mdspr3 -mgp32" } */
+/* References to RESULT within the loop need to have a higher frequency than
+   references to RESULT outside the loop, otherwise there is no reason
+   to prefer multiply/accumulator registers over GPRs.  */
+/* { dg-skip-if "requires register frequencies" { *-*-* } { "-O0" "-Os" } { "" } } */
+
+/* Check that the zero-initialization of the accumulator feeding into
+   the madd is done by means of an mthi & mtlo pair instead of a
+   "mult $0,$0" instruction.  */
+
+long long f (int n, int *v, int m)
+{
+  long long result = 0;
+  int i;
+
+  for (i = 0; i < n; i++)
+    result = __builtin_mips_madd (result, v[i], m);
+  return result;
+}
+
+/* { dg-final { scan-assembler "mult\t\[^\n\]*\\\$zero" } } */
+/* { dg-final { scan-assembler-not "\tmthi\t" } } */
+/* { dg-final { scan-assembler-not "\tmtlo\t" } } */
diff --git a/gcc/testsuite/gcc.target/nanomips/nanomips-dsp.c b/gcc/testsuite/gcc.target/nanomips/nanomips-dsp.c
new file mode 100644
index 00000000000..3d2ffd6de23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/nanomips-dsp.c
@@ -0,0 +1,1160 @@
+/* Test MIPS32 DSP instructions */
+/* { dg-do compile } */
+/* { dg-options "-mgp32 -mdspr3 (REQUIRES_STDLIB)" } */
+/* { dg-final { scan-assembler "\taddq.ph\t" } } */
+/* { dg-final { scan-assembler "\taddq_s.ph\t" } } */
+/* { dg-final { scan-assembler "\taddq_s.w\t" } } */
+/* { dg-final { scan-assembler "\taddu.qb\t" } } */
+/* { dg-final { scan-assembler "\taddu_s.qb\t" } } */
+/* { dg-final { scan-assembler "\tsubq.ph\t" } } */
+/* { dg-final { scan-assembler "\tsubq_s.ph\t" } } */
+/* { dg-final { scan-assembler "\tsubq_s.w\t" } } */
+/* { dg-final { scan-assembler "\tsubu.qb\t" } } */
+/* { dg-final { scan-assembler "\tsubu_s.qb\t" } } */
+/* { dg-final { scan-assembler "\taddsc\t" } } */
+/* { dg-final { scan-assembler "\taddwc\t" } } */
+/* { dg-final { scan-assembler "\tmodsub\t" } } */
+/* { dg-final { scan-assembler "\traddu.w.qb\t" } } */
+/* { dg-final { scan-assembler "\tabsq_s.ph\t" } } */
+/* { dg-final { scan-assembler "\tabsq_s.w\t" } } */
+/* { dg-final { scan-assembler "\tprecrq.qb.ph\t" } } */
+/* { dg-final { scan-assembler "\tprecrq.ph.w\t" } } */
+/* { dg-final { scan-assembler "\tprecrq_rs.ph.w\t" } } */
+/* { dg-final { scan-assembler "\tprecrqu_s.qb.ph\t" } } */
+/* { dg-final { scan-assembler "\tpreceq.w.phl\t" } } */
+/* { dg-final { scan-assembler "\tpreceq.w.phr\t" } } */
+/* { dg-final { scan-assembler "\tprecequ.ph.qbl\t" } } */
+/* { dg-final { scan-assembler "\tprecequ.ph.qbr\t" } } */
+/* { dg-final { scan-assembler "\tprecequ.ph.qbla\t" } } */
+/* { dg-final { scan-assembler "\tprecequ.ph.qbra\t" } } */
+/* { dg-final { scan-assembler "\tpreceu.ph.qbl\t" } } */
+/* { dg-final { scan-assembler "\tpreceu.ph.qbr\t" } } */
+/* { dg-final { scan-assembler "\tpreceu.ph.qbla\t" } } */
+/* { dg-final { scan-assembler "\tpreceu.ph.qbra\t" } } */
+/* { dg-final { scan-assembler "\tshllv?.qb\t" } } */
+/* { dg-final { scan-assembler "\tshllv?.ph\t" } } */
+/* { dg-final { scan-assembler "\tshllv?_s.ph\t" } } */
+/* { dg-final { scan-assembler "\tshllv?_s.w\t" } } */
+/* { dg-final { scan-assembler "\tshrlv?.qb\t" } } */
+/* { dg-final { scan-assembler "\tshrav?.ph\t" } } */
+/* { dg-final { scan-assembler "\tshrav?_r.ph\t" } } */
+/* { dg-final { scan-assembler "\tshrav?_r.w\t" } } */
+/* { dg-final { scan-assembler "\tmuleu_s.ph.qbl\t" } } */
+/* { dg-final { scan-assembler "\tmuleu_s.ph.qbr\t" } } */
+/* { dg-final { scan-assembler "\tmulq_rs.ph\t" } } */
+/* { dg-final { scan-assembler "\tmuleq_s.w.phl\t" } } */
+/* { dg-final { scan-assembler "\tmuleq_s.w.phr\t" } } */
+/* { dg-final { scan-assembler "\tdpau.h.qbl\t" } } */
+/* { dg-final { scan-assembler "\tdpau.h.qbr\t" } } */
+/* { dg-final { scan-assembler "\tdpsu.h.qbl\t" } } */
+/* { dg-final { scan-assembler "\tdpsu.h.qbr\t" } } */
+/* { dg-final { scan-assembler "\tdpaq_s.w.ph\t" } } */
+/* { dg-final { scan-assembler "\tdpsq_s.w.ph\t" } } */
+/* { dg-final { scan-assembler "\tmulsaq_s.w.ph\t" } } */
+/* { dg-final { scan-assembler "\tdpaq_sa.l.w\t" } } */
+/* { dg-final { scan-assembler "\tdpsq_sa.l.w\t" } } */
+/* { dg-final { scan-assembler "\tmaq_s.w.phl\t" } } */
+/* { dg-final { scan-assembler "\tmaq_s.w.phr\t" } } */
+/* { dg-final { scan-assembler "\tmaq_sa.w.phl\t" } } */
+/* { dg-final { scan-assembler "\tmaq_sa.w.phr\t" } } */
+/* { dg-final { scan-assembler "\tbitrev\t" } } */
+/* { dg-final { scan-assembler "\tinsv\t" } } */
+/* { dg-final { scan-assembler "\treplv?.qb\t" } } */
+/* { dg-final { scan-assembler "\trepl.ph\t" } } */
+/* { dg-final { scan-assembler "\treplv.ph\t" } } */
+/* { dg-final { scan-assembler "\tcmpu.eq.qb\t" } } */
+/* { dg-final { scan-assembler "\tcmpu.lt.qb\t" } } */
+/* { dg-final { scan-assembler "\tcmpu.le.qb\t" } } */
+/* { dg-final { scan-assembler "\tcmpgu.eq.qb\t" } } */
+/* { dg-final { scan-assembler "\tcmpgu.lt.qb\t" } } */
+/* { dg-final { scan-assembler "\tcmpgu.le.qb\t" } } */
+/* { dg-final { scan-assembler "\tcmp.eq.ph\t" } } */
+/* { dg-final { scan-assembler "\tcmp.lt.ph\t" } } */
+/* { dg-final { scan-assembler "\tcmp.le.ph\t" } } */
+/* { dg-final { scan-assembler "\tpick.qb\t" } } */
+/* { dg-final { scan-assembler "\tpick.ph\t" } } */
+/* { dg-final { scan-assembler "\tpackrl.ph\t" } } */
+/* { dg-final { scan-assembler "\textrv?.w\t" } } */
+/* { dg-final { scan-assembler "\textrv?_s.h\t" } } */
+/* { dg-final { scan-assembler "\textrv?_r.w\t" } } */
+/* { dg-final { scan-assembler "\textrv?_rs.w\t" } } */
+/* { dg-final { scan-assembler "\textpv?\t" } } */
+/* { dg-final { scan-assembler "\textpdpv?\t" } } */
+/* { dg-final { scan-assembler "\tshilov?\t" } } */
+/* { dg-final { scan-assembler "\tmthlip\t" } } */
+/* { dg-final { scan-assembler "\tmfhi\t" } } */
+/* { dg-final { scan-assembler "\tmflo\t" } } */
+/* { dg-final { scan-assembler "\tmthi\t" } } */
+/* { dg-final { scan-assembler "\tmtlo\t" } } */
+/* { dg-final { scan-assembler "\twrdsp\t" } } */
+/* { dg-final { scan-assembler "\trddsp\t" } } */
+/* { dg-final { scan-assembler "\tlbux?\t" } } */
+/* { dg-final { scan-assembler "\tlhx?\t" } } */
+/* { dg-final { scan-assembler "\tlwx?\t" } } */
+/* { dg-final { scan-assembler "\tbposge32c\t" } } */
+/* { dg-final { scan-assembler "\tmadd\t" } } */
+/* { dg-final { scan-assembler "\tmaddu\t" } } */
+/* { dg-final { scan-assembler "\tmsub\t" } } */
+/* { dg-final { scan-assembler "\tmsubu\t" } } */
+/* { dg-final { scan-assembler "\tmult\t" } } */
+/* { dg-final { scan-assembler "\tmultu\t" } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef signed char v4i8 __attribute__ ((vector_size(4)));
+typedef short v2q15 __attribute__ ((vector_size(4)));
+
+typedef int q31;
+typedef int i32;
+typedef unsigned int ui32;
+typedef long long a64;
+
+void test_MIPS_DSP (void);
+
+char array[100];
+int little_endian;
+
+int main ()
+{
+  int i;
+
+  union { long long ll; int i[2]; } endianness_test;
+  endianness_test.ll = 1;
+  little_endian = endianness_test.i[0];
+
+  for (i = 0; i < 100; i++)
+    array[i] = i;
+
+  test_MIPS_DSP ();
+
+  exit (0);
+}
+
+v2q15 add_v2q15 (v2q15 a, v2q15 b)
+{
+  return __builtin_mips_addq_ph (a, b);
+}
+
+v4i8 add_v4i8 (v4i8 a, v4i8 b)
+{
+  return __builtin_mips_addu_qb (a, b);
+}
+
+v2q15 sub_v2q15 (v2q15 a, v2q15 b)
+{
+  return __builtin_mips_subq_ph (a, b);
+}
+
+v4i8 sub_v4i8 (v4i8 a, v4i8 b)
+{
+  return __builtin_mips_subu_qb (a, b);
+}
+
+void test_MIPS_DSP ()
+{
+  v4i8 v4i8_a,v4i8_b,v4i8_c,v4i8_r,v4i8_s;
+  v2q15 v2q15_a,v2q15_b,v2q15_c,v2q15_r,v2q15_s;
+  q31 q31_a,q31_b,q31_c,q31_r,q31_s;
+  /* To protect the multiplication-related tests from being optimized
+     at compile time.  */
+  volatile i32 i32_a,i32_b,i32_c,i32_r,i32_s;
+  volatile ui32 ui32_a,ui32_b,ui32_c;
+  a64 a64_a,a64_b,a64_c,a64_r,a64_s;
+
+  void *ptr_a;
+  int r,s;
+  long long lr,ls;
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x81bd, 0x6789};
+  v2q15_r = add_v2q15 (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x7fff, 0x6789};
+  v2q15_r = __builtin_mips_addq_s_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_b = 0x71234567;
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_addq_s_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0xf1, 0xbd, 0x67, 0x89};
+  v4i8_r = add_v4i8 (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0xff, 0xbd, 0x67, 0x89};
+  v4i8_r = __builtin_mips_addu_s_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0xa2ab, 0x4567};
+  v2q15_r = sub_v2q15 (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x8000, 0x4567};
+  v2q15_r = __builtin_mips_subq_s_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_b = 0x71234567;
+  q31_s = 0xfedcba99;
+  q31_r = __builtin_mips_subq_s_w (q31_a, q31_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0xf3, 0xab, 0x45, 0x67};
+  v4i8_r = sub_v4i8 (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0xff, 0x89, 0x11, 0x11};
+  v4i8_s = (v4i8) {0x0, 0x0, 0x45, 0x67};
+  v4i8_r = __builtin_mips_subu_s_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0xf5678900;
+  i32_b = 0x7abcdef0;
+  i32_s = 0x702467f0;
+  i32_r = __builtin_mips_addsc (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x75678900;
+  i32_b = 0x7abcdef0;
+  i32_s = 0xf02467f1;
+  i32_r = __builtin_mips_addwc (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0;
+  i32_b = 0x00000901;
+  i32_s = 9;
+  i32_r = __builtin_mips_modsub (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  i32_s = 0x1f4;
+  i32_r = __builtin_mips_raddu_w_qb (v4i8_a);
+  if (i32_r != i32_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x8134};
+  v2q15_s = (v2q15) {0x7fff, 0x7ecc};
+  v2q15_r = __builtin_mips_absq_s_ph (v2q15_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = (q31) 0x80000000;
+  q31_s = (q31) 0x7fffffff;
+  q31_r = __builtin_mips_absq_s_w (q31_a);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x9999, 0x5612};
+  v2q15_b = (v2q15) {0x5612, 0x3333};
+  if (little_endian)
+    v4i8_s = (v4i8) {0x56, 0x33, 0x99, 0x56};
+  else
+    v4i8_s = (v4i8) {0x99, 0x56, 0x56, 0x33};
+  v4i8_r = __builtin_mips_precrq_qb_ph (v2q15_a, v2q15_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x12348678;
+  q31_b = 0x44445555;
+  if (little_endian)
+    v2q15_s = (v2q15) {0x4444, 0x1234};
+  else
+    v2q15_s = (v2q15) {0x1234, 0x4444};
+  v2q15_r = __builtin_mips_precrq_ph_w (q31_a, q31_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x12348678;
+  q31_b = 0x44445555;
+  if (little_endian)
+    v2q15_s = (v2q15) {0x4444, 0x1235};
+  else
+    v2q15_s = (v2q15) {0x1235, 0x4444};
+  v2q15_r = __builtin_mips_precrq_rs_ph_w (q31_a, q31_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x9999, 0x5612};
+  v2q15_b = (v2q15) {0x5612, 0x3333};
+  if (little_endian)
+    v4i8_s = (v4i8) {0xac, 0x66, 0x00, 0xac};
+  else
+    v4i8_s = (v4i8) {0x00, 0xac, 0xac, 0x66};
+  v4i8_r = __builtin_mips_precrqu_s_qb_ph (v2q15_a, v2q15_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3589, 0x4444};
+  if (little_endian)
+    q31_s = 0x44440000;
+  else
+    q31_s = 0x35890000;
+  q31_r = __builtin_mips_preceq_w_phl (v2q15_a);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x3589, 0x4444};
+  if (little_endian)
+    q31_s = 0x35890000;
+  else
+    q31_s = 0x44440000;
+  q31_r = __builtin_mips_preceq_w_phr (v2q15_a);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  else
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  v2q15_r = __builtin_mips_precequ_ph_qbl (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  else
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  v2q15_r = __builtin_mips_precequ_ph_qbr (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  else
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  v2q15_r = __builtin_mips_precequ_ph_qbla (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x0900, 0x2b00};
+  else
+    v2q15_s = (v2q15) {0x2b00, 0x1980};
+  v2q15_r = __builtin_mips_precequ_ph_qbra (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x56, 0x33};
+  else
+    v2q15_s = (v2q15) {0x12, 0x56};
+  v2q15_r = __builtin_mips_preceu_ph_qbl (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x56, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x12, 0x56};
+  else
+    v2q15_s = (v2q15) {0x56, 0x33};
+  v2q15_r = __builtin_mips_preceu_ph_qbr (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x99, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x99, 0x33};
+  else
+    v2q15_s = (v2q15) {0x12, 0x56};
+  v2q15_r = __builtin_mips_preceu_ph_qbla (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x99, 0x56, 0x33};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x12, 0x56};
+  else
+    v2q15_s = (v2q15) {0x99, 0x33};
+  v2q15_r = __builtin_mips_preceu_ph_qbra (v4i8_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_s = (v4i8) {0xc8, 0xd0, 0x58, 0xe0};
+  v4i8_r = __builtin_mips_shll_qb (v4i8_a, 2);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  i32_b = 1;
+  v4i8_s = (v4i8) {0xe4, 0x68, 0xac, 0xf0};
+  v4i8_r = __builtin_mips_shll_qb (v4i8_a, i32_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d0, 0x59e0};
+  v2q15_r = __builtin_mips_shll_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 1;
+  v2q15_s = (v2q15) {0x2468, 0xacf0};
+  v2q15_r = __builtin_mips_shll_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d0, 0x7fff};
+  v2q15_r = __builtin_mips_shll_s_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 1;
+  v2q15_s = (v2q15) {0x2468, 0x7fff};
+  v2q15_r = __builtin_mips_shll_s_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_shll_s_w (q31_a, 2);
+  if (q31_r != q31_s)
+    abort ();
+
+  q31_a = 0x70000000;
+  i32_b = 1;
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_shll_s_w (q31_a, i32_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  v4i8_s = (v4i8) {0x3c, 0xd, 0x15, 0x1e};
+  v4i8_r = __builtin_mips_shrl_qb (v4i8_a, 2);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0xf2, 0x34, 0x56, 0x78};
+  i32_b = 1;
+  v4i8_s = (v4i8) {0x79, 0x1a, 0x2b, 0x3c};
+  v4i8_r = __builtin_mips_shrl_qb (v4i8_a, i32_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d, 0x159e};
+  v2q15_r = __builtin_mips_shra_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 1;
+  v2q15_s = (v2q15) {0x91a, 0x2b3c};
+  v2q15_r = __builtin_mips_shra_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_s = (v2q15) {0x48d, 0x159e};
+  v2q15_r = __builtin_mips_shra_r_ph (v2q15_a, 2);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  i32_b = 3;
+  v2q15_s = (v2q15) {0x247, 0xacf};
+  v2q15_r = __builtin_mips_shra_r_ph (v2q15_a, i32_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  q31_a = 0x70000000;
+  q31_s = 0x1c000000;
+  q31_r = __builtin_mips_shra_r_w (q31_a, 2);
+  if (q31_r != q31_s)
+    abort ();
+
+  q31_a = 0x70000004;
+  i32_b = 3;
+  q31_s = 0x0e000001;
+  q31_r = __builtin_mips_shra_r_w (q31_a, i32_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x1, 0x2, 0x3, 0x4};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  if (little_endian)
+    v2q15_s = (v2q15) {0xffff, 0x4444};
+  else
+    v2q15_s = (v2q15) {0x6f89, 0x2222};
+  v2q15_r = __builtin_mips_muleu_s_ph_qbl (v4i8_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x1, 0x2, 0x3, 0x4};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x6f89, 0x2222};
+  else
+    v2q15_s = (v2q15) {0xffff, 0x4444};
+  v2q15_r = __builtin_mips_muleu_s_ph_qbr (v4i8_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x6f89, 0x1111};
+  v2q15_s = (v2q15) {0x0fdd, 0x0b87};
+  v2q15_r = __builtin_mips_mulq_rs_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x8000};
+  v2q15_b = (v2q15) {0x8000, 0x8000};
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_muleq_s_w_phl (v2q15_a, v2q15_b);
+  if (q31_r != q31_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x8000, 0x8000};
+  v2q15_b = (v2q15) {0x8000, 0x8000};
+  q31_s = 0x7fffffff;
+  q31_r = __builtin_mips_muleq_s_w_phr (v2q15_a, v2q15_b);
+  if (q31_r != q31_s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x22222f27;
+  else
+    a64_s = 0x222238d9;
+  a64_r = __builtin_mips_dpau_h_qbl (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x222238d9;
+  else
+    a64_s = 0x22222f27;
+  a64_r = __builtin_mips_dpau_h_qbr (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x2221f2fb;
+  else
+    a64_s = 0x2221e949;
+  a64_r = __builtin_mips_dpsu_h_qbl (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x22221111;
+  v4i8_b = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_c = (v4i8) {0xaa, 0x89, 0x11, 0x34};
+  if (little_endian)
+    a64_s = 0x2221e949;
+  else
+    a64_s = 0x2221f2fb;
+  a64_r = __builtin_mips_dpsu_h_qbr (a64_a, v4i8_b, v4i8_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x5678};
+  v2q15_c = (v2q15) {0x8000, 0x1111};
+  a64_s = 0x8b877d00;
+  a64_r = __builtin_mips_dpaq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x5678};
+  v2q15_c = (v2q15) {0x8000, 0x1111};
+  a64_s = 0xffffffff7478a522LL;
+  a64_r = __builtin_mips_dpsq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x5678};
+  v2q15_c = (v2q15) {0x8000, 0x1111};
+  if (little_endian)
+    a64_s = 0xffffffff8b877d02LL;
+  else
+    a64_s = 0x7478a520;
+  a64_r = __builtin_mips_mulsaq_s_w_ph (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  q31_b = 0x80000000;
+  q31_c = 0x80000000;
+  a64_s = 0x7fffffffffffffffLL;
+  a64_r = __builtin_mips_dpaq_sa_l_w (a64_a, q31_b, q31_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  q31_b = 0x80000000;
+  q31_c = 0x80000000;
+  a64_s = 0x8000000000001112LL;
+  a64_r = __builtin_mips_dpsq_sa_l_w (a64_a, q31_b, q31_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x1115;
+  else
+    a64_s = 0x80001110;
+  a64_r = __builtin_mips_maq_s_w_phl (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x80001110;
+  else
+    a64_s = 0x1115;
+  a64_r = __builtin_mips_maq_s_w_phr (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x1115;
+  else
+    a64_s = 0x7fffffff;
+  a64_r = __builtin_mips_maq_sa_w_phl (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x00001111;
+  v2q15_b = (v2q15) {0x8000, 0x1};
+  v2q15_c = (v2q15) {0x8000, 0x2};
+  if (little_endian)
+    a64_s = 0x7fffffff;
+  else
+    a64_s = 0x1115;
+  a64_r = __builtin_mips_maq_sa_w_phr (a64_a, v2q15_b, v2q15_c);
+  if (a64_r != a64_s)
+    abort ();
+#endif
+
+  i32_a = 0x12345678;
+  i32_s = 0x00001e6a;
+  i32_r = __builtin_mips_bitrev (i32_a);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x00000208; // pos is 8, size is 4
+  __builtin_mips_wrdsp (i32_a, 31);
+  i32_a = 0x12345678;
+  i32_b = 0x87654321;
+  i32_s = 0x12345178;
+  i32_r = __builtin_mips_insv (i32_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_s = (v4i8) {1, 1, 1, 1};
+  v4i8_r = __builtin_mips_repl_qb (1);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 99;
+  v4i8_s = (v4i8) {99, 99, 99, 99};
+  v4i8_r = __builtin_mips_repl_qb (i32_a);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  v2q15_s = (v2q15) {30, 30};
+  v2q15_r = __builtin_mips_repl_ph (30);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x5612;
+  v2q15_s = (v2q15) {0x5612, 0x5612};
+  v2q15_r = __builtin_mips_repl_ph (i32_a);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x03000000;
+  else
+    i32_s = 0x0c000000;
+  __builtin_mips_cmpu_eq_qb (v4i8_a, v4i8_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x04000000;
+  else
+    i32_s = 0x02000000;
+  __builtin_mips_cmpu_lt_qb (v4i8_a, v4i8_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x07000000;
+  else
+    i32_s = 0x0e000000;
+  __builtin_mips_cmpu_le_qb (v4i8_a, v4i8_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x3;
+  else
+    i32_s = 0xc;
+  i32_r=__builtin_mips_cmpgu_eq_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x4;
+  else
+    i32_s = 0x2;
+  i32_r = __builtin_mips_cmpgu_lt_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x12, 0x34, 0x78, 0x56};
+  if (little_endian)
+    i32_s = 0x7;
+  else
+    i32_s = 0xe;
+  i32_r = __builtin_mips_cmpgu_le_qb (v4i8_a, v4i8_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  __builtin_mips_wrdsp (0,31); // Clear all condition code bits.
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  if (little_endian)
+    i32_s = 0x01000000;
+  else
+    i32_s = 0x02000000;
+  __builtin_mips_cmp_eq_ph (v2q15_a, v2q15_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  if (little_endian)
+    i32_s = 0x02000000;
+  else
+    i32_s = 0x01000000;
+  __builtin_mips_cmp_lt_ph (v2q15_a, v2q15_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  i32_s = 0x03000000;
+  __builtin_mips_cmp_le_ph (v2q15_a, v2q15_b);
+  i32_r = __builtin_mips_rddsp (16);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0a000000; // cc: 0000 1010
+  __builtin_mips_wrdsp (i32_a, 31);
+  v4i8_a = (v4i8) {0x12, 0x34, 0x56, 0x78};
+  v4i8_b = (v4i8) {0x21, 0x43, 0x65, 0x87};
+  if (little_endian)
+    v4i8_s = (v4i8) {0x21, 0x34, 0x65, 0x78};
+  else
+    v4i8_s = (v4i8) {0x12, 0x43, 0x56, 0x87};
+  v4i8_r = __builtin_mips_pick_qb (v4i8_a, v4i8_b);
+  r = (int) v4i8_r;
+  s = (int) v4i8_s;
+  if (r != s)
+    abort ();
+
+  i32_a = 0x02000000; // cc: 0000 0010
+  __builtin_mips_wrdsp (i32_a, 31);
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x2143, 0x6587};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x2143, 0x5678};
+  else
+    v2q15_s = (v2q15) {0x1234, 0x6587};
+  v2q15_r = __builtin_mips_pick_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+  v2q15_a = (v2q15) {0x1234, 0x5678};
+  v2q15_b = (v2q15) {0x1234, 0x7856};
+  if (little_endian)
+    v2q15_s = (v2q15) {0x7856, 0x1234};
+  else
+    v2q15_s = (v2q15) {0x5678, 0x1234};
+  v2q15_r = __builtin_mips_packrl_ph (v2q15_a, v2q15_b);
+  r = (int) v2q15_r;
+  s = (int) v2q15_s;
+  if (r != s)
+    abort ();
+
+#ifndef __mips64
+  a64_a = 0x1234567887654321LL;
+  i32_s = 0x88765432;
+  i32_r = __builtin_mips_extr_w (a64_a, 4);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887658321LL;
+  i32_s = 0x56788766;
+  i32_r = __builtin_mips_extr_r_w (a64_a, 16);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x12345677fffffff8LL;
+  i32_s = 0x7fffffff;
+  i32_r = __builtin_mips_extr_rs_w (a64_a, 4);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887658321LL;
+  i32_s = 0x7fff;
+  i32_r = __builtin_mips_extr_s_h (a64_a, 16);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x0000007887658321LL;
+  i32_b = 24;
+  i32_s = 0x7887;
+  i32_r = __builtin_mips_extr_s_h (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887654321LL;
+  i32_b = 4;
+  i32_s = 0x88765432;
+  i32_r = __builtin_mips_extr_w (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887658321LL;
+  i32_b = 16;
+  i32_s = 0x56788766;
+  i32_r = __builtin_mips_extr_r_w (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x12345677fffffff8LL;
+  i32_b = 4;
+  i32_s = 0x7fffffff;
+  i32_r = __builtin_mips_extr_rs_w (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_s = 8;
+  i32_r = __builtin_mips_extp (a64_a, 3); // extract 4 bits
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_b = 7; // size is 8. NOTE!! we should use 7
+  i32_s = 0x87;
+  i32_r = __builtin_mips_extp (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_s = 8;
+  i32_r = __builtin_mips_extpdp (a64_a, 3); // extract 4 bits
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_s = 0x0000021b; // pos is 27
+  i32_r = __builtin_mips_rddsp (31);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x0000021f; // pos is 31
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_b = 11; // size is 12. NOTE!!! We should use 11
+  i32_s = 0x876;
+  i32_r = __builtin_mips_extpdp (a64_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_s = 0x00000213; // pos is 19
+  i32_r = __builtin_mips_rddsp (31);
+  if (i32_r != i32_s)
+    abort ();
+
+  a64_a = 0x1234567887654321LL;
+  a64_s = 0x0012345678876543LL;
+  a64_r = __builtin_mips_shilo (a64_a, 8);
+  if (a64_r != a64_s)
+    abort ();
+
+  a64_a = 0x1234567887654321LL;
+  i32_b = -16;
+  a64_s = 0x5678876543210000LL;
+  a64_r = __builtin_mips_shilo (a64_a, i32_b);
+  if (a64_r != a64_s)
+    abort ();
+
+  i32_a = 0x0;
+  __builtin_mips_wrdsp (i32_a, 31);
+  a64_a = 0x1234567887654321LL;
+  i32_b = 0x11112222;
+  a64_s = 0x8765432111112222LL;
+  a64_r = __builtin_mips_mthlip (a64_a, i32_b);
+  if (a64_r != a64_s)
+    abort ();
+  i32_s = 32;
+  i32_r = __builtin_mips_rddsp (31);
+  if (i32_r != i32_s)
+    abort ();
+#endif
+
+  i32_a = 0x1357a468;
+  __builtin_mips_wrdsp (i32_a, 63);
+  i32_s = 0x03572428;
+  i32_r = __builtin_mips_rddsp (63);
+  if (i32_r != i32_s)
+    abort ();
+
+  ptr_a = &array;
+  i32_b = 37;
+  i32_s = 37;
+  i32_r = __builtin_mips_lbux (ptr_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  ptr_a = &array;
+  i32_b = 38;
+  if (little_endian)
+    i32_s = 0x2726;
+  else
+    i32_s = 0x2627;
+  i32_r = __builtin_mips_lhx (ptr_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  ptr_a = &array;
+  i32_b = 40;
+  if (little_endian)
+    i32_s = 0x2b2a2928;
+  else
+    i32_s = 0x28292a2b;
+  i32_r = __builtin_mips_lwx (ptr_a, i32_b);
+  if (i32_r != i32_s)
+    abort ();
+
+  i32_a = 0x00000220; // pos is 32, size is 4
+  __builtin_mips_wrdsp (i32_a, 63);
+  i32_s = 1;
+  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
+}
+
diff --git a/gcc/testsuite/gcc.target/nanomips/nanomips-dspr3-type-1.c b/gcc/testsuite/gcc.target/nanomips/nanomips-dspr3-type-1.c
new file mode 100644
index 00000000000..6e31c491d64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/nanomips-dspr3-type-1.c
@@ -0,0 +1,30 @@
+/* Test MIPS32 DSP instructions */
+/* { dg-do compile } */
+/* { dg-options "-mdspr3" } */
+/* { dg-final { scan-assembler "\taddq.ph\t" } } */
+/* { dg-final { scan-assembler "\taddu.qb\t" } } */
+/* { dg-final { scan-assembler "\tsubq.ph\t" } } */
+/* { dg-final { scan-assembler "\tsubu.qb\t" } } */
+
+typedef char v4qi __attribute__ ((vector_size(4)));
+typedef short v2hi __attribute__ ((vector_size(4)));
+
+v2hi add_v2hi (v2hi a, v2hi b)
+{
+  return a + b;
+}
+
+v4qi add_v4qi (v4qi a, v4qi b)
+{
+  return a + b;
+}
+
+v2hi sub_v2hi (v2hi a, v2hi b)
+{
+  return a - b;
+}
+
+v4qi sub_v4qi (v4qi a, v4qi b)
+{
+  return a - b;
+}
diff --git a/gcc/testsuite/gcc.target/nanomips/nanomips-dspr3-type-2.c b/gcc/testsuite/gcc.target/nanomips/nanomips-dspr3-type-2.c
new file mode 100644
index 00000000000..d312bedfa0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nanomips/nanomips-dspr3-type-2.c
@@ -0,0 +1,12 @@
+/* Test MIPS32 DSP REV 2 instructions */
+/* { dg-do compile } */
+/* { dg-options "-mdspr3" } */
+/* { dg-final { scan-assembler "\tmul.ph\t" } } */
+
+typedef short v2hi __attribute__ ((vector_size(4)));
+
+v2hi mul_v2hi (v2hi a, v2hi b)
+{
+  return a * b;
+}
+
