Index: test/cctest/test-assembler-x64.cc |
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc |
index 3d305b650e807280961b334b502042911aad103c..23d0be64ae74f3e519ea7e1149848dd6e4caf08e 100644 |
--- a/test/cctest/test-assembler-x64.cc |
+++ b/test/cctest/test-assembler-x64.cc |
@@ -736,4 +736,454 @@ TEST(AssemblerX64SSE) { |
F6 f = FUNCTION_CAST<F6>(code->entry()); |
CHECK_EQ(2, f(1.0, 2.0)); |
} |
+ |
+ |
+typedef int (*F7)(double x, double y, double z); |
+TEST(AssemblerX64FMA_sd) { |
+ CcTest::InitializeVM(); |
+ if (!CpuFeatures::IsSupported(FMA3)) return; |
+ |
+ Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); |
+ HandleScope scope(isolate); |
+ v8::internal::byte buffer[1024]; |
+ MacroAssembler assm(isolate, buffer, sizeof buffer); |
+ { |
+ CpuFeatureScope fscope(&assm, FMA3); |
+ Label exit; |
+ // argument in xmm0, xmm1 and xmm2 |
+ // xmm0 * xmm1 + xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulsd(xmm3, xmm1); |
+ __ addsd(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ __ subq(rsp, Immediate(kDoubleSize)); // For memory operand |
+ // vfmadd132sd |
+ __ movl(rax, Immediate(1)); // Test number |
+ __ movaps(xmm8, xmm0); |
+ __ vfmadd132sd(xmm8, xmm2, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfmadd213sd(xmm8, xmm0, xmm2); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfmadd231sd(xmm8, xmm0, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfmadd132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfmadd132sd(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movsd(Operand(rsp, 0), xmm2); |
+ __ vfmadd213sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfmadd231sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // xmm0 * xmm1 - xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulsd(xmm3, xmm1); |
+ __ subsd(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ // vfmsub132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ vfmsub132sd(xmm8, xmm2, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfmsub213sd(xmm8, xmm0, xmm2); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfmsub231sd(xmm8, xmm0, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfmsub132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfmsub132sd(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movsd(Operand(rsp, 0), xmm2); |
+ __ vfmsub213sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfmsub231sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ |
+ // - xmm0 * xmm1 + xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulsd(xmm3, xmm1); |
+ __ Move(xmm4, (uint64_t)1 << 63); |
+ __ xorpd(xmm3, xmm4); |
+ __ addsd(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ // vfnmadd132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ vfnmadd132sd(xmm8, xmm2, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfnmadd213sd(xmm8, xmm0, xmm2); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmadd231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfnmadd231sd(xmm8, xmm0, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfnmadd132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfnmadd132sd(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmadd213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movsd(Operand(rsp, 0), xmm2); |
+ __ vfnmadd213sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmadd231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfnmadd231sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ |
+ // - xmm0 * xmm1 - xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulsd(xmm3, xmm1); |
+ __ Move(xmm4, (uint64_t)1 << 63); |
+ __ xorpd(xmm3, xmm4); |
+ __ subsd(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ // vfnmsub132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ vfnmsub132sd(xmm8, xmm2, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfnmsub213sd(xmm8, xmm0, xmm2); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmsub231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfnmsub231sd(xmm8, xmm0, xmm1); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfnmsub132sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfnmsub132sd(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmsub213sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movsd(Operand(rsp, 0), xmm2); |
+ __ vfnmsub213sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmsub231sd |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movsd(Operand(rsp, 0), xmm1); |
+ __ vfnmsub231sd(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomisd(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ |
+ __ xorl(rax, rax); |
+ __ bind(&exit); |
+ __ addq(rsp, Immediate(kDoubleSize)); |
+ __ ret(0); |
+ } |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Handle<Code> code = isolate->factory()->NewCode( |
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
+#ifdef OBJECT_PRINT |
+ OFStream os(stdout); |
+ code->Print(os); |
+#endif |
+ |
+ F7 f = FUNCTION_CAST<F7>(code->entry()); |
+ CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414)); |
+} |
+ |
+ |
+typedef int (*F8)(float x, float y, float z); |
+TEST(AssemblerX64FMA_ss) { |
+ CcTest::InitializeVM(); |
+ if (!CpuFeatures::IsSupported(FMA3)) return; |
+ |
+ Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate()); |
+ HandleScope scope(isolate); |
+ v8::internal::byte buffer[1024]; |
+ MacroAssembler assm(isolate, buffer, sizeof buffer); |
+ { |
+ CpuFeatureScope fscope(&assm, FMA3); |
+ Label exit; |
+ // arguments in xmm0, xmm1 and xmm2 |
+ // xmm0 * xmm1 + xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulss(xmm3, xmm1); |
+ __ addss(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ __ subq(rsp, Immediate(kDoubleSize)); // For memory operand |
+ // vfmadd132ss |
+ __ movl(rax, Immediate(1)); // Test number |
+ __ movaps(xmm8, xmm0); |
+ __ vfmadd132ss(xmm8, xmm2, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfmadd213ss(xmm8, xmm0, xmm2); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfmadd231ss(xmm8, xmm0, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfmadd132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfmadd132ss(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movss(Operand(rsp, 0), xmm2); |
+ __ vfmadd213ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfmadd231ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // xmm0 * xmm1 - xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulss(xmm3, xmm1); |
+ __ subss(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ // vfmsub132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ vfmsub132ss(xmm8, xmm2, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfmsub213ss(xmm8, xmm0, xmm2); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfmsub231ss(xmm8, xmm0, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfmsub132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfmsub132ss(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movss(Operand(rsp, 0), xmm2); |
+ __ vfmsub213ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfmsub231ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ |
+ // - xmm0 * xmm1 + xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulss(xmm3, xmm1); |
+ __ Move(xmm4, (uint32_t)1 << 31); |
+ __ xorps(xmm3, xmm4); |
+ __ addss(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ // vfnmadd132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ vfnmadd132ss(xmm8, xmm2, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmadd213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfnmadd213ss(xmm8, xmm0, xmm2); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmadd231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfnmadd231ss(xmm8, xmm0, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfnmadd132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfnmadd132ss(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmadd213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movss(Operand(rsp, 0), xmm2); |
+ __ vfnmadd213ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmadd231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfnmadd231ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ |
+ // - xmm0 * xmm1 - xmm2 |
+ __ movaps(xmm3, xmm0); |
+ __ mulss(xmm3, xmm1); |
+ __ Move(xmm4, (uint32_t)1 << 31); |
+ __ xorps(xmm3, xmm4); |
+ __ subss(xmm3, xmm2); // Expected result in xmm3 |
+ |
+ // vfnmsub132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ vfnmsub132ss(xmm8, xmm2, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfmsub213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ vfnmsub213ss(xmm8, xmm0, xmm2); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmsub231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ vfnmsub231ss(xmm8, xmm0, xmm1); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ // vfnmsub132ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm0); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfnmsub132ss(xmm8, xmm2, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmsub213ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm1); |
+ __ movss(Operand(rsp, 0), xmm2); |
+ __ vfnmsub213ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ // vfnmsub231ss |
+ __ incq(rax); |
+ __ movaps(xmm8, xmm2); |
+ __ movss(Operand(rsp, 0), xmm1); |
+ __ vfnmsub231ss(xmm8, xmm0, Operand(rsp, 0)); |
+ __ ucomiss(xmm8, xmm3); |
+ __ j(not_equal, &exit); |
+ |
+ |
+ __ xorl(rax, rax); |
+ __ bind(&exit); |
+ __ addq(rsp, Immediate(kDoubleSize)); |
+ __ ret(0); |
+ } |
+ |
+ CodeDesc desc; |
+ assm.GetCode(&desc); |
+ Handle<Code> code = isolate->factory()->NewCode( |
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
+#ifdef OBJECT_PRINT |
+ OFStream os(stdout); |
+ code->Print(os); |
+#endif |
+ |
+ F8 f = FUNCTION_CAST<F8>(code->entry()); |
+ CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f)); |
+} |
#undef __ |