| Index: runtime/vm/intermediate_language_mips.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_mips.cc (revision 24294)
|
| +++ runtime/vm/intermediate_language_mips.cc (working copy)
|
| @@ -1425,8 +1425,6 @@
|
| case kTypedDataUint8ArrayCid:
|
| case kTypedDataUint8ClampedArrayCid:
|
| case kOneByteStringCid:
|
| - locs->set_in(2, Location::RegisterOrSmiConstant(value()));
|
| - break;
|
| case kTypedDataInt16ArrayCid:
|
| case kTypedDataUint16ArrayCid:
|
| case kTypedDataInt32ArrayCid:
|
| @@ -1568,7 +1566,15 @@
|
| break;
|
| }
|
| case kTypedDataFloat32ArrayCid:
|
| + // Convert to single precision.
|
| + __ cvtsd(STMP1, locs()->in(2).fpu_reg());
|
| + // Store.
|
| + __ swc1(STMP1, element_address);
|
| + break;
|
| case kTypedDataFloat64ArrayCid:
|
| + __ StoreDToOffset(locs()->in(2).fpu_reg(), index.reg(),
|
| + FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
|
| + break;
|
| case kTypedDataFloat32x4ArrayCid:
|
| UNIMPLEMENTED();
|
| break;
|
| @@ -2257,8 +2263,8 @@
|
| __ BranchUnsignedGreaterEqual(
|
| right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt);
|
| }
|
| - __ SmiUntag(right);
|
| - __ sllv(result, left, right);
|
| + __ sra(TMP, right, kSmiTagMask); // SmiUntag right into TMP.
|
| + __ sllv(result, left, TMP);
|
| }
|
| return;
|
| }
|
| @@ -2285,8 +2291,8 @@
|
| // result = right < kBits ? left << right : result.
|
| __ movn(result, TMP1, CMPRES);
|
| } else {
|
| - __ SmiUntag(right);
|
| - __ sllv(result, left, right);
|
| + __ sra(TMP, right, kSmiTagSize);
|
| + __ sllv(result, left, TMP);
|
| }
|
| } else {
|
| if (right_needs_check) {
|
| @@ -2296,13 +2302,14 @@
|
| }
|
| // Left is not a constant.
|
| // Check if count too large for handling it inlined.
|
| - __ SmiUntag(right);
|
| - // Overflow test (preserve left and right);
|
| - __ sllv(TMP1, left, right);
|
| - __ srav(TMP1, TMP1, right);
|
| - __ bne(TMP1, left, deopt); // Overflow.
|
| + __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
|
| + // Overflow test (preserve left, right, and TMP);
|
| + Register temp = locs.temp(0).reg();
|
| + __ sllv(temp, left, TMP);
|
| + __ srav(temp, temp, TMP);
|
| + __ bne(temp, left, deopt); // Overflow.
|
| // Shift for result now we know there is no overflow.
|
| - __ sllv(result, left, right);
|
| + __ sll(result, left, TMP);
|
| }
|
| }
|
|
|
| @@ -2313,22 +2320,23 @@
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| if (op_kind() == Token::kTRUNCDIV) {
|
| + summary->set_in(0, Location::RequiresRegister());
|
| if (RightIsPowerOfTwoConstant()) {
|
| - summary->set_in(0, Location::RequiresRegister());
|
| ConstantInstr* right_constant = right()->definition()->AsConstant();
|
| summary->set_in(1, Location::Constant(right_constant->value()));
|
| - summary->set_out(Location::RequiresRegister());
|
| } else {
|
| - // Both inputs must be writable because they will be untagged.
|
| - summary->set_in(0, Location::WritableRegister());
|
| - summary->set_in(1, Location::WritableRegister());
|
| - summary->set_out(Location::RequiresRegister());
|
| + summary->set_in(1, Location::RequiresRegister());
|
| }
|
| + summary->AddTemp(Location::RequiresRegister());
|
| + summary->set_out(Location::RequiresRegister());
|
| return summary;
|
| }
|
| summary->set_in(0, Location::RequiresRegister());
|
| summary->set_in(1, Location::RegisterOrSmiConstant(right()));
|
| - if (op_kind() == Token::kADD) {
|
| + if (((op_kind() == Token::kSHL) && !is_truncating()) ||
|
| + (op_kind() == Token::kSHR)) {
|
| + summary->AddTemp(Location::RequiresRegister());
|
| + } else if (op_kind() == Token::kADD) {
|
| // Need an extra temp for the overflow detection code.
|
| summary->set_temp(0, Location::RequiresRegister());
|
| }
|
| @@ -2351,7 +2359,7 @@
|
| Register result = locs()->out().reg();
|
| Label* deopt = NULL;
|
| if (CanDeoptimize()) {
|
| - deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
| + deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
| }
|
|
|
| if (locs()->in(1).IsConstant()) {
|
| @@ -2425,10 +2433,11 @@
|
| ASSERT(kSmiTagSize == 1);
|
| __ sra(TMP, left, 31);
|
| ASSERT(shift_count > 1); // 1, -1 case handled above.
|
| + Register temp = locs()->temp(0).reg();
|
| __ srl(TMP, TMP, 32 - shift_count);
|
| - __ addu(left, left, TMP);
|
| + __ addu(temp, left, TMP);
|
| ASSERT(shift_count > 0);
|
| - __ sra(result, left, shift_count);
|
| + __ sra(result, temp, shift_count);
|
| if (value < 0) {
|
| __ subu(result, ZR, result);
|
| }
|
| @@ -2523,8 +2532,8 @@
|
| }
|
| case Token::kMUL: {
|
| __ TraceSimMsg("kMUL");
|
| - __ SmiUntag(left);
|
| - __ mult(left, right);
|
| + __ sra(TMP, left, kSmiTagSize);
|
| + __ mult(TMP, right);
|
| __ mflo(result);
|
| if (deopt != NULL) {
|
| __ mfhi(TMP1);
|
| @@ -2551,18 +2560,36 @@
|
| case Token::kTRUNCDIV: {
|
| // Handle divide by zero in runtime.
|
| __ beq(right, ZR, deopt);
|
| - __ SmiUntag(left);
|
| - __ SmiUntag(right);
|
| - __ div(left, right);
|
| + Register temp = locs()->temp(0).reg();
|
| + __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
|
| + __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
|
| + __ div(temp, TMP);
|
| __ mflo(result);
|
| // Check the corner case of dividing the 'MIN_SMI' with -1, in which
|
| // case we cannot tag the result.
|
| - __ BranchEqual(V0, 0x40000000, deopt);
|
| + __ BranchEqual(result, 0x40000000, deopt);
|
| __ SmiTag(result);
|
| break;
|
| }
|
| case Token::kSHR: {
|
| - UNIMPLEMENTED();
|
| + if (CanDeoptimize()) {
|
| + __ bltz(right, deopt);
|
| + }
|
| + __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
|
| + // sra operation masks the count to 5 bits.
|
| + const intptr_t kCountLimit = 0x1F;
|
| + Range* right_range = this->right()->definition()->range();
|
| + if ((right_range == NULL) ||
|
| + !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
|
| + Label ok;
|
| + __ BranchSignedLessEqual(TMP, kCountLimit, &ok);
|
| + __ LoadImmediate(TMP, kCountLimit);
|
| + __ Bind(&ok);
|
| + }
|
| + Register temp = locs()->temp(0).reg();
|
| + __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
|
| + __ srav(result, temp, TMP);
|
| + __ SmiTag(result);
|
| break;
|
| }
|
| case Token::kDIV: {
|
|
|