| Index: runtime/vm/intermediate_language_arm.cc
|
| diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
|
| index a54102be53eb6b6faf7d6c2d8113aeea7b26fd70..fd12d679f0d59183f322839cdb1fb2112da2c3f5 100644
|
| --- a/runtime/vm/intermediate_language_arm.cc
|
| +++ b/runtime/vm/intermediate_language_arm.cc
|
| @@ -380,14 +380,13 @@ static Condition TokenKindToSmiCondition(Token::Kind kind) {
|
| LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
| if (operation_cid() == kMintCid) {
|
| - const intptr_t kNumTemps = 3;
|
| + const intptr_t kNumTemps = 0;
|
| LocationSummary* locs =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - locs->set_in(0, Location::RequiresFpuRegister());
|
| - locs->set_in(1, Location::RequiresFpuRegister());
|
| - locs->set_temp(0, Location::RequiresFpuRegister());
|
| - locs->set_temp(1, Location::RequiresRegister());
|
| - locs->set_temp(2, Location::RequiresRegister());
|
| + locs->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| + locs->set_in(1, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| locs->set_out(0, Location::RequiresRegister());
|
| return locs;
|
| }
|
| @@ -515,37 +514,32 @@ static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
|
| LocationSummary* locs,
|
| Token::Kind kind) {
|
| ASSERT(Token::IsEqualityOperator(kind));
|
| - const QRegister left = locs->in(0).fpu_reg();
|
| - const QRegister right = locs->in(1).fpu_reg();
|
| - const QRegister tmpq = locs->temp(0).fpu_reg();
|
| - const Register tmp_lo = locs->temp(1).reg();
|
| - const Register tmp_hi = locs->temp(2).reg();
|
| -
|
| - __ vceqqi(kWord, tmpq, left, right);
|
| - __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq));
|
| - // tmp_lo and tmp_hi must both be 0xffffffff.
|
| - __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi));
|
| + PairLocation* left_pair = locs->in(0).AsPairLocation();
|
| + Register left1 = left_pair->At(0).reg();
|
| + Register left2 = left_pair->At(1).reg();
|
| + PairLocation* right_pair = locs->in(1).AsPairLocation();
|
| + Register right1 = right_pair->At(0).reg();
|
| + Register right2 = right_pair->At(1).reg();
|
|
|
| - Condition true_condition = TokenKindToMintCondition(kind);
|
| - __ CompareImmediate(tmp_lo, 0xffffffff);
|
| - return true_condition;
|
| + // Compare lower.
|
| + __ cmp(left1, ShifterOperand(right1));
|
| + // Compare upper if lower is equal.
|
| + __ cmp(left2, ShifterOperand(right2), EQ);
|
| + return TokenKindToMintCondition(kind);
|
| }
|
|
|
|
|
| static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
|
| LocationSummary* locs,
|
| Token::Kind kind) {
|
| - const QRegister left = locs->in(0).fpu_reg();
|
| - const QRegister right = locs->in(1).fpu_reg();
|
| - const DRegister dleft0 = EvenDRegisterOf(left);
|
| - const DRegister dright0 = EvenDRegisterOf(right);
|
| - const SRegister sleft0 = EvenSRegisterOf(dleft0);
|
| - const SRegister sleft1 = OddSRegisterOf(dleft0);
|
| - const SRegister sright0 = EvenSRegisterOf(dright0);
|
| - const SRegister sright1 = OddSRegisterOf(dright0);
|
| + PairLocation* left_pair = locs->in(0).AsPairLocation();
|
| + Register left1 = left_pair->At(0).reg();
|
| + Register left2 = left_pair->At(1).reg();
|
| + PairLocation* right_pair = locs->in(1).AsPairLocation();
|
| + Register right1 = right_pair->At(0).reg();
|
| + Register right2 = right_pair->At(1).reg();
|
|
|
| - const Register tmp_left = locs->temp(0).reg();
|
| - const Register tmp_right = locs->temp(1).reg();
|
| + Register out = locs->temp(0).reg();
|
|
|
| // 64-bit comparison
|
| Condition hi_true_cond, hi_false_cond, lo_false_cond;
|
| @@ -568,25 +562,18 @@ static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
|
| }
|
|
|
| Label is_true, is_false, done;
|
| - __ vmovrs(tmp_left, sleft1);
|
| - __ vmovrs(tmp_right, sright1);
|
| - __ cmp(tmp_left, ShifterOperand(tmp_right));
|
| - __ b(&is_false, hi_false_cond);
|
| - __ b(&is_true, hi_true_cond);
|
| -
|
| - __ vmovrs(tmp_left, sleft0);
|
| - __ vmovrs(tmp_right, sright0);
|
| - __ cmp(tmp_left, ShifterOperand(tmp_right));
|
| - __ b(&is_false, lo_false_cond);
|
| - // Else is true.
|
| - __ b(&is_true);
|
| -
|
| - __ Bind(&is_false);
|
| - __ LoadImmediate(tmp_left, 0);
|
| - __ b(&done);
|
| - __ Bind(&is_true);
|
| - __ LoadImmediate(tmp_left, 1);
|
| + // Compare upper halves first.
|
| + __ cmp(left2, ShifterOperand(right2));
|
| + __ LoadImmediate(out, 0, hi_false_cond);
|
| + __ LoadImmediate(out, 1, hi_true_cond);
|
| + // If higher words aren't equal, skip comparing lower words.
|
| + __ b(&done, NE);
|
| +
|
| + __ cmp(left1, ShifterOperand(right1));
|
| + __ LoadImmediate(out, 1);
|
| + __ LoadImmediate(out, 0, lo_false_cond);
|
| __ Bind(&done);
|
| +
|
| return NegateCondition(lo_false_cond);
|
| }
|
|
|
| @@ -793,13 +780,14 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
| const intptr_t kNumTemps = 0;
|
| if (operation_cid() == kMintCid) {
|
| - const intptr_t kNumTemps = 2;
|
| + const intptr_t kNumTemps = 1;
|
| LocationSummary* locs =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - locs->set_in(0, Location::RequiresFpuRegister());
|
| - locs->set_in(1, Location::RequiresFpuRegister());
|
| + locs->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| + locs->set_in(1, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| locs->set_temp(0, Location::RequiresRegister());
|
| - locs->set_temp(1, Location::RequiresRegister());
|
| locs->set_out(0, Location::RequiresRegister());
|
| return locs;
|
| }
|
| @@ -1153,7 +1141,11 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
|
| } else {
|
| locs->set_out(0, Location::RequiresFpuRegister());
|
| }
|
| + } else if (representation() == kUnboxedMint) {
|
| + locs->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| } else {
|
| + ASSERT(representation() == kTagged);
|
| locs->set_out(0, Location::RequiresRegister());
|
| }
|
| return locs;
|
| @@ -1162,7 +1154,6 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
|
|
|
| void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| if ((representation() == kUnboxedDouble) ||
|
| - (representation() == kUnboxedMint) ||
|
| (representation() == kUnboxedFloat32x4) ||
|
| (representation() == kUnboxedInt32x4) ||
|
| (representation() == kUnboxedFloat64x2)) {
|
| @@ -1194,23 +1185,6 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| const QRegister result = locs()->out(0).fpu_reg();
|
| const DRegister dresult0 = EvenDRegisterOf(result);
|
| switch (class_id()) {
|
| - case kTypedDataInt32ArrayCid:
|
| - __ veorq(result, result, result);
|
| - __ ldr(TMP, element_address);
|
| - // Re-use the index register so we don't have to require a low-numbered
|
| - // Q register.
|
| - // Sign-extend into idx.
|
| - __ Asr(idx, TMP, 31);
|
| - __ vmovdrr(dresult0, TMP, idx);
|
| - break;
|
| - case kTypedDataUint32ArrayCid:
|
| - __ veorq(result, result, result);
|
| - __ ldr(TMP, element_address);
|
| - // Re-use the index register so we don't have to require a low-numbered
|
| - // Q register.
|
| - __ LoadImmediate(idx, 0);
|
| - __ vmovdrr(dresult0, TMP, idx);
|
| - break;
|
| case kTypedDataFloat32ArrayCid:
|
| // Load single precision float.
|
| // vldrs does not support indexed addressing.
|
| @@ -1225,6 +1199,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| case kTypedDataFloat32x4ArrayCid:
|
| __ vldmd(IA, idx, dresult0, 2);
|
| break;
|
| + default:
|
| + UNREACHABLE();
|
| }
|
| return;
|
| }
|
| @@ -1267,7 +1243,34 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| UNREACHABLE();
|
| }
|
|
|
| - const Register result = locs()->out(0).reg();
|
| + if (representation() == kUnboxedMint) {
|
| + ASSERT(locs()->out(0).IsPairLocation());
|
| + PairLocation* result_pair = locs()->out(0).AsPairLocation();
|
| + Register result1 = result_pair->At(0).reg();
|
| + Register result2 = result_pair->At(1).reg();
|
| + switch (class_id()) {
|
| + case kTypedDataInt32ArrayCid:
|
| + // Load low word.
|
| + __ ldr(result1, element_address);
|
| + // Sign extend into high word.
|
| + __ SignFill(result2, result1);
|
| + break;
|
| + case kTypedDataUint32ArrayCid:
|
| + // Load low word.
|
| + __ ldr(result1, element_address);
|
| + // Zero high word.
|
| + __ eor(result2, result2, ShifterOperand(result2));
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| + return;
|
| + }
|
| +
|
| + ASSERT(representation() == kTagged);
|
| +
|
| + Register result = locs()->out(0).reg();
|
| switch (class_id()) {
|
| case kTypedDataInt8ArrayCid:
|
| ASSERT(index_scale() == 1);
|
| @@ -1384,11 +1387,16 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(bool opt) const {
|
| break;
|
| case kTypedDataInt32ArrayCid:
|
| case kTypedDataUint32ArrayCid:
|
| - // Mints are stored in Q registers. For smis, use a writable register
|
| - // because the value must be untagged before storing.
|
| - locs->set_in(2, value()->IsSmiValue()
|
| - ? Location::WritableRegister()
|
| - : Location::FpuRegisterLocation(Q7));
|
| + // For smis, use a writable register because the value must be untagged
|
| + // before storing. Mints are stored in register pairs.
|
| + if (value()->IsSmiValue()) {
|
| + locs->set_in(2, Location::WritableRegister());
|
| + } else {
|
| + // We only move the lower 32-bits so we don't care where the high bits
|
| + // are located.
|
| + locs->set_in(2, Location::Pair(Location::RequiresRegister(),
|
| + Location::Any()));
|
| + }
|
| break;
|
| case kTypedDataFloat32ArrayCid:
|
| // Need low register (<= Q7).
|
| @@ -1573,10 +1581,9 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ str(value, element_address);
|
| } else {
|
| ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
|
| - const QRegister value = locs()->in(2).fpu_reg();
|
| - ASSERT(value == Q7);
|
| - __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value)));
|
| - __ str(TMP, element_address);
|
| + PairLocation* value_pair = locs()->in(2).AsPairLocation();
|
| + Register value1 = value_pair->At(0).reg();
|
| + __ str(value1, element_address);
|
| }
|
| break;
|
| }
|
| @@ -5726,20 +5733,19 @@ void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
| static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
|
| Label* overflow,
|
| - QRegister result,
|
| - Register tmp_hi, Register tmp_lo) {
|
| - __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
|
| + Register result_lo,
|
| + Register result_hi) {
|
| // Compare upper half.
|
| Label check_lower;
|
| - __ CompareImmediate(tmp_hi, 0x00200000);
|
| + __ CompareImmediate(result_hi, 0x00200000);
|
| __ b(overflow, GT);
|
| __ b(&check_lower, NE);
|
|
|
| - __ CompareImmediate(tmp_lo, 0);
|
| + __ CompareImmediate(result_lo, 0);
|
| __ b(overflow, HI);
|
|
|
| __ Bind(&check_lower);
|
| - __ CompareImmediate(tmp_hi, -0x00200000);
|
| + __ CompareImmediate(result_hi, -0x00200000);
|
| __ b(overflow, LT);
|
| // Anything in the lower part would make the number bigger than the lower
|
| // bound, so we are done.
|
| @@ -5748,19 +5754,13 @@ static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
|
|
|
| LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 1;
|
| - const intptr_t value_cid = value()->Type()->ToCid();
|
| - const bool needs_writable_input = (value_cid != kMintCid);
|
| - const bool needs_temp = (value_cid != kMintCid);
|
| - const intptr_t kNumTemps = needs_temp ? 1 : 0;
|
| + const intptr_t kNumTemps = 1;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - summary->set_in(0, needs_writable_input
|
| - ? Location::WritableRegister()
|
| - : Location::RequiresRegister());
|
| - if (needs_temp) {
|
| - summary->set_temp(0, Location::RequiresRegister());
|
| - }
|
| - summary->set_out(0, Location::RequiresFpuRegister());
|
| + summary->set_in(0, Location::RequiresRegister());
|
| + summary->set_temp(0, Location::RequiresRegister());
|
| + summary->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| return summary;
|
| }
|
|
|
| @@ -5768,19 +5768,30 @@ LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
|
| void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| const intptr_t value_cid = value()->Type()->ToCid();
|
| const Register value = locs()->in(0).reg();
|
| - const QRegister result = locs()->out(0).fpu_reg();
|
| + PairLocation* result_pair = locs()->out(0).AsPairLocation();
|
| + Register result_lo = result_pair->At(0).reg();
|
| + Register result_hi = result_pair->At(1).reg();
|
| + ASSERT(value != result_lo);
|
| + ASSERT(value != result_hi);
|
|
|
| __ Comment("UnboxIntegerInstr");
|
| - __ veorq(result, result, result);
|
| if (value_cid == kMintCid) {
|
| - __ LoadDFromOffset(EvenDRegisterOf(result), value,
|
| - Mint::value_offset() - kHeapObjectTag);
|
| + // Load low word.
|
| + __ LoadFromOffset(kWord,
|
| + result_lo,
|
| + value,
|
| + Mint::value_offset() - kHeapObjectTag);
|
| + // Load high word.
|
| + __ LoadFromOffset(kWord,
|
| + result_hi,
|
| + value,
|
| + Mint::value_offset() - kHeapObjectTag + kWordSize);
|
| } else if (value_cid == kSmiCid) {
|
| - const Register temp = locs()->temp(0).reg();
|
| - __ SmiUntag(value);
|
| - // Sign extend value into temp.
|
| - __ Asr(temp, value, 31);
|
| - __ vmovdrr(EvenDRegisterOf(result), value, temp);
|
| + // Load Smi into result_lo.
|
| + __ mov(result_lo, ShifterOperand(value));
|
| + // Untag.
|
| + __ SmiUntag(result_lo);
|
| + __ SignFill(result_hi, result_lo);
|
| } else {
|
| const Register temp = locs()->temp(0).reg();
|
| Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
| @@ -5792,16 +5803,26 @@ void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| __ b(deopt, NE);
|
|
|
| // It's a Mint.
|
| - __ LoadDFromOffset(EvenDRegisterOf(result), value,
|
| - Mint::value_offset() - kHeapObjectTag);
|
| + // Load low word.
|
| + __ LoadFromOffset(kWord,
|
| + result_lo,
|
| + value,
|
| + Mint::value_offset() - kHeapObjectTag);
|
| + // Load high word.
|
| + __ LoadFromOffset(kWord,
|
| + result_hi,
|
| + value,
|
| + Mint::value_offset() - kHeapObjectTag + kWordSize);
|
| __ b(&done);
|
|
|
| // It's a Smi.
|
| __ Bind(&is_smi);
|
| - __ SmiUntag(value);
|
| - // Sign extend into temp.
|
| - __ Asr(temp, value, 31);
|
| - __ vmovdrr(EvenDRegisterOf(result), value, temp);
|
| + // Load Smi into result_lo.
|
| + __ mov(result_lo, ShifterOperand(value));
|
| + // Untag.
|
| + __ SmiUntag(result_lo);
|
| + // Sign extend result_lo into result_hi.
|
| + __ SignFill(result_hi, result_lo);
|
| __ Bind(&done);
|
| }
|
| }
|
| @@ -5809,14 +5830,14 @@ void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
| LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 1;
|
| - const intptr_t kNumTemps = 2;
|
| + const intptr_t kNumTemps = 1;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs,
|
| kNumTemps,
|
| LocationSummary::kCallOnSlowPath);
|
| - summary->set_in(0, Location::RequiresFpuRegister());
|
| + summary->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| summary->set_temp(0, Location::RequiresRegister());
|
| - summary->set_temp(1, Location::RequiresRegister());
|
| summary->set_out(0, Location::RequiresRegister());
|
| return summary;
|
| }
|
| @@ -5858,40 +5879,39 @@ class BoxIntegerSlowPath : public SlowPathCode {
|
| void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
|
| compiler->AddSlowPathCode(slow_path);
|
| -
|
| - const Register out_reg = locs()->out(0).reg();
|
| - const QRegister value = locs()->in(0).fpu_reg();
|
| - const DRegister dvalue0 = EvenDRegisterOf(value);
|
| - const Register lo = locs()->temp(0).reg();
|
| - const Register hi = locs()->temp(1).reg();
|
| + PairLocation* value_pair = locs()->in(0).AsPairLocation();
|
| + Register value_lo = value_pair->At(0).reg();
|
| + Register value_hi = value_pair->At(1).reg();
|
| + Register tmp = locs()->temp(0).reg();
|
| + Register out_reg = locs()->out(0).reg();
|
|
|
| // Unboxed operations produce smis or mint-sized values.
|
| // Check if value fits into a smi.
|
| __ Comment("BoxIntegerInstr");
|
| Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
|
| - __ vmovrrd(lo, hi, dvalue0);
|
| - __ CompareImmediate(hi, 0);
|
| + // Check high word.
|
| + __ CompareImmediate(value_hi, 0);
|
| __ b(&maybe_pos_smi, EQ);
|
|
|
| - __ CompareImmediate(hi, -1);
|
| + __ CompareImmediate(value_hi, -1);
|
| __ b(&maybe_neg_smi, EQ);
|
| __ b(¬_smi);
|
|
|
| __ Bind(&maybe_pos_smi);
|
| - __ CompareImmediate(lo, kSmiMax);
|
| + __ CompareImmediate(value_lo, kSmiMax);
|
| __ b(&is_smi, LS); // unsigned lower or same.
|
| __ b(¬_smi);
|
|
|
| __ Bind(&maybe_neg_smi);
|
| - __ CompareImmediate(lo, 0);
|
| + __ CompareImmediate(value_lo, 0);
|
| __ b(¬_smi, GE);
|
| - __ CompareImmediate(lo, kSmiMin);
|
| + __ CompareImmediate(value_lo, kSmiMin);
|
| __ b(¬_smi, LT);
|
|
|
| // lo is a Smi. Tag it and return.
|
| __ Bind(&is_smi);
|
| - __ SmiTag(lo);
|
| - __ mov(out_reg, ShifterOperand(lo));
|
| + __ mov(out_reg, ShifterOperand(value_lo));
|
| + __ SmiTag(out_reg);
|
| __ b(&done);
|
|
|
| // Not a smi. Box it.
|
| @@ -5900,148 +5920,169 @@ void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
|
| slow_path->entry_label(),
|
| out_reg,
|
| - lo);
|
| + tmp);
|
| __ Bind(slow_path->exit_label());
|
| - __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag);
|
| + __ StoreToOffset(kWord,
|
| + value_lo,
|
| + out_reg,
|
| + Mint::value_offset() - kHeapObjectTag);
|
| + __ StoreToOffset(kWord,
|
| + value_hi,
|
| + out_reg,
|
| + Mint::value_offset() - kHeapObjectTag + kWordSize);
|
| __ Bind(&done);
|
| }
|
|
|
|
|
| LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
| - const intptr_t kNumTemps =
|
| - FLAG_throw_on_javascript_int_overflow ? 2 : 0;
|
| + const intptr_t kNumTemps = 0;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - summary->set_in(0, Location::RequiresFpuRegister());
|
| - summary->set_in(1, Location::RequiresFpuRegister());
|
| - if (FLAG_throw_on_javascript_int_overflow) {
|
| - summary->set_temp(0, Location::RequiresRegister());
|
| - summary->set_temp(1, Location::RequiresRegister());
|
| - }
|
| - if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
|
| - // Need another temp for checking for overflow.
|
| - summary->AddTemp(Location::RequiresFpuRegister());
|
| - summary->AddTemp(Location::FpuRegisterLocation(Q7));
|
| - }
|
| - summary->set_out(0, Location::RequiresFpuRegister());
|
| + summary->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| + summary->set_in(1, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| + summary->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| return summary;
|
| }
|
|
|
|
|
| void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - const QRegister left = locs()->in(0).fpu_reg();
|
| - const QRegister right = locs()->in(1).fpu_reg();
|
| - const QRegister out = locs()->out(0).fpu_reg();
|
| + PairLocation* left_pair = locs()->in(0).AsPairLocation();
|
| + Register left_lo = left_pair->At(0).reg();
|
| + Register left_hi = left_pair->At(1).reg();
|
| + PairLocation* right_pair = locs()->in(1).AsPairLocation();
|
| + Register right_lo = right_pair->At(0).reg();
|
| + Register right_hi = right_pair->At(1).reg();
|
| + PairLocation* out_pair = locs()->out(0).AsPairLocation();
|
| + Register out_lo = out_pair->At(0).reg();
|
| + Register out_hi = out_pair->At(1).reg();
|
|
|
| Label* deopt = NULL;
|
| if (FLAG_throw_on_javascript_int_overflow) {
|
| deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
|
| }
|
| switch (op_kind()) {
|
| - case Token::kBIT_AND: __ vandq(out, left, right); break;
|
| - case Token::kBIT_OR: __ vorrq(out, left, right); break;
|
| - case Token::kBIT_XOR: __ veorq(out, left, right); break;
|
| + case Token::kBIT_AND: {
|
| + __ and_(out_lo, left_lo, ShifterOperand(right_lo));
|
| + __ and_(out_hi, left_hi, ShifterOperand(right_hi));
|
| + }
|
| + break;
|
| + case Token::kBIT_OR: {
|
| + __ orr(out_lo, left_lo, ShifterOperand(right_lo));
|
| + __ orr(out_hi, left_hi, ShifterOperand(right_hi));
|
| + }
|
| + break;
|
| + case Token::kBIT_XOR: {
|
| + __ eor(out_lo, left_lo, ShifterOperand(right_lo));
|
| + __ eor(out_hi, left_hi, ShifterOperand(right_hi));
|
| + }
|
| + break;
|
| case Token::kADD:
|
| case Token::kSUB: {
|
| - const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
|
| - const QRegister tmp = locs()->temp(tmpidx).fpu_reg();
|
| - const QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
|
| - ASSERT(ro == Q7);
|
| if (!FLAG_throw_on_javascript_int_overflow) {
|
| deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
|
| }
|
| if (op_kind() == Token::kADD) {
|
| - __ vaddqi(kWordPair, out, left, right);
|
| + __ adds(out_lo, left_lo, ShifterOperand(right_lo));
|
| + __ adcs(out_hi, left_hi, ShifterOperand(right_hi));
|
| } else {
|
| ASSERT(op_kind() == Token::kSUB);
|
| - __ vsubqi(kWordPair, out, left, right);
|
| + __ subs(out_lo, left_lo, ShifterOperand(right_lo));
|
| + __ sbcs(out_hi, left_hi, ShifterOperand(right_hi));
|
| }
|
| - __ veorq(ro, out, left);
|
| - __ veorq(tmp, left, right);
|
| - __ vandq(ro, tmp, ro);
|
| - __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
|
| - // If TMP < 0, there was overflow.
|
| - __ cmp(TMP, ShifterOperand(0));
|
| - __ b(deopt, LT);
|
| + // Deopt on overflow.
|
| + __ b(deopt, VS);
|
| break;
|
| }
|
| - default: UNREACHABLE(); break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| }
|
| if (FLAG_throw_on_javascript_int_overflow) {
|
| - const Register tmp1 = locs()->temp(0).reg();
|
| - const Register tmp2 = locs()->temp(1).reg();
|
| - EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
|
| + EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
|
| }
|
| }
|
|
|
|
|
| LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 2;
|
| - const intptr_t kNumTemps =
|
| - FLAG_throw_on_javascript_int_overflow ? 2 : 1;
|
| + const intptr_t kNumTemps = 1;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - summary->set_in(0, Location::RequiresFpuRegister());
|
| + summary->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| summary->set_in(1, Location::WritableRegister());
|
| - summary->set_temp(0, Location::FpuRegisterLocation(Q7));
|
| - if (FLAG_throw_on_javascript_int_overflow) {
|
| - summary->set_temp(1, Location::RequiresRegister());
|
| - }
|
| - summary->set_out(0, Location::RequiresFpuRegister());
|
| + summary->set_temp(0, Location::RequiresRegister());
|
| + summary->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| return summary;
|
| }
|
|
|
|
|
| void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - const QRegister value = locs()->in(0).fpu_reg();
|
| - const Register shift = locs()->in(1).reg();
|
| - const QRegister temp = locs()->temp(0).fpu_reg();
|
| - ASSERT(temp == Q7);
|
| - const QRegister out = locs()->out(0).fpu_reg();
|
| - const DRegister dtemp0 = EvenDRegisterOf(temp);
|
| - const SRegister stemp0 = EvenSRegisterOf(dtemp0);
|
| - const SRegister stemp1 = OddSRegisterOf(dtemp0);
|
| + PairLocation* left_pair = locs()->in(0).AsPairLocation();
|
| + Register left_lo = left_pair->At(0).reg();
|
| + Register left_hi = left_pair->At(1).reg();
|
| + Register shift = locs()->in(1).reg();
|
| + PairLocation* out_pair = locs()->out(0).AsPairLocation();
|
| + Register out_lo = out_pair->At(0).reg();
|
| + Register out_hi = out_pair->At(1).reg();
|
| + Register temp = locs()->temp(0).reg();
|
|
|
| Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
|
| Label done;
|
|
|
| + // Early out if shift is 0.
|
| __ CompareImmediate(shift, 0);
|
| - __ vmovq(out, value);
|
| + __ mov(out_lo, ShifterOperand(left_lo));
|
| + __ mov(out_hi, ShifterOperand(left_hi));
|
| __ b(&done, EQ);
|
| +
|
| + // Untag shift count.
|
| __ SmiUntag(shift);
|
|
|
| - // vshlq takes the shift value from low byte. Deopt if shift is
|
| - // outside of [0, 63].
|
| + // Deopt if shift is negative.
|
| + __ CompareImmediate(shift, 1);
|
| + __ b(deopt, LT);
|
| +
|
| + // Deopt if shift is larger than 63.
|
| __ CompareImmediate(shift, 63);
|
| __ b(deopt, GT);
|
| - __ CompareImmediate(shift, 0);
|
| - __ b(deopt, LT);
|
|
|
| - __ veorq(temp, temp, temp); // Zero out temp.
|
| switch (op_kind()) {
|
| case Token::kSHR: {
|
| - __ rsb(shift, shift, ShifterOperand(0)); // Negate shift.
|
| - __ vmovsr(stemp0, shift); // Move the shift into the low S register.
|
| - __ vshlqi(kWordPair, out, value, temp);
|
| + __ cmp(shift, ShifterOperand(32));
|
| +
|
| + __ mov(out_lo, ShifterOperand(out_hi), HI);
|
| + __ Asr(out_hi, out_hi, 31, HI);
|
| + __ sub(shift, shift, ShifterOperand(32), HI);
|
| +
|
| + __ rsb(temp, shift, ShifterOperand(32));
|
| + __ mov(temp, ShifterOperand(out_hi, LSL, temp));
|
| + __ orr(out_lo, temp, ShifterOperand(out_lo, LSR, shift));
|
| + __ Asr(out_hi, out_hi, shift);
|
| break;
|
| }
|
| case Token::kSHL: {
|
| - __ vmovsr(stemp0, shift); // Move the shift into the low S register.
|
| - __ vshlqu(kWordPair, out, value, temp);
|
| -
|
| - // check for overflow by shifting back and comparing.
|
| - __ rsb(shift, shift, ShifterOperand(0));
|
| - __ vmovsr(stemp0, shift);
|
| - __ vshlqi(kWordPair, temp, out, temp);
|
| - __ vceqqi(kWord, temp, temp, value);
|
| - // Low 64 bits of temp should be all 1's, otherwise temp != value and
|
| - // we deopt.
|
| - __ vmovrs(shift, stemp0);
|
| - __ CompareImmediate(shift, -1);
|
| - __ b(deopt, NE);
|
| - __ vmovrs(shift, stemp1);
|
| - __ CompareImmediate(shift, -1);
|
| + __ rsbs(temp, shift, ShifterOperand(32));
|
| + __ sub(temp, shift, ShifterOperand(32), MI);
|
| + __ mov(out_hi, ShifterOperand(out_lo, LSL, temp), MI);
|
| + __ mov(out_hi, ShifterOperand(out_hi, LSL, shift), PL);
|
| + __ orr(out_hi, out_hi, ShifterOperand(out_lo, LSR, temp), PL);
|
| + __ mov(out_lo, ShifterOperand(out_lo, LSL, shift));
|
| +
|
| + // Check for overflow.
|
| +
|
| + // Copy high word from output.
|
| + __ mov(temp, ShifterOperand(out_hi));
|
| + // Shift copy right.
|
| + __ Asr(temp, temp, shift);
|
| + // Compare with high word from input.
|
| + __ cmp(temp, ShifterOperand(left_hi));
|
| + // Overflow if they aren't equal.
|
| __ b(deopt, NE);
|
| break;
|
| }
|
| @@ -6052,42 +6093,43 @@ void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|
|
| __ Bind(&done);
|
| if (FLAG_throw_on_javascript_int_overflow) {
|
| - const Register tmp1 = locs()->in(1).reg();
|
| - const Register tmp2 = locs()->temp(1).reg();
|
| - EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
|
| + EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
|
| }
|
| }
|
|
|
|
|
| LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
|
| const intptr_t kNumInputs = 1;
|
| - const intptr_t kNumTemps =
|
| - FLAG_throw_on_javascript_int_overflow ? 2 : 0;
|
| + const intptr_t kNumTemps = 0;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| - summary->set_in(0, Location::RequiresFpuRegister());
|
| - summary->set_out(0, Location::RequiresFpuRegister());
|
| - if (FLAG_throw_on_javascript_int_overflow) {
|
| - summary->set_temp(0, Location::RequiresRegister());
|
| - summary->set_temp(1, Location::RequiresRegister());
|
| - }
|
| + summary->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| + summary->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| return summary;
|
| }
|
|
|
|
|
| void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| ASSERT(op_kind() == Token::kBIT_NOT);
|
| - const QRegister value = locs()->in(0).fpu_reg();
|
| - const QRegister out = locs()->out(0).fpu_reg();
|
| + PairLocation* left_pair = locs()->in(0).AsPairLocation();
|
| + Register left_lo = left_pair->At(0).reg();
|
| + Register left_hi = left_pair->At(1).reg();
|
| +
|
| + PairLocation* out_pair = locs()->out(0).AsPairLocation();
|
| + Register out_lo = out_pair->At(0).reg();
|
| + Register out_hi = out_pair->At(1).reg();
|
| +
|
| Label* deopt = NULL;
|
| +
|
| if (FLAG_throw_on_javascript_int_overflow) {
|
| deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
|
| }
|
| - __ vmvnq(out, value);
|
| + __ mvn(out_lo, ShifterOperand(left_lo));
|
| + __ mvn(out_hi, ShifterOperand(left_hi));
|
| if (FLAG_throw_on_javascript_int_overflow) {
|
| - const Register tmp1 = locs()->temp(0).reg();
|
| - const Register tmp2 = locs()->temp(1).reg();
|
| - EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
|
| + EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
|
| }
|
| }
|
|
|
|
|