| Index: runtime/vm/intermediate_language_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_ia32.cc (revision 17815)
|
| +++ runtime/vm/intermediate_language_ia32.cc (working copy)
|
| @@ -2551,6 +2551,18 @@
|
|
|
|
|
| LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary() const {
|
| + if (recognized_kind() == MethodRecognizer::kDoubleMod) {
|
| + ASSERT(InputCount() == 2);
|
| + const intptr_t kNumTemps = 2;
|
| + LocationSummary* result =
|
| + new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
|
| + result->set_in(0, Location::FpuRegisterLocation(XMM1, Location::kDouble));
|
| + result->set_in(1, Location::FpuRegisterLocation(XMM2, Location::kDouble));
|
| + result->set_out(Location::FpuRegisterLocation(XMM1, Location::kDouble));
|
| + result->set_temp(0, Location::FpuRegisterLocation(XMM2, Location::kDouble));
|
| + result->set_temp(1, Location::FpuRegisterLocation(XMM3, Location::kDouble));
|
| + return result;
|
| + }
|
| ASSERT((InputCount() == 1) || (InputCount() == 2));
|
| const intptr_t kNumTemps = 0;
|
| LocationSummary* result =
|
| @@ -2565,6 +2577,13 @@
|
|
|
|
|
| void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + if (recognized_kind() == MethodRecognizer::kDoubleMod) {
|
| + // Preserve right argument.
|
| + __ pushl(EAX);
|
| + __ pushl(EAX);
|
| + __ movsd(Address(ESP, 0), locs()->in(1).fpu_reg());
|
| + }
|
| +
|
| __ EnterFrame(0);
|
| __ ReserveAlignedFrameSpace(kDoubleSize * InputCount());
|
| for (intptr_t i = 0; i < InputCount(); i++) {
|
| @@ -2574,6 +2593,39 @@
|
| __ fstpl(Address(ESP, 0));
|
| __ movsd(locs()->out().fpu_reg(), Address(ESP, 0));
|
| __ leave();
|
| +
|
| + if (recognized_kind() == MethodRecognizer::kDoubleMod) {
|
| + // Result of C call is remainder, convert it to modulo.
|
| + Label done, equal_zero, right_greater_equal_zero;
|
| + XmmRegister remainder = locs()->out().fpu_reg();
|
| + XmmRegister zero_temp = locs()->temp(0).fpu_reg();
|
| + XmmRegister right_temp = locs()->temp(1).fpu_reg();
|
| +
|
| + __ xorpd(zero_temp, zero_temp); // 0.0 -> 'temp'.
|
| + __ comisd(remainder, zero_temp);
|
| + __ j(PARITY_EVEN, &done, Assembler::kNearJump); // NaN -> false;
|
| + __ j(EQUAL, &equal_zero, Assembler::kNearJump);
|
| + __ j(ABOVE, &done, Assembler::kNearJump); // (remainder) > 0 -> done.
|
| + // remainder < 0.
|
| + // Load preserved right argument.
|
| + __ movsd(right_temp, Address(ESP, 0));
|
| + __ comisd(right_temp, zero_temp);
|
| + __ j(ABOVE_EQUAL, &right_greater_equal_zero, Assembler::kNearJump);
|
| + // right < 0.
|
| + __ subsd(remainder, right_temp);
|
| + __ jmp(&done, Assembler::kNearJump);
|
| +
|
| + __ Bind(&right_greater_equal_zero);
|
| + __ addsd(remainder, right_temp);
|
| + __ jmp(&done);
|
| +
|
| + __ Bind(&equal_zero);
|
| + // Switch to the positive 0.0 (just in case it was negative).
|
| + __ movsd(remainder, zero_temp);
|
| +
|
| + __ Bind(&done);
|
| + __ Drop(2); // Remove preserved right argument.
|
| + }
|
| }
|
|
|
|
|
|
|