| Index: runtime/vm/intermediate_language_x64.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_x64.cc (revision 17815)
|
| +++ runtime/vm/intermediate_language_x64.cc (working copy)
|
| @@ -2421,6 +2421,18 @@
|
| // currently we can't specify these registers because ParallelMoveResolver
|
| // assumes that XMM0 is free at all times.
|
| // TODO(vegorov): allow XMM0 to be used.
|
| + 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 =
|
| @@ -2435,6 +2447,12 @@
|
|
|
|
|
| void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + if (recognized_kind() == MethodRecognizer::kDoubleMod) {
|
| + // Preserve right argument.
|
| + __ pushq(RAX);
|
| + __ movsd(Address(RSP, 0), locs()->in(1).fpu_reg());
|
| + }
|
| +
|
| ASSERT(locs()->in(0).fpu_reg() == XMM1);
|
| __ EnterFrame(0);
|
| __ ReserveAlignedFrameSpace(0);
|
| @@ -2446,6 +2464,39 @@
|
| __ CallRuntime(TargetFunction());
|
| __ movaps(locs()->out().fpu_reg(), XMM0);
|
| __ 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(RSP, 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(1); // Remove preserved right argument.
|
| + }
|
| }
|
|
|
|
|
|
|