| Index: test/cctest/test-assembler-mips64.cc | 
| diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc | 
| index 9529dab2422b69f094aa5e7ae2940d9a901ab963..b0315343b51b50614ff12048c992f5842b9a5974 100644 | 
| --- a/test/cctest/test-assembler-mips64.cc | 
| +++ b/test/cctest/test-assembler-mips64.cc | 
| @@ -5934,5 +5934,128 @@ TEST(Trampoline) { | 
| CHECK_EQ(res, 0); | 
| } | 
|  | 
| +template <class T> | 
| +struct TestCaseMaddMsub { | 
| +  T fr, fs, ft, fd_add, fd_sub; | 
| +}; | 
| + | 
| +template <typename T, typename F> | 
| +void helper_madd_msub_maddf_msubf(F func) { | 
| +  CcTest::InitializeVM(); | 
| +  Isolate* isolate = CcTest::i_isolate(); | 
| +  HandleScope scope(isolate); | 
| +  MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); | 
| + | 
| +  T x = std::sqrt(static_cast<T>(2.0)); | 
| +  T y = std::sqrt(static_cast<T>(3.0)); | 
| +  T z = std::sqrt(static_cast<T>(5.0)); | 
| +  T x2 = 11.11, y2 = 22.22, z2 = 33.33; | 
| +  TestCaseMaddMsub<T> test_cases[] = { | 
| +      {x, y, z, 0.0, 0.0}, | 
| +      {x, y, -z, 0.0, 0.0}, | 
| +      {x, -y, z, 0.0, 0.0}, | 
| +      {x, -y, -z, 0.0, 0.0}, | 
| +      {-x, y, z, 0.0, 0.0}, | 
| +      {-x, y, -z, 0.0, 0.0}, | 
| +      {-x, -y, z, 0.0, 0.0}, | 
| +      {-x, -y, -z, 0.0, 0.0}, | 
| +      {-3.14, 0.2345, -123.000056, 0.0, 0.0}, | 
| +      {7.3, -23.257, -357.1357, 0.0, 0.0}, | 
| +      {x2, y2, z2, 0.0, 0.0}, | 
| +      {x2, y2, -z2, 0.0, 0.0}, | 
| +      {x2, -y2, z2, 0.0, 0.0}, | 
| +      {x2, -y2, -z2, 0.0, 0.0}, | 
| +      {-x2, y2, z2, 0.0, 0.0}, | 
| +      {-x2, y2, -z2, 0.0, 0.0}, | 
| +      {-x2, -y2, z2, 0.0, 0.0}, | 
| +      {-x2, -y2, -z2, 0.0, 0.0}, | 
| +  }; | 
| + | 
| +  if (std::is_same<T, float>::value) { | 
| +    __ lwc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr))); | 
| +    __ lwc1(f6, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fs))); | 
| +    __ lwc1(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, ft))); | 
| +    __ lwc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr))); | 
| +  } else if (std::is_same<T, double>::value) { | 
| +    __ ldc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr))); | 
| +    __ ldc1(f6, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fs))); | 
| +    __ ldc1(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, ft))); | 
| +    __ ldc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr))); | 
| +  } else { | 
| +    UNREACHABLE(); | 
| +  } | 
| + | 
| +  func(assm); | 
| + | 
| +  __ jr(ra); | 
| +  __ nop(); | 
| + | 
| +  CodeDesc desc; | 
| +  assm.GetCode(&desc); | 
| +  Handle<Code> code = isolate->factory()->NewCode( | 
| +      desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 
| +  F3 f = FUNCTION_CAST<F3>(code->entry()); | 
| + | 
| +  const size_t kTableLength = sizeof(test_cases) / sizeof(TestCaseMaddMsub<T>); | 
| +  TestCaseMaddMsub<T> tc; | 
| +  for (size_t i = 0; i < kTableLength; i++) { | 
| +    tc.fr = test_cases[i].fr; | 
| +    tc.fs = test_cases[i].fs; | 
| +    tc.ft = test_cases[i].ft; | 
| + | 
| +    (CALL_GENERATED_CODE(isolate, f, &tc, 0, 0, 0, 0)); | 
| + | 
| +    T res_add = tc.fr + (tc.fs * tc.ft); | 
| +    T res_sub; | 
| +    if (kArchVariant != kMips64r6) { | 
| +      res_sub = (tc.fs * tc.ft) - tc.fr; | 
| +    } else { | 
| +      res_sub = tc.fr - (tc.fs * tc.ft); | 
| +    } | 
| + | 
| +    CHECK_EQ(tc.fd_add, res_add); | 
| +    CHECK_EQ(tc.fd_sub, res_sub); | 
| +  } | 
| +} | 
| + | 
| +TEST(madd_msub_s) { | 
| +  if (kArchVariant == kMips64r6) return; | 
| +  helper_madd_msub_maddf_msubf<float>([](MacroAssembler& assm) { | 
| +    __ madd_s(f10, f4, f6, f8); | 
| +    __ swc1(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_add))); | 
| +    __ msub_s(f16, f4, f6, f8); | 
| +    __ swc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_sub))); | 
| +  }); | 
| +} | 
| + | 
| +TEST(madd_msub_d) { | 
| +  if (kArchVariant == kMips64r6) return; | 
| +  helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) { | 
| +    __ madd_d(f10, f4, f6, f8); | 
| +    __ sdc1(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add))); | 
| +    __ msub_d(f16, f4, f6, f8); | 
| +    __ sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub))); | 
| +  }); | 
| +} | 
| + | 
| +TEST(maddf_msubf_s) { | 
| +  if (kArchVariant != kMips64r6) return; | 
| +  helper_madd_msub_maddf_msubf<float>([](MacroAssembler& assm) { | 
| +    __ maddf_s(f4, f6, f8); | 
| +    __ swc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_add))); | 
| +    __ msubf_s(f16, f6, f8); | 
| +    __ swc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_sub))); | 
| +  }); | 
| +} | 
| + | 
| +TEST(maddf_msubf_d) { | 
| +  if (kArchVariant != kMips64r6) return; | 
| +  helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) { | 
| +    __ maddf_d(f4, f6, f8); | 
| +    __ sdc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add))); | 
| +    __ msubf_d(f16, f6, f8); | 
| +    __ sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub))); | 
| +  }); | 
| +} | 
|  | 
| #undef __ | 
|  |