| Index: runtime/vm/intermediate_language_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_ia32.cc (revision 13352)
|
| +++ runtime/vm/intermediate_language_ia32.cc (working copy)
|
| @@ -2395,12 +2395,15 @@
|
|
|
| LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const {
|
| const intptr_t kNumInputs = 2;
|
| - const intptr_t kNumTemps = 1;
|
| + const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| summary->set_in(0, Location::RequiresXmmRegister());
|
| summary->set_in(1, Location::RegisterLocation(ECX));
|
| summary->set_temp(0, Location::RequiresRegister());
|
| + if (op_kind() == Token::kSHL) {
|
| + summary->set_temp(1, Location::RequiresRegister());
|
| + }
|
| summary->set_out(Location::SameAsFirstInput());
|
| return summary;
|
| }
|
| @@ -2408,38 +2411,55 @@
|
|
|
| void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| XmmRegister left = locs()->in(0).xmm_reg();
|
| - Register temp = locs()->temp(0).reg();
|
| ASSERT(locs()->in(1).reg() == ECX);
|
| ASSERT(locs()->out().xmm_reg() == left);
|
|
|
| + Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
| + kDeoptShiftMintOp);
|
| + Label done;
|
| + __ testl(ECX, ECX);
|
| + __ j(ZERO, &done); // Shift by 0 is a nop.
|
| + __ subl(ESP, Immediate(2 * kWordSize));
|
| + __ movq(Address(ESP, 0), left);
|
| + // Deoptimize if shift count is > 31.
|
| + // sarl operation masks the count to 5 bits and
|
| + // shrd is undefined with count > operand size (32)
|
| + // TODO(fschneider): Support shift counts > 31 without deoptimization.
|
| + __ SmiUntag(ECX);
|
| + const Immediate kCountLimit = Immediate(31);
|
| + __ cmpl(ECX, kCountLimit);
|
| + __ j(ABOVE, deopt);
|
| switch (op_kind()) {
|
| case Token::kSHR: {
|
| - Label* deopt = compiler->AddDeoptStub(deopt_id(),
|
| - kDeoptShiftMintOp);
|
| - __ subl(ESP, Immediate(2 * kWordSize));
|
| - __ movq(Address(ESP, 0), left);
|
| - // Deoptimize if shift count is > 31.
|
| - // sarl operation masks the count to 5 bits and
|
| - // shrd is undefined with count > operand size (32)
|
| - // TODO(fschneider): Support shift counts > 31 without deoptimization.
|
| - __ SmiUntag(ECX);
|
| - const Immediate kCountLimit = Immediate(31);
|
| - __ cmpl(ECX, kCountLimit);
|
| - __ j(ABOVE, deopt);
|
| - __ movl(temp, Address(ESP, 1 * kWordSize));
|
| + Register temp = locs()->temp(0).reg();
|
| + __ movl(temp, Address(ESP, 1 * kWordSize)); // High half.
|
| __ shrd(Address(ESP, 0), temp); // Shift count in CL.
|
| __ sarl(Address(ESP, 1 * kWordSize), ECX); // Shift count in CL.
|
| - __ movq(left, Address(ESP, 0));
|
| - __ addl(ESP, Immediate(2 * kWordSize));
|
| break;
|
| }
|
| - case Token::kSHL:
|
| - UNIMPLEMENTED();
|
| + case Token::kSHL: {
|
| + Register temp1 = locs()->temp(0).reg();
|
| + Register temp2 = locs()->temp(1).reg();
|
| + __ movl(temp1, Address(ESP, 0 * kWordSize)); // Low 32 bits.
|
| + __ movl(temp2, Address(ESP, 1 * kWordSize)); // High 32 bits.
|
| + __ shll(Address(ESP, 0 * kWordSize), ECX); // Shift count in CL.
|
| + __ shld(Address(ESP, 1 * kWordSize), temp1); // Shift count in CL.
|
| + // Check for overflow by shifting back the high 32 bits
|
| + // and comparing with the input.
|
| + __ movl(temp1, temp2);
|
| + __ movl(temp2, Address(ESP, 1 * kWordSize));
|
| + __ sarl(temp2, ECX);
|
| + __ cmpl(temp1, temp2);
|
| + __ j(NOT_EQUAL, deopt);
|
| break;
|
| + }
|
| default:
|
| UNREACHABLE();
|
| break;
|
| }
|
| + __ movq(left, Address(ESP, 0));
|
| + __ addl(ESP, Immediate(2 * kWordSize));
|
| + __ Bind(&done);
|
| }
|
|
|
|
|
|
|