OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 71 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
72 locs->set_in(0, Location::RegisterLocation(R0)); | 72 locs->set_in(0, Location::RegisterLocation(R0)); |
73 return locs; | 73 return locs; |
74 } | 74 } |
75 | 75 |
76 | 76 |
77 // Attempt optimized compilation at return instruction instead of at the entry. | 77 // Attempt optimized compilation at return instruction instead of at the entry. |
78 // The entry needs to be patchable, no inlined objects are allowed in the area | 78 // The entry needs to be patchable, no inlined objects are allowed in the area |
79 // that will be overwritten by the patch instructions: a branch macro sequence. | 79 // that will be overwritten by the patch instructions: a branch macro sequence. |
80 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 80 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
81 Register result = locs()->in(0).reg(); | 81 const Register result = locs()->in(0).reg(); |
82 ASSERT(result == R0); | 82 ASSERT(result == R0); |
83 #if defined(DEBUG) | 83 #if defined(DEBUG) |
84 Label stack_ok; | 84 Label stack_ok; |
85 __ Comment("Stack Check"); | 85 __ Comment("Stack Check"); |
86 const intptr_t fp_sp_dist = | 86 const intptr_t fp_sp_dist = |
87 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 87 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
88 ASSERT(fp_sp_dist <= 0); | 88 ASSERT(fp_sp_dist <= 0); |
89 __ sub(R2, SP, ShifterOperand(FP)); | 89 __ sub(R2, SP, ShifterOperand(FP)); |
90 __ CompareImmediate(R2, fp_sp_dist); | 90 __ CompareImmediate(R2, fp_sp_dist); |
91 __ b(&stack_ok, EQ); | 91 __ b(&stack_ok, EQ); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 | 233 |
234 | 234 |
235 LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const { | 235 LocationSummary* LoadLocalInstr::MakeLocationSummary(bool opt) const { |
236 return LocationSummary::Make(0, | 236 return LocationSummary::Make(0, |
237 Location::RequiresRegister(), | 237 Location::RequiresRegister(), |
238 LocationSummary::kNoCall); | 238 LocationSummary::kNoCall); |
239 } | 239 } |
240 | 240 |
241 | 241 |
242 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 242 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
243 Register result = locs()->out(0).reg(); | 243 const Register result = locs()->out(0).reg(); |
244 __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize); | 244 __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize); |
245 } | 245 } |
246 | 246 |
247 | 247 |
248 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { | 248 LocationSummary* StoreLocalInstr::MakeLocationSummary(bool opt) const { |
249 return LocationSummary::Make(1, | 249 return LocationSummary::Make(1, |
250 Location::SameAsFirstInput(), | 250 Location::SameAsFirstInput(), |
251 LocationSummary::kNoCall); | 251 LocationSummary::kNoCall); |
252 } | 252 } |
253 | 253 |
254 | 254 |
255 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 255 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
256 Register value = locs()->in(0).reg(); | 256 const Register value = locs()->in(0).reg(); |
257 Register result = locs()->out(0).reg(); | 257 const Register result = locs()->out(0).reg(); |
258 ASSERT(result == value); // Assert that register assignment is correct. | 258 ASSERT(result == value); // Assert that register assignment is correct. |
259 __ str(value, Address(FP, local().index() * kWordSize)); | 259 __ str(value, Address(FP, local().index() * kWordSize)); |
260 } | 260 } |
261 | 261 |
262 | 262 |
263 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { | 263 LocationSummary* ConstantInstr::MakeLocationSummary(bool opt) const { |
264 return LocationSummary::Make(0, | 264 return LocationSummary::Make(0, |
265 Location::RequiresRegister(), | 265 Location::RequiresRegister(), |
266 LocationSummary::kNoCall); | 266 LocationSummary::kNoCall); |
267 } | 267 } |
268 | 268 |
269 | 269 |
270 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 270 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
271 // The register allocator drops constant definitions that have no uses. | 271 // The register allocator drops constant definitions that have no uses. |
272 if (!locs()->out(0).IsInvalid()) { | 272 if (!locs()->out(0).IsInvalid()) { |
273 Register result = locs()->out(0).reg(); | 273 const Register result = locs()->out(0).reg(); |
274 __ LoadObject(result, value()); | 274 __ LoadObject(result, value()); |
275 } | 275 } |
276 } | 276 } |
277 | 277 |
278 | 278 |
279 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(bool opt) const { | 279 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(bool opt) const { |
280 const intptr_t kNumInputs = 0; | 280 const intptr_t kNumInputs = 0; |
281 const intptr_t kNumTemps = 1; | 281 const intptr_t kNumTemps = 1; |
282 LocationSummary* locs = | 282 LocationSummary* locs = |
283 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 283 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 kNonBoolTypeErrorRuntimeEntry, | 347 kNonBoolTypeErrorRuntimeEntry, |
348 1, | 348 1, |
349 locs); | 349 locs); |
350 // We should never return here. | 350 // We should never return here. |
351 __ bkpt(0); | 351 __ bkpt(0); |
352 __ Bind(&done); | 352 __ Bind(&done); |
353 } | 353 } |
354 | 354 |
355 | 355 |
356 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 356 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
357 Register obj = locs()->in(0).reg(); | 357 const Register obj = locs()->in(0).reg(); |
358 Register result = locs()->out(0).reg(); | 358 const Register result = locs()->out(0).reg(); |
359 | 359 |
360 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 360 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
361 ASSERT(obj == result); | 361 ASSERT(obj == result); |
362 } | 362 } |
363 | 363 |
364 | 364 |
365 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 365 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
366 switch (kind) { | 366 switch (kind) { |
367 case Token::kEQ: return EQ; | 367 case Token::kEQ: return EQ; |
368 case Token::kNE: return NE; | 368 case Token::kNE: return NE; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 UNREACHABLE(); | 508 UNREACHABLE(); |
509 return VS; | 509 return VS; |
510 } | 510 } |
511 } | 511 } |
512 | 512 |
513 | 513 |
514 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 514 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
515 LocationSummary* locs, | 515 LocationSummary* locs, |
516 Token::Kind kind) { | 516 Token::Kind kind) { |
517 ASSERT(Token::IsEqualityOperator(kind)); | 517 ASSERT(Token::IsEqualityOperator(kind)); |
518 QRegister left = locs->in(0).fpu_reg(); | 518 const QRegister left = locs->in(0).fpu_reg(); |
519 QRegister right = locs->in(1).fpu_reg(); | 519 const QRegister right = locs->in(1).fpu_reg(); |
520 QRegister tmpq = locs->temp(0).fpu_reg(); | 520 const QRegister tmpq = locs->temp(0).fpu_reg(); |
521 Register tmp_lo = locs->temp(1).reg(); | 521 const Register tmp_lo = locs->temp(1).reg(); |
522 Register tmp_hi = locs->temp(2).reg(); | 522 const Register tmp_hi = locs->temp(2).reg(); |
523 | 523 |
524 __ vceqqi(kWord, tmpq, left, right); | 524 __ vceqqi(kWord, tmpq, left, right); |
525 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq)); | 525 __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq)); |
526 // tmp_lo and tmp_hi must both be 0xffffffff. | 526 // tmp_lo and tmp_hi must both be 0xffffffff. |
527 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi)); | 527 __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi)); |
528 | 528 |
529 Condition true_condition = TokenKindToMintCondition(kind); | 529 Condition true_condition = TokenKindToMintCondition(kind); |
530 __ CompareImmediate(tmp_lo, 0xffffffff); | 530 __ CompareImmediate(tmp_lo, 0xffffffff); |
531 return true_condition; | 531 return true_condition; |
532 } | 532 } |
533 | 533 |
534 | 534 |
535 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 535 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
536 LocationSummary* locs, | 536 LocationSummary* locs, |
537 Token::Kind kind) { | 537 Token::Kind kind) { |
538 QRegister left = locs->in(0).fpu_reg(); | 538 const QRegister left = locs->in(0).fpu_reg(); |
539 QRegister right = locs->in(1).fpu_reg(); | 539 const QRegister right = locs->in(1).fpu_reg(); |
540 DRegister dleft0 = EvenDRegisterOf(left); | 540 const DRegister dleft0 = EvenDRegisterOf(left); |
541 DRegister dright0 = EvenDRegisterOf(right); | 541 const DRegister dright0 = EvenDRegisterOf(right); |
542 SRegister sleft0 = EvenSRegisterOf(dleft0); | 542 const SRegister sleft0 = EvenSRegisterOf(dleft0); |
543 SRegister sleft1 = OddSRegisterOf(dleft0); | 543 const SRegister sleft1 = OddSRegisterOf(dleft0); |
544 SRegister sright0 = EvenSRegisterOf(dright0); | 544 const SRegister sright0 = EvenSRegisterOf(dright0); |
545 SRegister sright1 = OddSRegisterOf(dright0); | 545 const SRegister sright1 = OddSRegisterOf(dright0); |
546 | 546 |
547 Register tmp_left = locs->temp(0).reg(); | 547 const Register tmp_left = locs->temp(0).reg(); |
548 Register tmp_right = locs->temp(1).reg(); | 548 const Register tmp_right = locs->temp(1).reg(); |
549 | 549 |
550 // 64-bit comparison | 550 // 64-bit comparison |
551 Condition hi_true_cond, hi_false_cond, lo_false_cond; | 551 Condition hi_true_cond, hi_false_cond, lo_false_cond; |
552 switch (kind) { | 552 switch (kind) { |
553 case Token::kLT: | 553 case Token::kLT: |
554 case Token::kLTE: | 554 case Token::kLTE: |
555 hi_true_cond = LT; | 555 hi_true_cond = LT; |
556 hi_false_cond = GT; | 556 hi_false_cond = GT; |
557 lo_false_cond = (kind == Token::kLT) ? CS : HI; | 557 lo_false_cond = (kind == Token::kLT) ? CS : HI; |
558 break; | 558 break; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 default: | 602 default: |
603 UNREACHABLE(); | 603 UNREACHABLE(); |
604 return VS; | 604 return VS; |
605 } | 605 } |
606 } | 606 } |
607 | 607 |
608 | 608 |
609 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 609 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
610 LocationSummary* locs, | 610 LocationSummary* locs, |
611 Token::Kind kind) { | 611 Token::Kind kind) { |
612 QRegister left = locs->in(0).fpu_reg(); | 612 const QRegister left = locs->in(0).fpu_reg(); |
613 QRegister right = locs->in(1).fpu_reg(); | 613 const QRegister right = locs->in(1).fpu_reg(); |
614 DRegister dleft = EvenDRegisterOf(left); | 614 const DRegister dleft = EvenDRegisterOf(left); |
615 DRegister dright = EvenDRegisterOf(right); | 615 const DRegister dright = EvenDRegisterOf(right); |
616 __ vcmpd(dleft, dright); | 616 __ vcmpd(dleft, dright); |
617 __ vmstat(); | 617 __ vmstat(); |
618 Condition true_condition = TokenKindToDoubleCondition(kind); | 618 Condition true_condition = TokenKindToDoubleCondition(kind); |
619 return true_condition; | 619 return true_condition; |
620 } | 620 } |
621 | 621 |
622 | 622 |
623 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 623 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
624 BranchLabels labels) { | 624 BranchLabels labels) { |
625 if (operation_cid() == kSmiCid) { | 625 if (operation_cid() == kSmiCid) { |
626 return EmitSmiComparisonOp(compiler, locs(), kind()); | 626 return EmitSmiComparisonOp(compiler, locs(), kind()); |
627 } else if (operation_cid() == kMintCid) { | 627 } else if (operation_cid() == kMintCid) { |
628 return EmitUnboxedMintEqualityOp(compiler, locs(), kind()); | 628 return EmitUnboxedMintEqualityOp(compiler, locs(), kind()); |
629 } else { | 629 } else { |
630 ASSERT(operation_cid() == kDoubleCid); | 630 ASSERT(operation_cid() == kDoubleCid); |
631 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 631 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
632 } | 632 } |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 636 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
637 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 637 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
638 | 638 |
639 // The ARM code does not use true- and false-labels here. | 639 // The ARM code does not use true- and false-labels here. |
640 BranchLabels labels = { NULL, NULL, NULL }; | 640 BranchLabels labels = { NULL, NULL, NULL }; |
641 Condition true_condition = EmitComparisonCode(compiler, labels); | 641 Condition true_condition = EmitComparisonCode(compiler, labels); |
642 | 642 |
643 Register result = locs()->out(0).reg(); | 643 const Register result = locs()->out(0).reg(); |
644 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 644 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
645 __ LoadObject(result, Bool::True(), true_condition); | 645 __ LoadObject(result, Bool::True(), true_condition); |
646 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 646 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
647 } else { | 647 } else { |
648 ASSERT(operation_cid() == kDoubleCid); | 648 ASSERT(operation_cid() == kDoubleCid); |
649 Label done; | 649 Label done; |
650 __ LoadObject(result, Bool::False()); | 650 __ LoadObject(result, Bool::False()); |
651 if (true_condition != NE) { | 651 if (true_condition != NE) { |
652 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 652 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
653 } | 653 } |
(...skipping 27 matching lines...) Expand all Loading... |
681 locs->set_in(0, Location::RequiresRegister()); | 681 locs->set_in(0, Location::RequiresRegister()); |
682 // Only one input can be a constant operand. The case of two constant | 682 // Only one input can be a constant operand. The case of two constant |
683 // operands should be handled by constant propagation. | 683 // operands should be handled by constant propagation. |
684 locs->set_in(1, Location::RegisterOrConstant(right())); | 684 locs->set_in(1, Location::RegisterOrConstant(right())); |
685 return locs; | 685 return locs; |
686 } | 686 } |
687 | 687 |
688 | 688 |
689 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 689 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
690 BranchLabels labels) { | 690 BranchLabels labels) { |
691 Register left = locs()->in(0).reg(); | 691 const Register left = locs()->in(0).reg(); |
692 Location right = locs()->in(1); | 692 Location right = locs()->in(1); |
693 if (right.IsConstant()) { | 693 if (right.IsConstant()) { |
694 ASSERT(right.constant().IsSmi()); | 694 ASSERT(right.constant().IsSmi()); |
695 const int32_t imm = | 695 const int32_t imm = |
696 reinterpret_cast<int32_t>(right.constant().raw()); | 696 reinterpret_cast<int32_t>(right.constant().raw()); |
697 __ TestImmediate(left, imm); | 697 __ TestImmediate(left, imm); |
698 } else { | 698 } else { |
699 __ tst(left, ShifterOperand(right.reg())); | 699 __ tst(left, ShifterOperand(right.reg())); |
700 } | 700 } |
701 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 701 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
(...skipping 23 matching lines...) Expand all Loading... |
725 locs->set_in(0, Location::RequiresRegister()); | 725 locs->set_in(0, Location::RequiresRegister()); |
726 locs->set_temp(0, Location::RequiresRegister()); | 726 locs->set_temp(0, Location::RequiresRegister()); |
727 locs->set_out(0, Location::RequiresRegister()); | 727 locs->set_out(0, Location::RequiresRegister()); |
728 return locs; | 728 return locs; |
729 } | 729 } |
730 | 730 |
731 | 731 |
732 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 732 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
733 BranchLabels labels) { | 733 BranchLabels labels) { |
734 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 734 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
735 Register val_reg = locs()->in(0).reg(); | 735 const Register val_reg = locs()->in(0).reg(); |
736 Register cid_reg = locs()->temp(0).reg(); | 736 const Register cid_reg = locs()->temp(0).reg(); |
737 | 737 |
738 Label* deopt = CanDeoptimize() ? | 738 Label* deopt = CanDeoptimize() ? |
739 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; | 739 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; |
740 | 740 |
741 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 741 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
742 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 742 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
743 ASSERT(data[0] == kSmiCid); | 743 ASSERT(data[0] == kSmiCid); |
744 bool result = data[1] == true_result; | 744 bool result = data[1] == true_result; |
745 __ tst(val_reg, ShifterOperand(kSmiTagMask)); | 745 __ tst(val_reg, ShifterOperand(kSmiTagMask)); |
746 __ b(result ? labels.true_label : labels.false_label, EQ); | 746 __ b(result ? labels.true_label : labels.false_label, EQ); |
(...skipping 22 matching lines...) Expand all Loading... |
769 | 769 |
770 | 770 |
771 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 771 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
772 BranchInstr* branch) { | 772 BranchInstr* branch) { |
773 BranchLabels labels = compiler->CreateBranchLabels(branch); | 773 BranchLabels labels = compiler->CreateBranchLabels(branch); |
774 EmitComparisonCode(compiler, labels); | 774 EmitComparisonCode(compiler, labels); |
775 } | 775 } |
776 | 776 |
777 | 777 |
778 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 778 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
779 Register result_reg = locs()->out(0).reg(); | 779 const Register result_reg = locs()->out(0).reg(); |
780 Label is_true, is_false, done; | 780 Label is_true, is_false, done; |
781 BranchLabels labels = { &is_true, &is_false, &is_false }; | 781 BranchLabels labels = { &is_true, &is_false, &is_false }; |
782 EmitComparisonCode(compiler, labels); | 782 EmitComparisonCode(compiler, labels); |
783 __ Bind(&is_false); | 783 __ Bind(&is_false); |
784 __ LoadObject(result_reg, Bool::False()); | 784 __ LoadObject(result_reg, Bool::False()); |
785 __ b(&done); | 785 __ b(&done); |
786 __ Bind(&is_true); | 786 __ Bind(&is_true); |
787 __ LoadObject(result_reg, Bool::True()); | 787 __ LoadObject(result_reg, Bool::True()); |
788 __ Bind(&done); | 788 __ Bind(&done); |
789 } | 789 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 836 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
837 } | 837 } |
838 } | 838 } |
839 | 839 |
840 | 840 |
841 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 841 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
842 // The ARM code does not use true- and false-labels here. | 842 // The ARM code does not use true- and false-labels here. |
843 BranchLabels labels = { NULL, NULL, NULL }; | 843 BranchLabels labels = { NULL, NULL, NULL }; |
844 Condition true_condition = EmitComparisonCode(compiler, labels); | 844 Condition true_condition = EmitComparisonCode(compiler, labels); |
845 | 845 |
846 Register result = locs()->out(0).reg(); | 846 const Register result = locs()->out(0).reg(); |
847 if (operation_cid() == kSmiCid) { | 847 if (operation_cid() == kSmiCid) { |
848 __ LoadObject(result, Bool::True(), true_condition); | 848 __ LoadObject(result, Bool::True(), true_condition); |
849 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 849 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
850 } else if (operation_cid() == kMintCid) { | 850 } else if (operation_cid() == kMintCid) { |
851 Register cr = locs()->temp(0).reg(); | 851 const Register cr = locs()->temp(0).reg(); |
852 __ LoadObject(result, Bool::True()); | 852 __ LoadObject(result, Bool::True()); |
853 __ CompareImmediate(cr, 1); | 853 __ CompareImmediate(cr, 1); |
854 __ LoadObject(result, Bool::False(), NE); | 854 __ LoadObject(result, Bool::False(), NE); |
855 } else { | 855 } else { |
856 ASSERT(operation_cid() == kDoubleCid); | 856 ASSERT(operation_cid() == kDoubleCid); |
857 Label done; | 857 Label done; |
858 __ LoadObject(result, Bool::False()); | 858 __ LoadObject(result, Bool::False()); |
859 if (true_condition != NE) { | 859 if (true_condition != NE) { |
860 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 860 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
861 } | 861 } |
862 __ LoadObject(result, Bool::True(), true_condition); | 862 __ LoadObject(result, Bool::True(), true_condition); |
863 __ Bind(&done); | 863 __ Bind(&done); |
864 } | 864 } |
865 } | 865 } |
866 | 866 |
867 | 867 |
868 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 868 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
869 BranchInstr* branch) { | 869 BranchInstr* branch) { |
870 BranchLabels labels = compiler->CreateBranchLabels(branch); | 870 BranchLabels labels = compiler->CreateBranchLabels(branch); |
871 Condition true_condition = EmitComparisonCode(compiler, labels); | 871 Condition true_condition = EmitComparisonCode(compiler, labels); |
872 | 872 |
873 if (operation_cid() == kSmiCid) { | 873 if (operation_cid() == kSmiCid) { |
874 EmitBranchOnCondition(compiler, true_condition, labels); | 874 EmitBranchOnCondition(compiler, true_condition, labels); |
875 } else if (operation_cid() == kMintCid) { | 875 } else if (operation_cid() == kMintCid) { |
876 Register result = locs()->temp(0).reg(); | 876 const Register result = locs()->temp(0).reg(); |
877 __ CompareImmediate(result, 1); | 877 __ CompareImmediate(result, 1); |
878 __ b(labels.true_label, EQ); | 878 __ b(labels.true_label, EQ); |
879 __ b(labels.false_label, NE); | 879 __ b(labels.false_label, NE); |
880 } else if (operation_cid() == kDoubleCid) { | 880 } else if (operation_cid() == kDoubleCid) { |
881 Label* nan_result = (true_condition == NE) ? | 881 Label* nan_result = (true_condition == NE) ? |
882 labels.true_label : labels.false_label; | 882 labels.true_label : labels.false_label; |
883 __ b(nan_result, VS); | 883 __ b(nan_result, VS); |
884 EmitBranchOnCondition(compiler, true_condition, labels); | 884 EmitBranchOnCondition(compiler, true_condition, labels); |
885 } | 885 } |
886 } | 886 } |
887 | 887 |
888 | 888 |
889 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { | 889 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { |
890 const intptr_t kNumInputs = 0; | 890 const intptr_t kNumInputs = 0; |
891 const intptr_t kNumTemps = 3; | 891 const intptr_t kNumTemps = 3; |
892 LocationSummary* locs = | 892 LocationSummary* locs = |
893 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 893 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
894 locs->set_temp(0, Location::RegisterLocation(R1)); | 894 locs->set_temp(0, Location::RegisterLocation(R1)); |
895 locs->set_temp(1, Location::RegisterLocation(R2)); | 895 locs->set_temp(1, Location::RegisterLocation(R2)); |
896 locs->set_temp(2, Location::RegisterLocation(R5)); | 896 locs->set_temp(2, Location::RegisterLocation(R5)); |
897 locs->set_out(0, Location::RegisterLocation(R0)); | 897 locs->set_out(0, Location::RegisterLocation(R0)); |
898 return locs; | 898 return locs; |
899 } | 899 } |
900 | 900 |
901 | 901 |
902 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 902 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
903 ASSERT(locs()->temp(0).reg() == R1); | 903 ASSERT(locs()->temp(0).reg() == R1); |
904 ASSERT(locs()->temp(1).reg() == R2); | 904 ASSERT(locs()->temp(1).reg() == R2); |
905 ASSERT(locs()->temp(2).reg() == R5); | 905 ASSERT(locs()->temp(2).reg() == R5); |
906 Register result = locs()->out(0).reg(); | 906 const Register result = locs()->out(0).reg(); |
907 | 907 |
908 // Push the result place holder initialized to NULL. | 908 // Push the result place holder initialized to NULL. |
909 __ PushObject(Object::ZoneHandle()); | 909 __ PushObject(Object::ZoneHandle()); |
910 // Pass a pointer to the first argument in R2. | 910 // Pass a pointer to the first argument in R2. |
911 if (!function().HasOptionalParameters()) { | 911 if (!function().HasOptionalParameters()) { |
912 __ AddImmediate(R2, FP, (kParamEndSlotFromFp + | 912 __ AddImmediate(R2, FP, (kParamEndSlotFromFp + |
913 function().NumParameters()) * kWordSize); | 913 function().NumParameters()) * kWordSize); |
914 } else { | 914 } else { |
915 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); | 915 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); |
916 } | 916 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary(bool opt) const { | 950 LocationSummary* StringFromCharCodeInstr::MakeLocationSummary(bool opt) const { |
951 const intptr_t kNumInputs = 1; | 951 const intptr_t kNumInputs = 1; |
952 // TODO(fschneider): Allow immediate operands for the char code. | 952 // TODO(fschneider): Allow immediate operands for the char code. |
953 return LocationSummary::Make(kNumInputs, | 953 return LocationSummary::Make(kNumInputs, |
954 Location::RequiresRegister(), | 954 Location::RequiresRegister(), |
955 LocationSummary::kNoCall); | 955 LocationSummary::kNoCall); |
956 } | 956 } |
957 | 957 |
958 | 958 |
959 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 959 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
960 Register char_code = locs()->in(0).reg(); | 960 const Register char_code = locs()->in(0).reg(); |
961 Register result = locs()->out(0).reg(); | 961 const Register result = locs()->out(0).reg(); |
962 __ LoadImmediate(result, | 962 __ LoadImmediate(result, |
963 reinterpret_cast<uword>(Symbols::PredefinedAddress())); | 963 reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
964 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 964 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
965 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. | 965 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. |
966 } | 966 } |
967 | 967 |
968 | 968 |
969 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { | 969 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { |
970 const intptr_t kNumInputs = 1; | 970 const intptr_t kNumInputs = 1; |
971 return LocationSummary::Make(kNumInputs, | 971 return LocationSummary::Make(kNumInputs, |
972 Location::RequiresRegister(), | 972 Location::RequiresRegister(), |
973 LocationSummary::kNoCall); | 973 LocationSummary::kNoCall); |
974 } | 974 } |
975 | 975 |
976 | 976 |
977 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 977 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
978 ASSERT(cid_ == kOneByteStringCid); | 978 ASSERT(cid_ == kOneByteStringCid); |
979 Register str = locs()->in(0).reg(); | 979 const Register str = locs()->in(0).reg(); |
980 Register result = locs()->out(0).reg(); | 980 const Register result = locs()->out(0).reg(); |
981 __ ldr(result, FieldAddress(str, String::length_offset())); | 981 __ ldr(result, FieldAddress(str, String::length_offset())); |
982 __ cmp(result, ShifterOperand(Smi::RawValue(1))); | 982 __ cmp(result, ShifterOperand(Smi::RawValue(1))); |
983 __ LoadImmediate(result, -1, NE); | 983 __ LoadImmediate(result, -1, NE); |
984 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); | 984 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); |
985 __ SmiTag(result); | 985 __ SmiTag(result); |
986 } | 986 } |
987 | 987 |
988 | 988 |
989 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { | 989 LocationSummary* StringInterpolateInstr::MakeLocationSummary(bool opt) const { |
990 const intptr_t kNumInputs = 1; | 990 const intptr_t kNumInputs = 1; |
991 const intptr_t kNumTemps = 0; | 991 const intptr_t kNumTemps = 0; |
992 LocationSummary* summary = | 992 LocationSummary* summary = |
993 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 993 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
994 summary->set_in(0, Location::RegisterLocation(R0)); | 994 summary->set_in(0, Location::RegisterLocation(R0)); |
995 summary->set_out(0, Location::RegisterLocation(R0)); | 995 summary->set_out(0, Location::RegisterLocation(R0)); |
996 return summary; | 996 return summary; |
997 } | 997 } |
998 | 998 |
999 | 999 |
1000 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1000 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1001 Register array = locs()->in(0).reg(); | 1001 const Register array = locs()->in(0).reg(); |
1002 __ Push(array); | 1002 __ Push(array); |
1003 const int kNumberOfArguments = 1; | 1003 const int kNumberOfArguments = 1; |
1004 const Array& kNoArgumentNames = Object::null_array(); | 1004 const Array& kNoArgumentNames = Object::null_array(); |
1005 compiler->GenerateStaticCall(deopt_id(), | 1005 compiler->GenerateStaticCall(deopt_id(), |
1006 token_pos(), | 1006 token_pos(), |
1007 CallFunction(), | 1007 CallFunction(), |
1008 kNumberOfArguments, | 1008 kNumberOfArguments, |
1009 kNoArgumentNames, | 1009 kNoArgumentNames, |
1010 locs()); | 1010 locs()); |
1011 ASSERT(locs()->out(0).reg() == R0); | 1011 ASSERT(locs()->out(0).reg() == R0); |
1012 } | 1012 } |
1013 | 1013 |
1014 | 1014 |
1015 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { | 1015 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(bool opt) const { |
1016 const intptr_t kNumInputs = 1; | 1016 const intptr_t kNumInputs = 1; |
1017 return LocationSummary::Make(kNumInputs, | 1017 return LocationSummary::Make(kNumInputs, |
1018 Location::RequiresRegister(), | 1018 Location::RequiresRegister(), |
1019 LocationSummary::kNoCall); | 1019 LocationSummary::kNoCall); |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1023 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1024 Register object = locs()->in(0).reg(); | 1024 const Register object = locs()->in(0).reg(); |
1025 Register result = locs()->out(0).reg(); | 1025 const Register result = locs()->out(0).reg(); |
1026 __ LoadFromOffset(kWord, result, object, offset() - kHeapObjectTag); | 1026 __ LoadFromOffset(kWord, result, object, offset() - kHeapObjectTag); |
1027 } | 1027 } |
1028 | 1028 |
1029 | 1029 |
1030 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { | 1030 LocationSummary* LoadClassIdInstr::MakeLocationSummary(bool opt) const { |
1031 const intptr_t kNumInputs = 1; | 1031 const intptr_t kNumInputs = 1; |
1032 return LocationSummary::Make(kNumInputs, | 1032 return LocationSummary::Make(kNumInputs, |
1033 Location::RequiresRegister(), | 1033 Location::RequiresRegister(), |
1034 LocationSummary::kNoCall); | 1034 LocationSummary::kNoCall); |
1035 } | 1035 } |
1036 | 1036 |
1037 | 1037 |
1038 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1038 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1039 Register object = locs()->in(0).reg(); | 1039 const Register object = locs()->in(0).reg(); |
1040 Register result = locs()->out(0).reg(); | 1040 const Register result = locs()->out(0).reg(); |
1041 Label load, done; | 1041 Label load, done; |
1042 __ tst(object, ShifterOperand(kSmiTagMask)); | 1042 __ tst(object, ShifterOperand(kSmiTagMask)); |
1043 __ b(&load, NE); | 1043 __ b(&load, NE); |
1044 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); | 1044 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); |
1045 __ b(&done); | 1045 __ b(&done); |
1046 __ Bind(&load); | 1046 __ Bind(&load); |
1047 __ LoadClassId(result, object); | 1047 __ LoadClassId(result, object); |
1048 __ SmiTag(result); | 1048 __ SmiTag(result); |
1049 __ Bind(&done); | 1049 __ Bind(&done); |
1050 } | 1050 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1159 return locs; | 1159 return locs; |
1160 } | 1160 } |
1161 | 1161 |
1162 | 1162 |
1163 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1163 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1164 if ((representation() == kUnboxedDouble) || | 1164 if ((representation() == kUnboxedDouble) || |
1165 (representation() == kUnboxedMint) || | 1165 (representation() == kUnboxedMint) || |
1166 (representation() == kUnboxedFloat32x4) || | 1166 (representation() == kUnboxedFloat32x4) || |
1167 (representation() == kUnboxedInt32x4) || | 1167 (representation() == kUnboxedInt32x4) || |
1168 (representation() == kUnboxedFloat64x2)) { | 1168 (representation() == kUnboxedFloat64x2)) { |
1169 Register array = locs()->in(0).reg(); | 1169 const Register array = locs()->in(0).reg(); |
1170 Register idx = locs()->in(1).reg(); | 1170 const Register idx = locs()->in(1).reg(); |
1171 switch (index_scale()) { | 1171 switch (index_scale()) { |
1172 case 1: | 1172 case 1: |
1173 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); | 1173 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); |
1174 break; | 1174 break; |
1175 case 4: | 1175 case 4: |
1176 __ add(idx, array, ShifterOperand(idx, LSL, 1)); | 1176 __ add(idx, array, ShifterOperand(idx, LSL, 1)); |
1177 break; | 1177 break; |
1178 case 8: | 1178 case 8: |
1179 __ add(idx, array, ShifterOperand(idx, LSL, 2)); | 1179 __ add(idx, array, ShifterOperand(idx, LSL, 2)); |
1180 break; | 1180 break; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 break; | 1222 break; |
1223 case kTypedDataFloat64x2ArrayCid: | 1223 case kTypedDataFloat64x2ArrayCid: |
1224 case kTypedDataInt32x4ArrayCid: | 1224 case kTypedDataInt32x4ArrayCid: |
1225 case kTypedDataFloat32x4ArrayCid: | 1225 case kTypedDataFloat32x4ArrayCid: |
1226 __ vldmd(IA, idx, dresult0, 2); | 1226 __ vldmd(IA, idx, dresult0, 2); |
1227 break; | 1227 break; |
1228 } | 1228 } |
1229 return; | 1229 return; |
1230 } | 1230 } |
1231 | 1231 |
1232 Register array = locs()->in(0).reg(); | 1232 const Register array = locs()->in(0).reg(); |
1233 Location index = locs()->in(1); | 1233 Location index = locs()->in(1); |
1234 ASSERT(index.IsRegister()); // TODO(regis): Revisit. | 1234 ASSERT(index.IsRegister()); // TODO(regis): Revisit. |
1235 Address element_address(kNoRegister, 0); | 1235 Address element_address(kNoRegister, 0); |
1236 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | 1236 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays |
1237 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | 1237 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the |
1238 // index is expected to be untagged before accessing. | 1238 // index is expected to be untagged before accessing. |
1239 ASSERT(kSmiTagShift == 1); | 1239 ASSERT(kSmiTagShift == 1); |
1240 const intptr_t offset = IsExternal() | 1240 const intptr_t offset = IsExternal() |
1241 ? 0 | 1241 ? 0 |
1242 : FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag; | 1242 : FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag; |
(...skipping 17 matching lines...) Expand all Loading... |
1260 case 4: { | 1260 case 4: { |
1261 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1)); | 1261 __ add(index.reg(), array, ShifterOperand(index.reg(), LSL, 1)); |
1262 element_address = Address(index.reg(), offset); | 1262 element_address = Address(index.reg(), offset); |
1263 break; | 1263 break; |
1264 } | 1264 } |
1265 // Cases 8 and 16 are only for unboxed values and are handled above. | 1265 // Cases 8 and 16 are only for unboxed values and are handled above. |
1266 default: | 1266 default: |
1267 UNREACHABLE(); | 1267 UNREACHABLE(); |
1268 } | 1268 } |
1269 | 1269 |
1270 Register result = locs()->out(0).reg(); | 1270 const Register result = locs()->out(0).reg(); |
1271 switch (class_id()) { | 1271 switch (class_id()) { |
1272 case kTypedDataInt8ArrayCid: | 1272 case kTypedDataInt8ArrayCid: |
1273 ASSERT(index_scale() == 1); | 1273 ASSERT(index_scale() == 1); |
1274 __ ldrsb(result, element_address); | 1274 __ ldrsb(result, element_address); |
1275 __ SmiTag(result); | 1275 __ SmiTag(result); |
1276 break; | 1276 break; |
1277 case kTypedDataUint8ArrayCid: | 1277 case kTypedDataUint8ArrayCid: |
1278 case kTypedDataUint8ClampedArrayCid: | 1278 case kTypedDataUint8ClampedArrayCid: |
1279 case kExternalTypedDataUint8ArrayCid: | 1279 case kExternalTypedDataUint8ArrayCid: |
1280 case kExternalTypedDataUint8ClampedArrayCid: | 1280 case kExternalTypedDataUint8ClampedArrayCid: |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 return locs; | 1407 return locs; |
1408 } | 1408 } |
1409 | 1409 |
1410 | 1410 |
1411 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1411 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1412 if ((class_id() == kTypedDataFloat32ArrayCid) || | 1412 if ((class_id() == kTypedDataFloat32ArrayCid) || |
1413 (class_id() == kTypedDataFloat64ArrayCid) || | 1413 (class_id() == kTypedDataFloat64ArrayCid) || |
1414 (class_id() == kTypedDataFloat32x4ArrayCid) || | 1414 (class_id() == kTypedDataFloat32x4ArrayCid) || |
1415 (class_id() == kTypedDataFloat64x2ArrayCid) || | 1415 (class_id() == kTypedDataFloat64x2ArrayCid) || |
1416 (class_id() == kTypedDataInt32x4ArrayCid)) { | 1416 (class_id() == kTypedDataInt32x4ArrayCid)) { |
1417 Register array = locs()->in(0).reg(); | 1417 const Register array = locs()->in(0).reg(); |
1418 Register idx = locs()->in(1).reg(); | 1418 const Register idx = locs()->in(1).reg(); |
1419 Location value = locs()->in(2); | 1419 Location value = locs()->in(2); |
1420 switch (index_scale()) { | 1420 switch (index_scale()) { |
1421 case 1: | 1421 case 1: |
1422 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); | 1422 __ add(idx, array, ShifterOperand(idx, ASR, kSmiTagSize)); |
1423 break; | 1423 break; |
1424 case 4: | 1424 case 4: |
1425 __ add(idx, array, ShifterOperand(idx, LSL, 1)); | 1425 __ add(idx, array, ShifterOperand(idx, LSL, 1)); |
1426 break; | 1426 break; |
1427 case 8: | 1427 case 8: |
1428 __ add(idx, array, ShifterOperand(idx, LSL, 2)); | 1428 __ add(idx, array, ShifterOperand(idx, LSL, 2)); |
1429 break; | 1429 break; |
1430 case 16: | 1430 case 16: |
1431 __ add(idx, array, ShifterOperand(idx, LSL, 3)); | 1431 __ add(idx, array, ShifterOperand(idx, LSL, 3)); |
1432 break; | 1432 break; |
1433 default: | 1433 default: |
1434 // Case 2 is not reachable: We don't have unboxed 16-bit sized loads. | 1434 // Case 2 is not reachable: We don't have unboxed 16-bit sized loads. |
1435 UNREACHABLE(); | 1435 UNREACHABLE(); |
1436 } | 1436 } |
1437 if (!IsExternal()) { | 1437 if (!IsExternal()) { |
1438 ASSERT(this->array()->definition()->representation() == kTagged); | 1438 ASSERT(this->array()->definition()->representation() == kTagged); |
1439 __ AddImmediate(idx, | 1439 __ AddImmediate(idx, |
1440 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); | 1440 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag); |
1441 } | 1441 } |
1442 switch (class_id()) { | 1442 switch (class_id()) { |
1443 case kTypedDataFloat32ArrayCid: { | 1443 case kTypedDataFloat32ArrayCid: { |
1444 SRegister value_reg = | 1444 const SRegister value_reg = |
1445 EvenSRegisterOf(EvenDRegisterOf(value.fpu_reg())); | 1445 EvenSRegisterOf(EvenDRegisterOf(value.fpu_reg())); |
1446 __ StoreSToOffset(value_reg, idx, 0); | 1446 __ StoreSToOffset(value_reg, idx, 0); |
1447 break; | 1447 break; |
1448 } | 1448 } |
1449 case kTypedDataFloat64ArrayCid: { | 1449 case kTypedDataFloat64ArrayCid: { |
1450 DRegister value_reg = EvenDRegisterOf(value.fpu_reg()); | 1450 const DRegister value_reg = EvenDRegisterOf(value.fpu_reg()); |
1451 __ StoreDToOffset(value_reg, idx, 0); | 1451 __ StoreDToOffset(value_reg, idx, 0); |
1452 break; | 1452 break; |
1453 } | 1453 } |
1454 case kTypedDataFloat64x2ArrayCid: | 1454 case kTypedDataFloat64x2ArrayCid: |
1455 case kTypedDataInt32x4ArrayCid: | 1455 case kTypedDataInt32x4ArrayCid: |
1456 case kTypedDataFloat32x4ArrayCid: { | 1456 case kTypedDataFloat32x4ArrayCid: { |
1457 const DRegister value_reg = EvenDRegisterOf(value.fpu_reg()); | 1457 const DRegister value_reg = EvenDRegisterOf(value.fpu_reg()); |
1458 __ vstmd(IA, idx, value_reg, 2); | 1458 __ vstmd(IA, idx, value_reg, 2); |
1459 break; | 1459 break; |
1460 } | 1460 } |
1461 default: | 1461 default: |
1462 UNREACHABLE(); | 1462 UNREACHABLE(); |
1463 } | 1463 } |
1464 return; | 1464 return; |
1465 } | 1465 } |
1466 | 1466 |
1467 Register array = locs()->in(0).reg(); | 1467 const Register array = locs()->in(0).reg(); |
1468 Location index = locs()->in(1); | 1468 Location index = locs()->in(1); |
1469 | 1469 |
1470 Address element_address(kNoRegister, 0); | 1470 Address element_address(kNoRegister, 0); |
1471 ASSERT(index.IsRegister()); // TODO(regis): Revisit. | 1471 ASSERT(index.IsRegister()); // TODO(regis): Revisit. |
1472 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | 1472 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays |
1473 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | 1473 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the |
1474 // index is expected to be untagged before accessing. | 1474 // index is expected to be untagged before accessing. |
1475 ASSERT(kSmiTagShift == 1); | 1475 ASSERT(kSmiTagShift == 1); |
1476 const intptr_t offset = IsExternal() | 1476 const intptr_t offset = IsExternal() |
1477 ? 0 | 1477 ? 0 |
(...skipping 20 matching lines...) Expand all Loading... |
1498 break; | 1498 break; |
1499 } | 1499 } |
1500 // Cases 8 and 16 are only for unboxed values and are handled above. | 1500 // Cases 8 and 16 are only for unboxed values and are handled above. |
1501 default: | 1501 default: |
1502 UNREACHABLE(); | 1502 UNREACHABLE(); |
1503 } | 1503 } |
1504 | 1504 |
1505 switch (class_id()) { | 1505 switch (class_id()) { |
1506 case kArrayCid: | 1506 case kArrayCid: |
1507 if (ShouldEmitStoreBarrier()) { | 1507 if (ShouldEmitStoreBarrier()) { |
1508 Register value = locs()->in(2).reg(); | 1508 const Register value = locs()->in(2).reg(); |
1509 __ StoreIntoObject(array, element_address, value); | 1509 __ StoreIntoObject(array, element_address, value); |
1510 } else if (locs()->in(2).IsConstant()) { | 1510 } else if (locs()->in(2).IsConstant()) { |
1511 const Object& constant = locs()->in(2).constant(); | 1511 const Object& constant = locs()->in(2).constant(); |
1512 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1512 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
1513 } else { | 1513 } else { |
1514 Register value = locs()->in(2).reg(); | 1514 const Register value = locs()->in(2).reg(); |
1515 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1515 __ StoreIntoObjectNoBarrier(array, element_address, value); |
1516 } | 1516 } |
1517 break; | 1517 break; |
1518 case kTypedDataInt8ArrayCid: | 1518 case kTypedDataInt8ArrayCid: |
1519 case kTypedDataUint8ArrayCid: | 1519 case kTypedDataUint8ArrayCid: |
1520 case kExternalTypedDataUint8ArrayCid: | 1520 case kExternalTypedDataUint8ArrayCid: |
1521 case kOneByteStringCid: { | 1521 case kOneByteStringCid: { |
1522 if (locs()->in(2).IsConstant()) { | 1522 if (locs()->in(2).IsConstant()) { |
1523 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1523 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1524 __ LoadImmediate(IP, static_cast<int8_t>(constant.Value())); | 1524 __ LoadImmediate(IP, static_cast<int8_t>(constant.Value())); |
1525 __ strb(IP, element_address); | 1525 __ strb(IP, element_address); |
1526 } else { | 1526 } else { |
1527 Register value = locs()->in(2).reg(); | 1527 const Register value = locs()->in(2).reg(); |
1528 __ SmiUntag(value); | 1528 __ SmiUntag(value); |
1529 __ strb(value, element_address); | 1529 __ strb(value, element_address); |
1530 } | 1530 } |
1531 break; | 1531 break; |
1532 } | 1532 } |
1533 case kTypedDataUint8ClampedArrayCid: | 1533 case kTypedDataUint8ClampedArrayCid: |
1534 case kExternalTypedDataUint8ClampedArrayCid: { | 1534 case kExternalTypedDataUint8ClampedArrayCid: { |
1535 if (locs()->in(2).IsConstant()) { | 1535 if (locs()->in(2).IsConstant()) { |
1536 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1536 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
1537 intptr_t value = constant.Value(); | 1537 intptr_t value = constant.Value(); |
1538 // Clamp to 0x0 or 0xFF respectively. | 1538 // Clamp to 0x0 or 0xFF respectively. |
1539 if (value > 0xFF) { | 1539 if (value > 0xFF) { |
1540 value = 0xFF; | 1540 value = 0xFF; |
1541 } else if (value < 0) { | 1541 } else if (value < 0) { |
1542 value = 0; | 1542 value = 0; |
1543 } | 1543 } |
1544 __ LoadImmediate(IP, static_cast<int8_t>(value)); | 1544 __ LoadImmediate(IP, static_cast<int8_t>(value)); |
1545 __ strb(IP, element_address); | 1545 __ strb(IP, element_address); |
1546 } else { | 1546 } else { |
1547 Register value = locs()->in(2).reg(); | 1547 const Register value = locs()->in(2).reg(); |
1548 Label store_value; | 1548 Label store_value; |
1549 __ SmiUntag(value); | 1549 __ SmiUntag(value); |
1550 __ cmp(value, ShifterOperand(0xFF)); | 1550 __ cmp(value, ShifterOperand(0xFF)); |
1551 // Clamp to 0x00 or 0xFF respectively. | 1551 // Clamp to 0x00 or 0xFF respectively. |
1552 __ b(&store_value, LS); | 1552 __ b(&store_value, LS); |
1553 __ mov(value, ShifterOperand(0x00), LE); | 1553 __ mov(value, ShifterOperand(0x00), LE); |
1554 __ mov(value, ShifterOperand(0xFF), GT); | 1554 __ mov(value, ShifterOperand(0xFF), GT); |
1555 __ Bind(&store_value); | 1555 __ Bind(&store_value); |
1556 __ strb(value, element_address); | 1556 __ strb(value, element_address); |
1557 } | 1557 } |
1558 break; | 1558 break; |
1559 } | 1559 } |
1560 case kTypedDataInt16ArrayCid: | 1560 case kTypedDataInt16ArrayCid: |
1561 case kTypedDataUint16ArrayCid: { | 1561 case kTypedDataUint16ArrayCid: { |
1562 Register value = locs()->in(2).reg(); | 1562 const Register value = locs()->in(2).reg(); |
1563 __ SmiUntag(value); | 1563 __ SmiUntag(value); |
1564 __ strh(value, element_address); | 1564 __ strh(value, element_address); |
1565 break; | 1565 break; |
1566 } | 1566 } |
1567 case kTypedDataInt32ArrayCid: | 1567 case kTypedDataInt32ArrayCid: |
1568 case kTypedDataUint32ArrayCid: { | 1568 case kTypedDataUint32ArrayCid: { |
1569 if (value()->IsSmiValue()) { | 1569 if (value()->IsSmiValue()) { |
1570 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1570 ASSERT(RequiredInputRepresentation(2) == kTagged); |
1571 Register value = locs()->in(2).reg(); | 1571 const Register value = locs()->in(2).reg(); |
1572 __ SmiUntag(value); | 1572 __ SmiUntag(value); |
1573 __ str(value, element_address); | 1573 __ str(value, element_address); |
1574 } else { | 1574 } else { |
1575 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1575 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
1576 QRegister value = locs()->in(2).fpu_reg(); | 1576 const QRegister value = locs()->in(2).fpu_reg(); |
1577 ASSERT(value == Q7); | 1577 ASSERT(value == Q7); |
1578 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); | 1578 __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value))); |
1579 __ str(TMP, element_address); | 1579 __ str(TMP, element_address); |
1580 } | 1580 } |
1581 break; | 1581 break; |
1582 } | 1582 } |
1583 default: | 1583 default: |
1584 UNREACHABLE(); | 1584 UNREACHABLE(); |
1585 } | 1585 } |
1586 } | 1586 } |
(...skipping 28 matching lines...) Expand all Loading... |
1615 ASSERT(field().is_final()); | 1615 ASSERT(field().is_final()); |
1616 } | 1616 } |
1617 | 1617 |
1618 if (field_cid == kDynamicCid) { | 1618 if (field_cid == kDynamicCid) { |
1619 ASSERT(!compiler->is_optimizing()); | 1619 ASSERT(!compiler->is_optimizing()); |
1620 return; // Nothing to emit. | 1620 return; // Nothing to emit. |
1621 } | 1621 } |
1622 | 1622 |
1623 const intptr_t value_cid = value()->Type()->ToCid(); | 1623 const intptr_t value_cid = value()->Type()->ToCid(); |
1624 | 1624 |
1625 Register value_reg = locs()->in(0).reg(); | 1625 const Register value_reg = locs()->in(0).reg(); |
1626 | 1626 |
1627 Register value_cid_reg = locs()->temp(0).reg(); | 1627 const Register value_cid_reg = locs()->temp(0).reg(); |
1628 | 1628 |
1629 Register temp_reg = locs()->temp(1).reg(); | 1629 const Register temp_reg = locs()->temp(1).reg(); |
1630 | 1630 |
1631 Register field_reg = needs_field_temp_reg ? | 1631 Register field_reg = needs_field_temp_reg ? |
1632 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1632 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; |
1633 | 1633 |
1634 Label ok, fail_label; | 1634 Label ok, fail_label; |
1635 | 1635 |
1636 Label* deopt = compiler->is_optimizing() ? | 1636 Label* deopt = compiler->is_optimizing() ? |
1637 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1637 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; |
1638 | 1638 |
1639 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1639 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1968 ? Location::WritableRegister() | 1968 ? Location::WritableRegister() |
1969 : Location::RegisterOrConstant(value())); | 1969 : Location::RegisterOrConstant(value())); |
1970 } | 1970 } |
1971 return summary; | 1971 return summary; |
1972 } | 1972 } |
1973 | 1973 |
1974 | 1974 |
1975 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1975 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1976 Label skip_store; | 1976 Label skip_store; |
1977 | 1977 |
1978 Register instance_reg = locs()->in(0).reg(); | 1978 const Register instance_reg = locs()->in(0).reg(); |
1979 | 1979 |
1980 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1980 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1981 const DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 1981 const DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
1982 const Register temp = locs()->temp(0).reg(); | 1982 const Register temp = locs()->temp(0).reg(); |
1983 const Register temp2 = locs()->temp(1).reg(); | 1983 const Register temp2 = locs()->temp(1).reg(); |
1984 const intptr_t cid = field().UnboxedFieldCid(); | 1984 const intptr_t cid = field().UnboxedFieldCid(); |
1985 | 1985 |
1986 if (is_initialization_) { | 1986 if (is_initialization_) { |
1987 const Class* cls = NULL; | 1987 const Class* cls = NULL; |
1988 switch (cid) { | 1988 switch (cid) { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 temp2); | 2153 temp2); |
2154 __ Bind(©_float64x2); | 2154 __ Bind(©_float64x2); |
2155 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); | 2155 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); |
2156 __ b(&skip_store); | 2156 __ b(&skip_store); |
2157 } | 2157 } |
2158 | 2158 |
2159 __ Bind(&store_pointer); | 2159 __ Bind(&store_pointer); |
2160 } | 2160 } |
2161 | 2161 |
2162 if (ShouldEmitStoreBarrier()) { | 2162 if (ShouldEmitStoreBarrier()) { |
2163 Register value_reg = locs()->in(1).reg(); | 2163 const Register value_reg = locs()->in(1).reg(); |
2164 __ StoreIntoObject(instance_reg, | 2164 __ StoreIntoObject(instance_reg, |
2165 FieldAddress(instance_reg, offset_in_bytes_), | 2165 FieldAddress(instance_reg, offset_in_bytes_), |
2166 value_reg, | 2166 value_reg, |
2167 CanValueBeSmi()); | 2167 CanValueBeSmi()); |
2168 } else { | 2168 } else { |
2169 if (locs()->in(1).IsConstant()) { | 2169 if (locs()->in(1).IsConstant()) { |
2170 __ StoreIntoObjectNoBarrier( | 2170 __ StoreIntoObjectNoBarrier( |
2171 instance_reg, | 2171 instance_reg, |
2172 FieldAddress(instance_reg, offset_in_bytes_), | 2172 FieldAddress(instance_reg, offset_in_bytes_), |
2173 locs()->in(1).constant()); | 2173 locs()->in(1).constant()); |
2174 } else { | 2174 } else { |
2175 Register value_reg = locs()->in(1).reg(); | 2175 const Register value_reg = locs()->in(1).reg(); |
2176 __ StoreIntoObjectNoBarrier(instance_reg, | 2176 __ StoreIntoObjectNoBarrier(instance_reg, |
2177 FieldAddress(instance_reg, offset_in_bytes_), value_reg); | 2177 FieldAddress(instance_reg, offset_in_bytes_), value_reg); |
2178 } | 2178 } |
2179 } | 2179 } |
2180 __ Bind(&skip_store); | 2180 __ Bind(&skip_store); |
2181 } | 2181 } |
2182 | 2182 |
2183 | 2183 |
2184 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { | 2184 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(bool opt) const { |
2185 const intptr_t kNumInputs = 1; | 2185 const intptr_t kNumInputs = 1; |
2186 const intptr_t kNumTemps = 0; | 2186 const intptr_t kNumTemps = 0; |
2187 LocationSummary* summary = | 2187 LocationSummary* summary = |
2188 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2188 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2189 summary->set_in(0, Location::RequiresRegister()); | 2189 summary->set_in(0, Location::RequiresRegister()); |
2190 summary->set_out(0, Location::RequiresRegister()); | 2190 summary->set_out(0, Location::RequiresRegister()); |
2191 return summary; | 2191 return summary; |
2192 } | 2192 } |
2193 | 2193 |
2194 | 2194 |
2195 // When the parser is building an implicit static getter for optimization, | 2195 // When the parser is building an implicit static getter for optimization, |
2196 // it can generate a function body where deoptimization ids do not line up | 2196 // it can generate a function body where deoptimization ids do not line up |
2197 // with the unoptimized code. | 2197 // with the unoptimized code. |
2198 // | 2198 // |
2199 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2199 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
2200 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2200 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2201 Register field = locs()->in(0).reg(); | 2201 const Register field = locs()->in(0).reg(); |
2202 Register result = locs()->out(0).reg(); | 2202 const Register result = locs()->out(0).reg(); |
2203 __ LoadFromOffset(kWord, result, | 2203 __ LoadFromOffset(kWord, result, |
2204 field, Field::value_offset() - kHeapObjectTag); | 2204 field, Field::value_offset() - kHeapObjectTag); |
2205 } | 2205 } |
2206 | 2206 |
2207 | 2207 |
2208 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { | 2208 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(bool opt) const { |
2209 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); | 2209 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall); |
2210 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2210 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
2211 : Location::RequiresRegister()); | 2211 : Location::RequiresRegister()); |
2212 locs->set_temp(0, Location::RequiresRegister()); | 2212 locs->set_temp(0, Location::RequiresRegister()); |
2213 return locs; | 2213 return locs; |
2214 } | 2214 } |
2215 | 2215 |
2216 | 2216 |
2217 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2217 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2218 Register value = locs()->in(0).reg(); | 2218 const Register value = locs()->in(0).reg(); |
2219 Register temp = locs()->temp(0).reg(); | 2219 const Register temp = locs()->temp(0).reg(); |
2220 | 2220 |
2221 __ LoadObject(temp, field()); | 2221 __ LoadObject(temp, field()); |
2222 if (this->value()->NeedsStoreBuffer()) { | 2222 if (this->value()->NeedsStoreBuffer()) { |
2223 __ StoreIntoObject(temp, | 2223 __ StoreIntoObject(temp, |
2224 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); | 2224 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
2225 } else { | 2225 } else { |
2226 __ StoreIntoObjectNoBarrier( | 2226 __ StoreIntoObjectNoBarrier( |
2227 temp, FieldAddress(temp, Field::value_offset()), value); | 2227 temp, FieldAddress(temp, Field::value_offset()), value); |
2228 } | 2228 } |
2229 } | 2229 } |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2524 __ LoadMultipleDFromOffset(result, 2, temp, | 2524 __ LoadMultipleDFromOffset(result, 2, temp, |
2525 Float64x2::value_offset() - kHeapObjectTag); | 2525 Float64x2::value_offset() - kHeapObjectTag); |
2526 break; | 2526 break; |
2527 default: | 2527 default: |
2528 UNREACHABLE(); | 2528 UNREACHABLE(); |
2529 } | 2529 } |
2530 return; | 2530 return; |
2531 } | 2531 } |
2532 | 2532 |
2533 Label done; | 2533 Label done; |
2534 Register result_reg = locs()->out(0).reg(); | 2534 const Register result_reg = locs()->out(0).reg(); |
2535 if (IsPotentialUnboxedLoad()) { | 2535 if (IsPotentialUnboxedLoad()) { |
2536 const DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); | 2536 const DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); |
2537 const Register temp = locs()->temp(1).reg(); | 2537 const Register temp = locs()->temp(1).reg(); |
2538 const Register temp2 = locs()->temp(2).reg(); | 2538 const Register temp2 = locs()->temp(2).reg(); |
2539 | 2539 |
2540 Label load_pointer; | 2540 Label load_pointer; |
2541 Label load_double; | 2541 Label load_double; |
2542 Label load_float32x4; | 2542 Label load_float32x4; |
2543 Label load_float64x2; | 2543 Label load_float64x2; |
2544 | 2544 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2629 const intptr_t kNumTemps = 0; | 2629 const intptr_t kNumTemps = 0; |
2630 LocationSummary* locs = | 2630 LocationSummary* locs = |
2631 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2631 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
2632 locs->set_in(0, Location::RegisterLocation(R0)); | 2632 locs->set_in(0, Location::RegisterLocation(R0)); |
2633 locs->set_out(0, Location::RegisterLocation(R0)); | 2633 locs->set_out(0, Location::RegisterLocation(R0)); |
2634 return locs; | 2634 return locs; |
2635 } | 2635 } |
2636 | 2636 |
2637 | 2637 |
2638 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2638 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2639 Register instantiator_reg = locs()->in(0).reg(); | 2639 const Register instantiator_reg = locs()->in(0).reg(); |
2640 Register result_reg = locs()->out(0).reg(); | 2640 const Register result_reg = locs()->out(0).reg(); |
2641 | 2641 |
2642 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2642 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
2643 // A runtime call to instantiate the type is required. | 2643 // A runtime call to instantiate the type is required. |
2644 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2644 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
2645 __ PushObject(type()); | 2645 __ PushObject(type()); |
2646 __ Push(instantiator_reg); // Push instantiator type arguments. | 2646 __ Push(instantiator_reg); // Push instantiator type arguments. |
2647 compiler->GenerateRuntimeCall(token_pos(), | 2647 compiler->GenerateRuntimeCall(token_pos(), |
2648 deopt_id(), | 2648 deopt_id(), |
2649 kInstantiateTypeRuntimeEntry, | 2649 kInstantiateTypeRuntimeEntry, |
2650 2, | 2650 2, |
(...skipping 11 matching lines...) Expand all Loading... |
2662 LocationSummary* locs = | 2662 LocationSummary* locs = |
2663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2663 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
2664 locs->set_in(0, Location::RegisterLocation(R0)); | 2664 locs->set_in(0, Location::RegisterLocation(R0)); |
2665 locs->set_out(0, Location::RegisterLocation(R0)); | 2665 locs->set_out(0, Location::RegisterLocation(R0)); |
2666 return locs; | 2666 return locs; |
2667 } | 2667 } |
2668 | 2668 |
2669 | 2669 |
2670 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2670 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2671 FlowGraphCompiler* compiler) { | 2671 FlowGraphCompiler* compiler) { |
2672 Register instantiator_reg = locs()->in(0).reg(); | 2672 const Register instantiator_reg = locs()->in(0).reg(); |
2673 Register result_reg = locs()->out(0).reg(); | 2673 const Register result_reg = locs()->out(0).reg(); |
2674 ASSERT(instantiator_reg == R0); | 2674 ASSERT(instantiator_reg == R0); |
2675 ASSERT(instantiator_reg == result_reg); | 2675 ASSERT(instantiator_reg == result_reg); |
2676 | 2676 |
2677 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2677 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
2678 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2678 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
2679 !type_arguments().CanShareInstantiatorTypeArguments( | 2679 !type_arguments().CanShareInstantiatorTypeArguments( |
2680 instantiator_class())); | 2680 instantiator_class())); |
2681 // If the instantiator is null and if the type argument vector | 2681 // If the instantiator is null and if the type argument vector |
2682 // instantiated from null becomes a vector of dynamic, then use null as | 2682 // instantiated from null becomes a vector of dynamic, then use null as |
2683 // the type arguments. | 2683 // the type arguments. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2754 const intptr_t kNumTemps = 0; | 2754 const intptr_t kNumTemps = 0; |
2755 LocationSummary* locs = | 2755 LocationSummary* locs = |
2756 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 2756 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
2757 locs->set_in(0, Location::RegisterLocation(R0)); | 2757 locs->set_in(0, Location::RegisterLocation(R0)); |
2758 locs->set_out(0, Location::RegisterLocation(R0)); | 2758 locs->set_out(0, Location::RegisterLocation(R0)); |
2759 return locs; | 2759 return locs; |
2760 } | 2760 } |
2761 | 2761 |
2762 | 2762 |
2763 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2763 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2764 Register context_value = locs()->in(0).reg(); | 2764 const Register context_value = locs()->in(0).reg(); |
2765 Register result = locs()->out(0).reg(); | 2765 const Register result = locs()->out(0).reg(); |
2766 | 2766 |
2767 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2767 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
2768 __ Push(context_value); | 2768 __ Push(context_value); |
2769 compiler->GenerateRuntimeCall(token_pos(), | 2769 compiler->GenerateRuntimeCall(token_pos(), |
2770 deopt_id(), | 2770 deopt_id(), |
2771 kCloneContextRuntimeEntry, | 2771 kCloneContextRuntimeEntry, |
2772 1, | 2772 1, |
2773 locs()); | 2773 locs()); |
2774 __ Drop(1); // Remove argument. | 2774 __ Drop(1); // Remove argument. |
2775 __ Pop(result); // Get result (cloned context). | 2775 __ Pop(result); // Get result (cloned context). |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2826 | 2826 |
2827 | 2827 |
2828 class CheckStackOverflowSlowPath : public SlowPathCode { | 2828 class CheckStackOverflowSlowPath : public SlowPathCode { |
2829 public: | 2829 public: |
2830 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2830 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2831 : instruction_(instruction) { } | 2831 : instruction_(instruction) { } |
2832 | 2832 |
2833 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2833 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2834 if (FLAG_use_osr) { | 2834 if (FLAG_use_osr) { |
2835 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); | 2835 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); |
2836 Register value = instruction_->locs()->temp(0).reg(); | 2836 const Register value = instruction_->locs()->temp(0).reg(); |
2837 __ Comment("CheckStackOverflowSlowPathOsr"); | 2837 __ Comment("CheckStackOverflowSlowPathOsr"); |
2838 __ Bind(osr_entry_label()); | 2838 __ Bind(osr_entry_label()); |
2839 __ LoadImmediate(IP, flags_address); | 2839 __ LoadImmediate(IP, flags_address); |
2840 __ LoadImmediate(value, Isolate::kOsrRequest); | 2840 __ LoadImmediate(value, Isolate::kOsrRequest); |
2841 __ str(value, Address(IP)); | 2841 __ str(value, Address(IP)); |
2842 } | 2842 } |
2843 __ Comment("CheckStackOverflowSlowPath"); | 2843 __ Comment("CheckStackOverflowSlowPath"); |
2844 __ Bind(entry_label()); | 2844 __ Bind(entry_label()); |
2845 compiler->SaveLiveRegisters(instruction_->locs()); | 2845 compiler->SaveLiveRegisters(instruction_->locs()); |
2846 // pending_deoptimization_env_ is needed to generate a runtime call that | 2846 // pending_deoptimization_env_ is needed to generate a runtime call that |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2878 | 2878 |
2879 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2879 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2880 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2880 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
2881 compiler->AddSlowPathCode(slow_path); | 2881 compiler->AddSlowPathCode(slow_path); |
2882 | 2882 |
2883 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); | 2883 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); |
2884 __ ldr(IP, Address(IP)); | 2884 __ ldr(IP, Address(IP)); |
2885 __ cmp(SP, ShifterOperand(IP)); | 2885 __ cmp(SP, ShifterOperand(IP)); |
2886 __ b(slow_path->entry_label(), LS); | 2886 __ b(slow_path->entry_label(), LS); |
2887 if (compiler->CanOSRFunction() && in_loop()) { | 2887 if (compiler->CanOSRFunction() && in_loop()) { |
2888 Register temp = locs()->temp(0).reg(); | 2888 const Register temp = locs()->temp(0).reg(); |
2889 // In unoptimized code check the usage counter to trigger OSR at loop | 2889 // In unoptimized code check the usage counter to trigger OSR at loop |
2890 // stack checks. Use progressively higher thresholds for more deeply | 2890 // stack checks. Use progressively higher thresholds for more deeply |
2891 // nested loops to attempt to hit outer loops with OSR when possible. | 2891 // nested loops to attempt to hit outer loops with OSR when possible. |
2892 __ LoadObject(temp, compiler->parsed_function().function()); | 2892 __ LoadObject(temp, compiler->parsed_function().function()); |
2893 intptr_t threshold = | 2893 intptr_t threshold = |
2894 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2894 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2895 __ ldr(temp, FieldAddress(temp, Function::usage_counter_offset())); | 2895 __ ldr(temp, FieldAddress(temp, Function::usage_counter_offset())); |
2896 __ CompareImmediate(temp, threshold); | 2896 __ CompareImmediate(temp, threshold); |
2897 __ b(slow_path->osr_entry_label(), GE); | 2897 __ b(slow_path->osr_entry_label(), GE); |
2898 } | 2898 } |
2899 if (compiler->ForceSlowPathForStackOverflow()) { | 2899 if (compiler->ForceSlowPathForStackOverflow()) { |
2900 __ b(slow_path->entry_label()); | 2900 __ b(slow_path->entry_label()); |
2901 } | 2901 } |
2902 __ Bind(slow_path->exit_label()); | 2902 __ Bind(slow_path->exit_label()); |
2903 } | 2903 } |
2904 | 2904 |
2905 | 2905 |
2906 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2906 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2907 BinarySmiOpInstr* shift_left) { | 2907 BinarySmiOpInstr* shift_left) { |
2908 const bool is_truncating = shift_left->is_truncating(); | 2908 const bool is_truncating = shift_left->is_truncating(); |
2909 const LocationSummary& locs = *shift_left->locs(); | 2909 const LocationSummary& locs = *shift_left->locs(); |
2910 Register left = locs.in(0).reg(); | 2910 const Register left = locs.in(0).reg(); |
2911 Register result = locs.out(0).reg(); | 2911 const Register result = locs.out(0).reg(); |
2912 Label* deopt = shift_left->CanDeoptimize() ? | 2912 Label* deopt = shift_left->CanDeoptimize() ? |
2913 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2913 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) |
2914 : NULL; | 2914 : NULL; |
2915 if (locs.in(1).IsConstant()) { | 2915 if (locs.in(1).IsConstant()) { |
2916 const Object& constant = locs.in(1).constant(); | 2916 const Object& constant = locs.in(1).constant(); |
2917 ASSERT(constant.IsSmi()); | 2917 ASSERT(constant.IsSmi()); |
2918 // Immediate shift operation takes 5 bits for the count. | 2918 // Immediate shift operation takes 5 bits for the count. |
2919 const intptr_t kCountLimit = 0x1F; | 2919 const intptr_t kCountLimit = 0x1F; |
2920 const intptr_t value = Smi::Cast(constant).Value(); | 2920 const intptr_t value = Smi::Cast(constant).Value(); |
2921 if (value == 0) { | 2921 if (value == 0) { |
(...skipping 14 matching lines...) Expand all Loading... |
2936 __ cmp(left, ShifterOperand(IP, ASR, value)); | 2936 __ cmp(left, ShifterOperand(IP, ASR, value)); |
2937 __ b(deopt, NE); // Overflow. | 2937 __ b(deopt, NE); // Overflow. |
2938 } | 2938 } |
2939 // Shift for result now we know there is no overflow. | 2939 // Shift for result now we know there is no overflow. |
2940 __ Lsl(result, left, value); | 2940 __ Lsl(result, left, value); |
2941 } | 2941 } |
2942 return; | 2942 return; |
2943 } | 2943 } |
2944 | 2944 |
2945 // Right (locs.in(1)) is not constant. | 2945 // Right (locs.in(1)) is not constant. |
2946 Register right = locs.in(1).reg(); | 2946 const Register right = locs.in(1).reg(); |
2947 Range* right_range = shift_left->right()->definition()->range(); | 2947 Range* right_range = shift_left->right()->definition()->range(); |
2948 if (shift_left->left()->BindsToConstant() && !is_truncating) { | 2948 if (shift_left->left()->BindsToConstant() && !is_truncating) { |
2949 // TODO(srdjan): Implement code below for is_truncating(). | 2949 // TODO(srdjan): Implement code below for is_truncating(). |
2950 // If left is constant, we know the maximal allowed size for right. | 2950 // If left is constant, we know the maximal allowed size for right. |
2951 const Object& obj = shift_left->left()->BoundConstant(); | 2951 const Object& obj = shift_left->left()->BoundConstant(); |
2952 if (obj.IsSmi()) { | 2952 if (obj.IsSmi()) { |
2953 const intptr_t left_int = Smi::Cast(obj).Value(); | 2953 const intptr_t left_int = Smi::Cast(obj).Value(); |
2954 if (left_int == 0) { | 2954 if (left_int == 0) { |
2955 __ cmp(right, ShifterOperand(0)); | 2955 __ cmp(right, ShifterOperand(0)); |
2956 __ b(deopt, MI); | 2956 __ b(deopt, MI); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2998 if (right_needs_check) { | 2998 if (right_needs_check) { |
2999 ASSERT(shift_left->CanDeoptimize()); | 2999 ASSERT(shift_left->CanDeoptimize()); |
3000 __ cmp(right, | 3000 __ cmp(right, |
3001 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 3001 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
3002 __ b(deopt, CS); | 3002 __ b(deopt, CS); |
3003 } | 3003 } |
3004 // Left is not a constant. | 3004 // Left is not a constant. |
3005 // Check if count too large for handling it inlined. | 3005 // Check if count too large for handling it inlined. |
3006 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3006 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
3007 // Overflow test (preserve left, right, and IP); | 3007 // Overflow test (preserve left, right, and IP); |
3008 Register temp = locs.temp(0).reg(); | 3008 const Register temp = locs.temp(0).reg(); |
3009 __ Lsl(temp, left, IP); | 3009 __ Lsl(temp, left, IP); |
3010 __ cmp(left, ShifterOperand(temp, ASR, IP)); | 3010 __ cmp(left, ShifterOperand(temp, ASR, IP)); |
3011 __ b(deopt, NE); // Overflow. | 3011 __ b(deopt, NE); // Overflow. |
3012 // Shift for result now we know there is no overflow. | 3012 // Shift for result now we know there is no overflow. |
3013 __ Lsl(result, left, IP); | 3013 __ Lsl(result, left, IP); |
3014 } | 3014 } |
3015 } | 3015 } |
3016 | 3016 |
3017 | 3017 |
3018 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const { | 3018 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3060 } | 3060 } |
3061 | 3061 |
3062 | 3062 |
3063 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3063 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3064 if (op_kind() == Token::kSHL) { | 3064 if (op_kind() == Token::kSHL) { |
3065 EmitSmiShiftLeft(compiler, this); | 3065 EmitSmiShiftLeft(compiler, this); |
3066 return; | 3066 return; |
3067 } | 3067 } |
3068 | 3068 |
3069 ASSERT(!is_truncating()); | 3069 ASSERT(!is_truncating()); |
3070 Register left = locs()->in(0).reg(); | 3070 const Register left = locs()->in(0).reg(); |
3071 Register result = locs()->out(0).reg(); | 3071 const Register result = locs()->out(0).reg(); |
3072 Label* deopt = NULL; | 3072 Label* deopt = NULL; |
3073 if (CanDeoptimize()) { | 3073 if (CanDeoptimize()) { |
3074 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 3074 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
3075 } | 3075 } |
3076 | 3076 |
3077 if (locs()->in(1).IsConstant()) { | 3077 if (locs()->in(1).IsConstant()) { |
3078 const Object& constant = locs()->in(1).constant(); | 3078 const Object& constant = locs()->in(1).constant(); |
3079 ASSERT(constant.IsSmi()); | 3079 ASSERT(constant.IsSmi()); |
3080 const int32_t imm = reinterpret_cast<int32_t>(constant.raw()); | 3080 const int32_t imm = reinterpret_cast<int32_t>(constant.raw()); |
3081 switch (op_kind()) { | 3081 switch (op_kind()) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3147 __ b(deopt, EQ); | 3147 __ b(deopt, EQ); |
3148 __ rsb(result, left, ShifterOperand(0)); | 3148 __ rsb(result, left, ShifterOperand(0)); |
3149 break; | 3149 break; |
3150 } | 3150 } |
3151 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); | 3151 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); |
3152 const intptr_t shift_count = | 3152 const intptr_t shift_count = |
3153 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; | 3153 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; |
3154 ASSERT(kSmiTagSize == 1); | 3154 ASSERT(kSmiTagSize == 1); |
3155 __ mov(IP, ShifterOperand(left, ASR, 31)); | 3155 __ mov(IP, ShifterOperand(left, ASR, 31)); |
3156 ASSERT(shift_count > 1); // 1, -1 case handled above. | 3156 ASSERT(shift_count > 1); // 1, -1 case handled above. |
3157 Register temp = locs()->temp(0).reg(); | 3157 const Register temp = locs()->temp(0).reg(); |
3158 __ add(temp, left, ShifterOperand(IP, LSR, 32 - shift_count)); | 3158 __ add(temp, left, ShifterOperand(IP, LSR, 32 - shift_count)); |
3159 ASSERT(shift_count > 0); | 3159 ASSERT(shift_count > 0); |
3160 __ mov(result, ShifterOperand(temp, ASR, shift_count)); | 3160 __ mov(result, ShifterOperand(temp, ASR, shift_count)); |
3161 if (value < 0) { | 3161 if (value < 0) { |
3162 __ rsb(result, result, ShifterOperand(0)); | 3162 __ rsb(result, result, ShifterOperand(0)); |
3163 } | 3163 } |
3164 __ SmiTag(result); | 3164 __ SmiTag(result); |
3165 break; | 3165 break; |
3166 } | 3166 } |
3167 case Token::kBIT_AND: { | 3167 case Token::kBIT_AND: { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3224 break; | 3224 break; |
3225 } | 3225 } |
3226 | 3226 |
3227 default: | 3227 default: |
3228 UNREACHABLE(); | 3228 UNREACHABLE(); |
3229 break; | 3229 break; |
3230 } | 3230 } |
3231 return; | 3231 return; |
3232 } | 3232 } |
3233 | 3233 |
3234 Register right = locs()->in(1).reg(); | 3234 const Register right = locs()->in(1).reg(); |
3235 Range* right_range = this->right()->definition()->range(); | 3235 Range* right_range = this->right()->definition()->range(); |
3236 switch (op_kind()) { | 3236 switch (op_kind()) { |
3237 case Token::kADD: { | 3237 case Token::kADD: { |
3238 if (deopt == NULL) { | 3238 if (deopt == NULL) { |
3239 __ add(result, left, ShifterOperand(right)); | 3239 __ add(result, left, ShifterOperand(right)); |
3240 } else { | 3240 } else { |
3241 __ adds(result, left, ShifterOperand(right)); | 3241 __ adds(result, left, ShifterOperand(right)); |
3242 __ b(deopt, VS); | 3242 __ b(deopt, VS); |
3243 } | 3243 } |
3244 break; | 3244 break; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3286 // No overflow check. | 3286 // No overflow check. |
3287 __ eor(result, left, ShifterOperand(right)); | 3287 __ eor(result, left, ShifterOperand(right)); |
3288 break; | 3288 break; |
3289 } | 3289 } |
3290 case Token::kTRUNCDIV: { | 3290 case Token::kTRUNCDIV: { |
3291 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3291 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
3292 // Handle divide by zero in runtime. | 3292 // Handle divide by zero in runtime. |
3293 __ cmp(right, ShifterOperand(0)); | 3293 __ cmp(right, ShifterOperand(0)); |
3294 __ b(deopt, EQ); | 3294 __ b(deopt, EQ); |
3295 } | 3295 } |
3296 Register temp = locs()->temp(0).reg(); | 3296 const Register temp = locs()->temp(0).reg(); |
3297 DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3297 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
3298 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3298 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
3299 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3299 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
3300 | 3300 |
3301 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3301 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
3302 | 3302 |
3303 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3303 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
3304 // case we cannot tag the result. | 3304 // case we cannot tag the result. |
3305 __ CompareImmediate(result, 0x40000000); | 3305 __ CompareImmediate(result, 0x40000000); |
3306 __ b(deopt, EQ); | 3306 __ b(deopt, EQ); |
3307 __ SmiTag(result); | 3307 __ SmiTag(result); |
3308 break; | 3308 break; |
3309 } | 3309 } |
3310 case Token::kMOD: { | 3310 case Token::kMOD: { |
3311 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3311 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
3312 // Handle divide by zero in runtime. | 3312 // Handle divide by zero in runtime. |
3313 __ cmp(right, ShifterOperand(0)); | 3313 __ cmp(right, ShifterOperand(0)); |
3314 __ b(deopt, EQ); | 3314 __ b(deopt, EQ); |
3315 } | 3315 } |
3316 Register temp = locs()->temp(0).reg(); | 3316 const Register temp = locs()->temp(0).reg(); |
3317 DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3317 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
3318 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3318 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
3319 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3319 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
3320 | 3320 |
3321 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3321 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
3322 | 3322 |
3323 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3323 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
3324 __ mls(result, IP, result, temp); // result <- left - right * result | 3324 __ mls(result, IP, result, temp); // result <- left - right * result |
3325 __ SmiTag(result); | 3325 __ SmiTag(result); |
3326 // res = left % right; | 3326 // res = left % right; |
3327 // if (res < 0) { | 3327 // if (res < 0) { |
(...skipping 19 matching lines...) Expand all Loading... |
3347 __ b(deopt, LT); | 3347 __ b(deopt, LT); |
3348 } | 3348 } |
3349 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3349 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
3350 // sarl operation masks the count to 5 bits. | 3350 // sarl operation masks the count to 5 bits. |
3351 const intptr_t kCountLimit = 0x1F; | 3351 const intptr_t kCountLimit = 0x1F; |
3352 if ((right_range == NULL) || | 3352 if ((right_range == NULL) || |
3353 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 3353 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
3354 __ CompareImmediate(IP, kCountLimit); | 3354 __ CompareImmediate(IP, kCountLimit); |
3355 __ LoadImmediate(IP, kCountLimit, GT); | 3355 __ LoadImmediate(IP, kCountLimit, GT); |
3356 } | 3356 } |
3357 Register temp = locs()->temp(0).reg(); | 3357 const Register temp = locs()->temp(0).reg(); |
3358 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3358 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
3359 __ Asr(result, temp, IP); | 3359 __ Asr(result, temp, IP); |
3360 __ SmiTag(result); | 3360 __ SmiTag(result); |
3361 break; | 3361 break; |
3362 } | 3362 } |
3363 case Token::kDIV: { | 3363 case Token::kDIV: { |
3364 // Dispatches to 'Double./'. | 3364 // Dispatches to 'Double./'. |
3365 // TODO(srdjan): Implement as conversion to double and double division. | 3365 // TODO(srdjan): Implement as conversion to double and double division. |
3366 UNREACHABLE(); | 3366 UNREACHABLE(); |
3367 break; | 3367 break; |
(...skipping 24 matching lines...) Expand all Loading... |
3392 summary->set_in(1, Location::RequiresRegister()); | 3392 summary->set_in(1, Location::RequiresRegister()); |
3393 return summary; | 3393 return summary; |
3394 } | 3394 } |
3395 | 3395 |
3396 | 3396 |
3397 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3397 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3398 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3398 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
3399 ICData::kDeoptBinaryDoubleOp); | 3399 ICData::kDeoptBinaryDoubleOp); |
3400 intptr_t left_cid = left()->Type()->ToCid(); | 3400 intptr_t left_cid = left()->Type()->ToCid(); |
3401 intptr_t right_cid = right()->Type()->ToCid(); | 3401 intptr_t right_cid = right()->Type()->ToCid(); |
3402 Register left = locs()->in(0).reg(); | 3402 const Register left = locs()->in(0).reg(); |
3403 Register right = locs()->in(1).reg(); | 3403 const Register right = locs()->in(1).reg(); |
3404 if (this->left()->definition() == this->right()->definition()) { | 3404 if (this->left()->definition() == this->right()->definition()) { |
3405 __ tst(left, ShifterOperand(kSmiTagMask)); | 3405 __ tst(left, ShifterOperand(kSmiTagMask)); |
3406 } else if (left_cid == kSmiCid) { | 3406 } else if (left_cid == kSmiCid) { |
3407 __ tst(right, ShifterOperand(kSmiTagMask)); | 3407 __ tst(right, ShifterOperand(kSmiTagMask)); |
3408 } else if (right_cid == kSmiCid) { | 3408 } else if (right_cid == kSmiCid) { |
3409 __ tst(left, ShifterOperand(kSmiTagMask)); | 3409 __ tst(left, ShifterOperand(kSmiTagMask)); |
3410 } else { | 3410 } else { |
3411 __ orr(IP, left, ShifterOperand(right)); | 3411 __ orr(IP, left, ShifterOperand(right)); |
3412 __ tst(IP, ShifterOperand(kSmiTagMask)); | 3412 __ tst(IP, ShifterOperand(kSmiTagMask)); |
3413 } | 3413 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3470 | 3470 |
3471 if (value_cid == kDoubleCid) { | 3471 if (value_cid == kDoubleCid) { |
3472 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); | 3472 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); |
3473 } else if (value_cid == kSmiCid) { | 3473 } else if (value_cid == kSmiCid) { |
3474 __ SmiUntag(value); // Untag input before conversion. | 3474 __ SmiUntag(value); // Untag input before conversion. |
3475 __ vmovsr(STMP, value); | 3475 __ vmovsr(STMP, value); |
3476 __ vcvtdi(result, STMP); | 3476 __ vcvtdi(result, STMP); |
3477 } else { | 3477 } else { |
3478 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 3478 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
3479 ICData::kDeoptBinaryDoubleOp); | 3479 ICData::kDeoptBinaryDoubleOp); |
3480 Register temp = locs()->temp(0).reg(); | 3480 const Register temp = locs()->temp(0).reg(); |
3481 if (value_type->is_nullable() && | 3481 if (value_type->is_nullable() && |
3482 (value_type->ToNullableCid() == kDoubleCid)) { | 3482 (value_type->ToNullableCid() == kDoubleCid)) { |
3483 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); | 3483 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); |
3484 __ b(deopt, EQ); | 3484 __ b(deopt, EQ); |
3485 // It must be double now. | 3485 // It must be double now. |
3486 __ LoadDFromOffset(result, value, | 3486 __ LoadDFromOffset(result, value, |
3487 Double::value_offset() - kHeapObjectTag); | 3487 Double::value_offset() - kHeapObjectTag); |
3488 } else { | 3488 } else { |
3489 Label is_smi, done; | 3489 Label is_smi, done; |
3490 __ tst(value, ShifterOperand(kSmiTagMask)); | 3490 __ tst(value, ShifterOperand(kSmiTagMask)); |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3775 LocationSummary* summary = | 3775 LocationSummary* summary = |
3776 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3776 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3777 summary->set_in(0, Location::RequiresFpuRegister()); | 3777 summary->set_in(0, Location::RequiresFpuRegister()); |
3778 summary->set_in(1, Location::RequiresFpuRegister()); | 3778 summary->set_in(1, Location::RequiresFpuRegister()); |
3779 summary->set_out(0, Location::RequiresFpuRegister()); | 3779 summary->set_out(0, Location::RequiresFpuRegister()); |
3780 return summary; | 3780 return summary; |
3781 } | 3781 } |
3782 | 3782 |
3783 | 3783 |
3784 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3784 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3785 QRegister left = locs()->in(0).fpu_reg(); | 3785 const QRegister left = locs()->in(0).fpu_reg(); |
3786 QRegister right = locs()->in(1).fpu_reg(); | 3786 const QRegister right = locs()->in(1).fpu_reg(); |
3787 QRegister result = locs()->out(0).fpu_reg(); | 3787 const QRegister result = locs()->out(0).fpu_reg(); |
3788 | 3788 |
3789 switch (op_kind()) { | 3789 switch (op_kind()) { |
3790 case Token::kADD: __ vaddqs(result, left, right); break; | 3790 case Token::kADD: __ vaddqs(result, left, right); break; |
3791 case Token::kSUB: __ vsubqs(result, left, right); break; | 3791 case Token::kSUB: __ vsubqs(result, left, right); break; |
3792 case Token::kMUL: __ vmulqs(result, left, right); break; | 3792 case Token::kMUL: __ vmulqs(result, left, right); break; |
3793 case Token::kDIV: __ Vdivqs(result, left, right); break; | 3793 case Token::kDIV: __ Vdivqs(result, left, right); break; |
3794 default: UNREACHABLE(); | 3794 default: UNREACHABLE(); |
3795 } | 3795 } |
3796 } | 3796 } |
3797 | 3797 |
3798 | 3798 |
3799 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(bool opt) const { | 3799 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(bool opt) const { |
3800 const intptr_t kNumInputs = 2; | 3800 const intptr_t kNumInputs = 2; |
3801 const intptr_t kNumTemps = 0; | 3801 const intptr_t kNumTemps = 0; |
3802 LocationSummary* summary = | 3802 LocationSummary* summary = |
3803 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3803 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3804 summary->set_in(0, Location::RequiresFpuRegister()); | 3804 summary->set_in(0, Location::RequiresFpuRegister()); |
3805 summary->set_in(1, Location::RequiresFpuRegister()); | 3805 summary->set_in(1, Location::RequiresFpuRegister()); |
3806 summary->set_out(0, Location::RequiresFpuRegister()); | 3806 summary->set_out(0, Location::RequiresFpuRegister()); |
3807 return summary; | 3807 return summary; |
3808 } | 3808 } |
3809 | 3809 |
3810 | 3810 |
3811 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3811 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3812 QRegister left = locs()->in(0).fpu_reg(); | 3812 const QRegister left = locs()->in(0).fpu_reg(); |
3813 QRegister right = locs()->in(1).fpu_reg(); | 3813 const QRegister right = locs()->in(1).fpu_reg(); |
3814 QRegister result = locs()->out(0).fpu_reg(); | 3814 const QRegister result = locs()->out(0).fpu_reg(); |
3815 | 3815 |
3816 DRegister left0 = EvenDRegisterOf(left); | 3816 const DRegister left0 = EvenDRegisterOf(left); |
3817 DRegister left1 = OddDRegisterOf(left); | 3817 const DRegister left1 = OddDRegisterOf(left); |
3818 | 3818 |
3819 DRegister right0 = EvenDRegisterOf(right); | 3819 const DRegister right0 = EvenDRegisterOf(right); |
3820 DRegister right1 = OddDRegisterOf(right); | 3820 const DRegister right1 = OddDRegisterOf(right); |
3821 | 3821 |
3822 DRegister result0 = EvenDRegisterOf(result); | 3822 const DRegister result0 = EvenDRegisterOf(result); |
3823 DRegister result1 = OddDRegisterOf(result); | 3823 const DRegister result1 = OddDRegisterOf(result); |
3824 | 3824 |
3825 switch (op_kind()) { | 3825 switch (op_kind()) { |
3826 case Token::kADD: | 3826 case Token::kADD: |
3827 __ vaddd(result0, left0, right0); | 3827 __ vaddd(result0, left0, right0); |
3828 __ vaddd(result1, left1, right1); | 3828 __ vaddd(result1, left1, right1); |
3829 break; | 3829 break; |
3830 case Token::kSUB: | 3830 case Token::kSUB: |
3831 __ vsubd(result0, left0, right0); | 3831 __ vsubd(result0, left0, right0); |
3832 __ vsubd(result1, left1, right1); | 3832 __ vsubd(result1, left1, right1); |
3833 break; | 3833 break; |
(...skipping 16 matching lines...) Expand all Loading... |
3850 LocationSummary* summary = | 3850 LocationSummary* summary = |
3851 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3851 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3852 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. | 3852 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. |
3853 summary->set_in(0, Location::FpuRegisterLocation(Q5)); | 3853 summary->set_in(0, Location::FpuRegisterLocation(Q5)); |
3854 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 3854 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
3855 return summary; | 3855 return summary; |
3856 } | 3856 } |
3857 | 3857 |
3858 | 3858 |
3859 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3859 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3860 QRegister value = locs()->in(0).fpu_reg(); | 3860 const QRegister value = locs()->in(0).fpu_reg(); |
3861 QRegister result = locs()->out(0).fpu_reg(); | 3861 const QRegister result = locs()->out(0).fpu_reg(); |
3862 DRegister dresult0 = EvenDRegisterOf(result); | 3862 const DRegister dresult0 = EvenDRegisterOf(result); |
3863 DRegister dresult1 = OddDRegisterOf(result); | 3863 const DRegister dresult1 = OddDRegisterOf(result); |
3864 SRegister sresult0 = EvenSRegisterOf(dresult0); | 3864 const SRegister sresult0 = EvenSRegisterOf(dresult0); |
3865 SRegister sresult1 = OddSRegisterOf(dresult0); | 3865 const SRegister sresult1 = OddSRegisterOf(dresult0); |
3866 SRegister sresult2 = EvenSRegisterOf(dresult1); | 3866 const SRegister sresult2 = EvenSRegisterOf(dresult1); |
3867 SRegister sresult3 = OddSRegisterOf(dresult1); | 3867 const SRegister sresult3 = OddSRegisterOf(dresult1); |
3868 | 3868 |
3869 DRegister dvalue0 = EvenDRegisterOf(value); | 3869 const DRegister dvalue0 = EvenDRegisterOf(value); |
3870 DRegister dvalue1 = OddDRegisterOf(value); | 3870 const DRegister dvalue1 = OddDRegisterOf(value); |
3871 | 3871 |
3872 DRegister dtemp0 = DTMP; | 3872 const DRegister dtemp0 = DTMP; |
3873 DRegister dtemp1 = OddDRegisterOf(QTMP); | 3873 const DRegister dtemp1 = OddDRegisterOf(QTMP); |
3874 | 3874 |
3875 // For some cases the vdup instruction requires fewer | 3875 // For some cases the vdup instruction requires fewer |
3876 // instructions. For arbitrary shuffles, use vtbl. | 3876 // instructions. For arbitrary shuffles, use vtbl. |
3877 | 3877 |
3878 switch (op_kind()) { | 3878 switch (op_kind()) { |
3879 case MethodRecognizer::kFloat32x4ShuffleX: | 3879 case MethodRecognizer::kFloat32x4ShuffleX: |
3880 __ vdup(kWord, result, dvalue0, 0); | 3880 __ vdup(kWord, result, dvalue0, 0); |
3881 __ vcvtds(dresult0, sresult0); | 3881 __ vcvtds(dresult0, sresult0); |
3882 break; | 3882 break; |
3883 case MethodRecognizer::kFloat32x4ShuffleY: | 3883 case MethodRecognizer::kFloat32x4ShuffleY: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3931 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3931 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3932 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. | 3932 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. |
3933 summary->set_in(0, Location::FpuRegisterLocation(Q4)); | 3933 summary->set_in(0, Location::FpuRegisterLocation(Q4)); |
3934 summary->set_in(1, Location::FpuRegisterLocation(Q5)); | 3934 summary->set_in(1, Location::FpuRegisterLocation(Q5)); |
3935 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 3935 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
3936 return summary; | 3936 return summary; |
3937 } | 3937 } |
3938 | 3938 |
3939 | 3939 |
3940 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3940 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3941 QRegister left = locs()->in(0).fpu_reg(); | 3941 const QRegister left = locs()->in(0).fpu_reg(); |
3942 QRegister right = locs()->in(1).fpu_reg(); | 3942 const QRegister right = locs()->in(1).fpu_reg(); |
3943 QRegister result = locs()->out(0).fpu_reg(); | 3943 const QRegister result = locs()->out(0).fpu_reg(); |
3944 | 3944 |
3945 DRegister dresult0 = EvenDRegisterOf(result); | 3945 const DRegister dresult0 = EvenDRegisterOf(result); |
3946 DRegister dresult1 = OddDRegisterOf(result); | 3946 const DRegister dresult1 = OddDRegisterOf(result); |
3947 SRegister sresult0 = EvenSRegisterOf(dresult0); | 3947 const SRegister sresult0 = EvenSRegisterOf(dresult0); |
3948 SRegister sresult1 = OddSRegisterOf(dresult0); | 3948 const SRegister sresult1 = OddSRegisterOf(dresult0); |
3949 SRegister sresult2 = EvenSRegisterOf(dresult1); | 3949 const SRegister sresult2 = EvenSRegisterOf(dresult1); |
3950 SRegister sresult3 = OddSRegisterOf(dresult1); | 3950 const SRegister sresult3 = OddSRegisterOf(dresult1); |
3951 | 3951 |
3952 DRegister dleft0 = EvenDRegisterOf(left); | 3952 const DRegister dleft0 = EvenDRegisterOf(left); |
3953 DRegister dleft1 = OddDRegisterOf(left); | 3953 const DRegister dleft1 = OddDRegisterOf(left); |
3954 DRegister dright0 = EvenDRegisterOf(right); | 3954 const DRegister dright0 = EvenDRegisterOf(right); |
3955 DRegister dright1 = OddDRegisterOf(right); | 3955 const DRegister dright1 = OddDRegisterOf(right); |
3956 | 3956 |
3957 switch (op_kind()) { | 3957 switch (op_kind()) { |
3958 case MethodRecognizer::kFloat32x4ShuffleMix: | 3958 case MethodRecognizer::kFloat32x4ShuffleMix: |
3959 case MethodRecognizer::kInt32x4ShuffleMix: | 3959 case MethodRecognizer::kInt32x4ShuffleMix: |
3960 // TODO(zra): Investigate better instruction sequences for shuffle masks. | 3960 // TODO(zra): Investigate better instruction sequences for shuffle masks. |
3961 SRegister left_svalues[4]; | 3961 SRegister left_svalues[4]; |
3962 SRegister right_svalues[4]; | 3962 SRegister right_svalues[4]; |
3963 | 3963 |
3964 left_svalues[0] = EvenSRegisterOf(dleft0); | 3964 left_svalues[0] = EvenSRegisterOf(dleft0); |
3965 left_svalues[1] = OddSRegisterOf(dleft0); | 3965 left_svalues[1] = OddSRegisterOf(dleft0); |
(...skipping 20 matching lines...) Expand all Loading... |
3986 LocationSummary* summary = | 3986 LocationSummary* summary = |
3987 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3987 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3988 summary->set_in(0, Location::FpuRegisterLocation(Q5)); | 3988 summary->set_in(0, Location::FpuRegisterLocation(Q5)); |
3989 summary->set_temp(0, Location::RequiresRegister()); | 3989 summary->set_temp(0, Location::RequiresRegister()); |
3990 summary->set_out(0, Location::RequiresRegister()); | 3990 summary->set_out(0, Location::RequiresRegister()); |
3991 return summary; | 3991 return summary; |
3992 } | 3992 } |
3993 | 3993 |
3994 | 3994 |
3995 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3995 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3996 QRegister value = locs()->in(0).fpu_reg(); | 3996 const QRegister value = locs()->in(0).fpu_reg(); |
3997 DRegister dvalue0 = EvenDRegisterOf(value); | 3997 const DRegister dvalue0 = EvenDRegisterOf(value); |
3998 DRegister dvalue1 = OddDRegisterOf(value); | 3998 const DRegister dvalue1 = OddDRegisterOf(value); |
3999 | 3999 |
4000 Register out = locs()->out(0).reg(); | 4000 const Register out = locs()->out(0).reg(); |
4001 Register temp = locs()->temp(0).reg(); | 4001 const Register temp = locs()->temp(0).reg(); |
4002 | 4002 |
4003 // X lane. | 4003 // X lane. |
4004 __ vmovrs(out, EvenSRegisterOf(dvalue0)); | 4004 __ vmovrs(out, EvenSRegisterOf(dvalue0)); |
4005 __ Lsr(out, out, 31); | 4005 __ Lsr(out, out, 31); |
4006 // Y lane. | 4006 // Y lane. |
4007 __ vmovrs(temp, OddSRegisterOf(dvalue0)); | 4007 __ vmovrs(temp, OddSRegisterOf(dvalue0)); |
4008 __ Lsr(temp, temp, 31); | 4008 __ Lsr(temp, temp, 31); |
4009 __ orr(out, out, ShifterOperand(temp, LSL, 1)); | 4009 __ orr(out, out, ShifterOperand(temp, LSL, 1)); |
4010 // Z lane. | 4010 // Z lane. |
4011 __ vmovrs(temp, EvenSRegisterOf(dvalue1)); | 4011 __ vmovrs(temp, EvenSRegisterOf(dvalue1)); |
(...skipping 18 matching lines...) Expand all Loading... |
4030 summary->set_in(1, Location::RequiresFpuRegister()); | 4030 summary->set_in(1, Location::RequiresFpuRegister()); |
4031 summary->set_in(2, Location::RequiresFpuRegister()); | 4031 summary->set_in(2, Location::RequiresFpuRegister()); |
4032 summary->set_in(3, Location::RequiresFpuRegister()); | 4032 summary->set_in(3, Location::RequiresFpuRegister()); |
4033 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 4033 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
4034 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4034 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4035 return summary; | 4035 return summary; |
4036 } | 4036 } |
4037 | 4037 |
4038 | 4038 |
4039 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4039 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4040 QRegister q0 = locs()->in(0).fpu_reg(); | 4040 const QRegister q0 = locs()->in(0).fpu_reg(); |
4041 QRegister q1 = locs()->in(1).fpu_reg(); | 4041 const QRegister q1 = locs()->in(1).fpu_reg(); |
4042 QRegister q2 = locs()->in(2).fpu_reg(); | 4042 const QRegister q2 = locs()->in(2).fpu_reg(); |
4043 QRegister q3 = locs()->in(3).fpu_reg(); | 4043 const QRegister q3 = locs()->in(3).fpu_reg(); |
4044 QRegister r = locs()->out(0).fpu_reg(); | 4044 const QRegister r = locs()->out(0).fpu_reg(); |
4045 | 4045 |
4046 DRegister dr0 = EvenDRegisterOf(r); | 4046 const DRegister dr0 = EvenDRegisterOf(r); |
4047 DRegister dr1 = OddDRegisterOf(r); | 4047 const DRegister dr1 = OddDRegisterOf(r); |
4048 | 4048 |
4049 __ vcvtsd(EvenSRegisterOf(dr0), EvenDRegisterOf(q0)); | 4049 __ vcvtsd(EvenSRegisterOf(dr0), EvenDRegisterOf(q0)); |
4050 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); | 4050 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); |
4051 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); | 4051 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); |
4052 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); | 4052 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); |
4053 } | 4053 } |
4054 | 4054 |
4055 | 4055 |
4056 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const { | 4056 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(bool opt) const { |
4057 const intptr_t kNumInputs = 0; | 4057 const intptr_t kNumInputs = 0; |
4058 const intptr_t kNumTemps = 0; | 4058 const intptr_t kNumTemps = 0; |
4059 LocationSummary* summary = | 4059 LocationSummary* summary = |
4060 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4060 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4061 summary->set_out(0, Location::RequiresFpuRegister()); | 4061 summary->set_out(0, Location::RequiresFpuRegister()); |
4062 return summary; | 4062 return summary; |
4063 } | 4063 } |
4064 | 4064 |
4065 | 4065 |
4066 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4066 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4067 QRegister q = locs()->out(0).fpu_reg(); | 4067 const QRegister q = locs()->out(0).fpu_reg(); |
4068 __ veorq(q, q, q); | 4068 __ veorq(q, q, q); |
4069 } | 4069 } |
4070 | 4070 |
4071 | 4071 |
4072 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const { | 4072 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(bool opt) const { |
4073 const intptr_t kNumInputs = 1; | 4073 const intptr_t kNumInputs = 1; |
4074 const intptr_t kNumTemps = 0; | 4074 const intptr_t kNumTemps = 0; |
4075 LocationSummary* summary = | 4075 LocationSummary* summary = |
4076 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4076 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4077 summary->set_in(0, Location::RequiresFpuRegister()); | 4077 summary->set_in(0, Location::RequiresFpuRegister()); |
4078 summary->set_out(0, Location::RequiresFpuRegister()); | 4078 summary->set_out(0, Location::RequiresFpuRegister()); |
4079 return summary; | 4079 return summary; |
4080 } | 4080 } |
4081 | 4081 |
4082 | 4082 |
4083 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4083 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4084 QRegister value = locs()->in(0).fpu_reg(); | 4084 const QRegister value = locs()->in(0).fpu_reg(); |
4085 QRegister result = locs()->out(0).fpu_reg(); | 4085 const QRegister result = locs()->out(0).fpu_reg(); |
4086 | 4086 |
4087 DRegister dvalue0 = EvenDRegisterOf(value); | 4087 const DRegister dvalue0 = EvenDRegisterOf(value); |
4088 | 4088 |
4089 // Convert to Float32. | 4089 // Convert to Float32. |
4090 __ vcvtsd(STMP, dvalue0); | 4090 __ vcvtsd(STMP, dvalue0); |
4091 | 4091 |
4092 // Splat across all lanes. | 4092 // Splat across all lanes. |
4093 __ vdup(kWord, result, DTMP, 0); | 4093 __ vdup(kWord, result, DTMP, 0); |
4094 } | 4094 } |
4095 | 4095 |
4096 | 4096 |
4097 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const { | 4097 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(bool opt) const { |
4098 const intptr_t kNumInputs = 2; | 4098 const intptr_t kNumInputs = 2; |
4099 const intptr_t kNumTemps = 0; | 4099 const intptr_t kNumTemps = 0; |
4100 LocationSummary* summary = | 4100 LocationSummary* summary = |
4101 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4101 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4102 summary->set_in(0, Location::RequiresFpuRegister()); | 4102 summary->set_in(0, Location::RequiresFpuRegister()); |
4103 summary->set_in(1, Location::RequiresFpuRegister()); | 4103 summary->set_in(1, Location::RequiresFpuRegister()); |
4104 summary->set_out(0, Location::RequiresFpuRegister()); | 4104 summary->set_out(0, Location::RequiresFpuRegister()); |
4105 return summary; | 4105 return summary; |
4106 } | 4106 } |
4107 | 4107 |
4108 | 4108 |
4109 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4109 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4110 QRegister left = locs()->in(0).fpu_reg(); | 4110 const QRegister left = locs()->in(0).fpu_reg(); |
4111 QRegister right = locs()->in(1).fpu_reg(); | 4111 const QRegister right = locs()->in(1).fpu_reg(); |
4112 QRegister result = locs()->out(0).fpu_reg(); | 4112 const QRegister result = locs()->out(0).fpu_reg(); |
4113 | 4113 |
4114 switch (op_kind()) { | 4114 switch (op_kind()) { |
4115 case MethodRecognizer::kFloat32x4Equal: | 4115 case MethodRecognizer::kFloat32x4Equal: |
4116 __ vceqqs(result, left, right); | 4116 __ vceqqs(result, left, right); |
4117 break; | 4117 break; |
4118 case MethodRecognizer::kFloat32x4NotEqual: | 4118 case MethodRecognizer::kFloat32x4NotEqual: |
4119 __ vceqqs(result, left, right); | 4119 __ vceqqs(result, left, right); |
4120 // Invert the result. | 4120 // Invert the result. |
4121 __ vmvnq(result, result); | 4121 __ vmvnq(result, result); |
4122 break; | 4122 break; |
(...skipping 21 matching lines...) Expand all Loading... |
4144 LocationSummary* summary = | 4144 LocationSummary* summary = |
4145 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4145 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4146 summary->set_in(0, Location::RequiresFpuRegister()); | 4146 summary->set_in(0, Location::RequiresFpuRegister()); |
4147 summary->set_in(1, Location::RequiresFpuRegister()); | 4147 summary->set_in(1, Location::RequiresFpuRegister()); |
4148 summary->set_out(0, Location::RequiresFpuRegister()); | 4148 summary->set_out(0, Location::RequiresFpuRegister()); |
4149 return summary; | 4149 return summary; |
4150 } | 4150 } |
4151 | 4151 |
4152 | 4152 |
4153 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4153 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4154 QRegister left = locs()->in(0).fpu_reg(); | 4154 const QRegister left = locs()->in(0).fpu_reg(); |
4155 QRegister right = locs()->in(1).fpu_reg(); | 4155 const QRegister right = locs()->in(1).fpu_reg(); |
4156 QRegister result = locs()->out(0).fpu_reg(); | 4156 const QRegister result = locs()->out(0).fpu_reg(); |
4157 | 4157 |
4158 switch (op_kind()) { | 4158 switch (op_kind()) { |
4159 case MethodRecognizer::kFloat32x4Min: | 4159 case MethodRecognizer::kFloat32x4Min: |
4160 __ vminqs(result, left, right); | 4160 __ vminqs(result, left, right); |
4161 break; | 4161 break; |
4162 case MethodRecognizer::kFloat32x4Max: | 4162 case MethodRecognizer::kFloat32x4Max: |
4163 __ vmaxqs(result, left, right); | 4163 __ vmaxqs(result, left, right); |
4164 break; | 4164 break; |
4165 default: UNREACHABLE(); | 4165 default: UNREACHABLE(); |
4166 } | 4166 } |
4167 } | 4167 } |
4168 | 4168 |
4169 | 4169 |
4170 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const { | 4170 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(bool opt) const { |
4171 const intptr_t kNumInputs = 1; | 4171 const intptr_t kNumInputs = 1; |
4172 const intptr_t kNumTemps = 1; | 4172 const intptr_t kNumTemps = 1; |
4173 LocationSummary* summary = | 4173 LocationSummary* summary = |
4174 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4174 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4175 summary->set_in(0, Location::RequiresFpuRegister()); | 4175 summary->set_in(0, Location::RequiresFpuRegister()); |
4176 summary->set_out(0, Location::RequiresFpuRegister()); | 4176 summary->set_out(0, Location::RequiresFpuRegister()); |
4177 summary->set_temp(0, Location::RequiresFpuRegister()); | 4177 summary->set_temp(0, Location::RequiresFpuRegister()); |
4178 return summary; | 4178 return summary; |
4179 } | 4179 } |
4180 | 4180 |
4181 | 4181 |
4182 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4182 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4183 QRegister left = locs()->in(0).fpu_reg(); | 4183 const QRegister left = locs()->in(0).fpu_reg(); |
4184 QRegister result = locs()->out(0).fpu_reg(); | 4184 const QRegister result = locs()->out(0).fpu_reg(); |
4185 QRegister temp = locs()->temp(0).fpu_reg(); | 4185 const QRegister temp = locs()->temp(0).fpu_reg(); |
4186 | 4186 |
4187 switch (op_kind()) { | 4187 switch (op_kind()) { |
4188 case MethodRecognizer::kFloat32x4Sqrt: | 4188 case MethodRecognizer::kFloat32x4Sqrt: |
4189 __ Vsqrtqs(result, left, temp); | 4189 __ Vsqrtqs(result, left, temp); |
4190 break; | 4190 break; |
4191 case MethodRecognizer::kFloat32x4Reciprocal: | 4191 case MethodRecognizer::kFloat32x4Reciprocal: |
4192 __ Vreciprocalqs(result, left); | 4192 __ Vreciprocalqs(result, left); |
4193 break; | 4193 break; |
4194 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4194 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
4195 __ VreciprocalSqrtqs(result, left); | 4195 __ VreciprocalSqrtqs(result, left); |
4196 break; | 4196 break; |
4197 default: UNREACHABLE(); | 4197 default: UNREACHABLE(); |
4198 } | 4198 } |
4199 } | 4199 } |
4200 | 4200 |
4201 | 4201 |
4202 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const { | 4202 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(bool opt) const { |
4203 const intptr_t kNumInputs = 2; | 4203 const intptr_t kNumInputs = 2; |
4204 const intptr_t kNumTemps = 0; | 4204 const intptr_t kNumTemps = 0; |
4205 LocationSummary* summary = | 4205 LocationSummary* summary = |
4206 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4206 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4207 summary->set_in(0, Location::RequiresFpuRegister()); | 4207 summary->set_in(0, Location::RequiresFpuRegister()); |
4208 summary->set_in(1, Location::RequiresFpuRegister()); | 4208 summary->set_in(1, Location::RequiresFpuRegister()); |
4209 summary->set_out(0, Location::RequiresFpuRegister()); | 4209 summary->set_out(0, Location::RequiresFpuRegister()); |
4210 return summary; | 4210 return summary; |
4211 } | 4211 } |
4212 | 4212 |
4213 | 4213 |
4214 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4214 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4215 QRegister left = locs()->in(0).fpu_reg(); | 4215 const QRegister left = locs()->in(0).fpu_reg(); |
4216 QRegister right = locs()->in(1).fpu_reg(); | 4216 const QRegister right = locs()->in(1).fpu_reg(); |
4217 QRegister result = locs()->out(0).fpu_reg(); | 4217 const QRegister result = locs()->out(0).fpu_reg(); |
4218 | 4218 |
4219 switch (op_kind()) { | 4219 switch (op_kind()) { |
4220 case MethodRecognizer::kFloat32x4Scale: | 4220 case MethodRecognizer::kFloat32x4Scale: |
4221 __ vcvtsd(STMP, EvenDRegisterOf(left)); | 4221 __ vcvtsd(STMP, EvenDRegisterOf(left)); |
4222 __ vdup(kWord, result, DTMP, 0); | 4222 __ vdup(kWord, result, DTMP, 0); |
4223 __ vmulqs(result, result, right); | 4223 __ vmulqs(result, result, right); |
4224 break; | 4224 break; |
4225 default: UNREACHABLE(); | 4225 default: UNREACHABLE(); |
4226 } | 4226 } |
4227 } | 4227 } |
4228 | 4228 |
4229 | 4229 |
4230 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const { | 4230 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(bool opt) const { |
4231 const intptr_t kNumInputs = 1; | 4231 const intptr_t kNumInputs = 1; |
4232 const intptr_t kNumTemps = 0; | 4232 const intptr_t kNumTemps = 0; |
4233 LocationSummary* summary = | 4233 LocationSummary* summary = |
4234 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4234 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4235 summary->set_in(0, Location::RequiresFpuRegister()); | 4235 summary->set_in(0, Location::RequiresFpuRegister()); |
4236 summary->set_out(0, Location::RequiresFpuRegister()); | 4236 summary->set_out(0, Location::RequiresFpuRegister()); |
4237 return summary; | 4237 return summary; |
4238 } | 4238 } |
4239 | 4239 |
4240 | 4240 |
4241 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4241 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4242 QRegister left = locs()->in(0).fpu_reg(); | 4242 const QRegister left = locs()->in(0).fpu_reg(); |
4243 QRegister result = locs()->out(0).fpu_reg(); | 4243 const QRegister result = locs()->out(0).fpu_reg(); |
4244 | 4244 |
4245 switch (op_kind()) { | 4245 switch (op_kind()) { |
4246 case MethodRecognizer::kFloat32x4Negate: | 4246 case MethodRecognizer::kFloat32x4Negate: |
4247 __ vnegqs(result, left); | 4247 __ vnegqs(result, left); |
4248 break; | 4248 break; |
4249 case MethodRecognizer::kFloat32x4Absolute: | 4249 case MethodRecognizer::kFloat32x4Absolute: |
4250 __ vabsqs(result, left); | 4250 __ vabsqs(result, left); |
4251 break; | 4251 break; |
4252 default: UNREACHABLE(); | 4252 default: UNREACHABLE(); |
4253 } | 4253 } |
4254 } | 4254 } |
4255 | 4255 |
4256 | 4256 |
4257 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const { | 4257 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(bool opt) const { |
4258 const intptr_t kNumInputs = 3; | 4258 const intptr_t kNumInputs = 3; |
4259 const intptr_t kNumTemps = 0; | 4259 const intptr_t kNumTemps = 0; |
4260 LocationSummary* summary = | 4260 LocationSummary* summary = |
4261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4261 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4262 summary->set_in(0, Location::RequiresFpuRegister()); | 4262 summary->set_in(0, Location::RequiresFpuRegister()); |
4263 summary->set_in(1, Location::RequiresFpuRegister()); | 4263 summary->set_in(1, Location::RequiresFpuRegister()); |
4264 summary->set_in(2, Location::RequiresFpuRegister()); | 4264 summary->set_in(2, Location::RequiresFpuRegister()); |
4265 summary->set_out(0, Location::RequiresFpuRegister()); | 4265 summary->set_out(0, Location::RequiresFpuRegister()); |
4266 return summary; | 4266 return summary; |
4267 } | 4267 } |
4268 | 4268 |
4269 | 4269 |
4270 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4270 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4271 QRegister left = locs()->in(0).fpu_reg(); | 4271 const QRegister left = locs()->in(0).fpu_reg(); |
4272 QRegister lower = locs()->in(1).fpu_reg(); | 4272 const QRegister lower = locs()->in(1).fpu_reg(); |
4273 QRegister upper = locs()->in(2).fpu_reg(); | 4273 const QRegister upper = locs()->in(2).fpu_reg(); |
4274 QRegister result = locs()->out(0).fpu_reg(); | 4274 const QRegister result = locs()->out(0).fpu_reg(); |
4275 __ vminqs(result, left, upper); | 4275 __ vminqs(result, left, upper); |
4276 __ vmaxqs(result, result, lower); | 4276 __ vmaxqs(result, result, lower); |
4277 } | 4277 } |
4278 | 4278 |
4279 | 4279 |
4280 LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const { | 4280 LocationSummary* Float32x4WithInstr::MakeLocationSummary(bool opt) const { |
4281 const intptr_t kNumInputs = 2; | 4281 const intptr_t kNumInputs = 2; |
4282 const intptr_t kNumTemps = 0; | 4282 const intptr_t kNumTemps = 0; |
4283 LocationSummary* summary = | 4283 LocationSummary* summary = |
4284 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4284 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4285 summary->set_in(0, Location::RequiresFpuRegister()); | 4285 summary->set_in(0, Location::RequiresFpuRegister()); |
4286 summary->set_in(1, Location::RequiresFpuRegister()); | 4286 summary->set_in(1, Location::RequiresFpuRegister()); |
4287 // Low (< 7) Q registers are needed for the vmovs instruction. | 4287 // Low (< 7) Q registers are needed for the vmovs instruction. |
4288 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4288 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4289 return summary; | 4289 return summary; |
4290 } | 4290 } |
4291 | 4291 |
4292 | 4292 |
4293 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4293 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4294 QRegister replacement = locs()->in(0).fpu_reg(); | 4294 const QRegister replacement = locs()->in(0).fpu_reg(); |
4295 QRegister value = locs()->in(1).fpu_reg(); | 4295 const QRegister value = locs()->in(1).fpu_reg(); |
4296 QRegister result = locs()->out(0).fpu_reg(); | 4296 const QRegister result = locs()->out(0).fpu_reg(); |
4297 | 4297 |
4298 DRegister dresult0 = EvenDRegisterOf(result); | 4298 const DRegister dresult0 = EvenDRegisterOf(result); |
4299 DRegister dresult1 = OddDRegisterOf(result); | 4299 const DRegister dresult1 = OddDRegisterOf(result); |
4300 SRegister sresult0 = EvenSRegisterOf(dresult0); | 4300 const SRegister sresult0 = EvenSRegisterOf(dresult0); |
4301 SRegister sresult1 = OddSRegisterOf(dresult0); | 4301 const SRegister sresult1 = OddSRegisterOf(dresult0); |
4302 SRegister sresult2 = EvenSRegisterOf(dresult1); | 4302 const SRegister sresult2 = EvenSRegisterOf(dresult1); |
4303 SRegister sresult3 = OddSRegisterOf(dresult1); | 4303 const SRegister sresult3 = OddSRegisterOf(dresult1); |
4304 | 4304 |
4305 __ vcvtsd(STMP, EvenDRegisterOf(replacement)); | 4305 __ vcvtsd(STMP, EvenDRegisterOf(replacement)); |
4306 if (result != value) { | 4306 if (result != value) { |
4307 __ vmovq(result, value); | 4307 __ vmovq(result, value); |
4308 } | 4308 } |
4309 | 4309 |
4310 switch (op_kind()) { | 4310 switch (op_kind()) { |
4311 case MethodRecognizer::kFloat32x4WithX: | 4311 case MethodRecognizer::kFloat32x4WithX: |
4312 __ vmovs(sresult0, STMP); | 4312 __ vmovs(sresult0, STMP); |
4313 break; | 4313 break; |
(...skipping 16 matching lines...) Expand all Loading... |
4330 const intptr_t kNumTemps = 0; | 4330 const intptr_t kNumTemps = 0; |
4331 LocationSummary* summary = | 4331 LocationSummary* summary = |
4332 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4332 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4333 summary->set_in(0, Location::RequiresFpuRegister()); | 4333 summary->set_in(0, Location::RequiresFpuRegister()); |
4334 summary->set_out(0, Location::RequiresFpuRegister()); | 4334 summary->set_out(0, Location::RequiresFpuRegister()); |
4335 return summary; | 4335 return summary; |
4336 } | 4336 } |
4337 | 4337 |
4338 | 4338 |
4339 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4339 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4340 QRegister value = locs()->in(0).fpu_reg(); | 4340 const QRegister value = locs()->in(0).fpu_reg(); |
4341 QRegister result = locs()->out(0).fpu_reg(); | 4341 const QRegister result = locs()->out(0).fpu_reg(); |
4342 | 4342 |
4343 if (value != result) { | 4343 if (value != result) { |
4344 __ vmovq(result, value); | 4344 __ vmovq(result, value); |
4345 } | 4345 } |
4346 } | 4346 } |
4347 | 4347 |
4348 | 4348 |
4349 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(bool opt) const { | 4349 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(bool opt) const { |
4350 const intptr_t kNumInputs = 1; | 4350 const intptr_t kNumInputs = 1; |
4351 const intptr_t kNumTemps = 0; | 4351 const intptr_t kNumTemps = 0; |
4352 LocationSummary* summary = | 4352 LocationSummary* summary = |
4353 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4353 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4354 summary->set_in(0, Location::RequiresFpuRegister()); | 4354 summary->set_in(0, Location::RequiresFpuRegister()); |
4355 summary->set_out(0, Location::RequiresFpuRegister()); | 4355 summary->set_out(0, Location::RequiresFpuRegister()); |
4356 return summary; | 4356 return summary; |
4357 } | 4357 } |
4358 | 4358 |
4359 | 4359 |
4360 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4360 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4361 QRegister value = locs()->in(0).fpu_reg(); | 4361 const QRegister value = locs()->in(0).fpu_reg(); |
4362 | 4362 |
4363 DRegister dvalue0 = EvenDRegisterOf(value); | 4363 const DRegister dvalue0 = EvenDRegisterOf(value); |
4364 DRegister dvalue1 = OddDRegisterOf(value); | 4364 const DRegister dvalue1 = OddDRegisterOf(value); |
4365 | 4365 |
4366 QRegister result = locs()->out(0).fpu_reg(); | 4366 const QRegister result = locs()->out(0).fpu_reg(); |
4367 | 4367 |
4368 DRegister dresult0 = EvenDRegisterOf(result); | 4368 const DRegister dresult0 = EvenDRegisterOf(result); |
4369 | 4369 |
4370 switch (op_kind()) { | 4370 switch (op_kind()) { |
4371 case MethodRecognizer::kFloat64x2GetX: | 4371 case MethodRecognizer::kFloat64x2GetX: |
4372 __ vmovd(dresult0, dvalue0); | 4372 __ vmovd(dresult0, dvalue0); |
4373 break; | 4373 break; |
4374 case MethodRecognizer::kFloat64x2GetY: | 4374 case MethodRecognizer::kFloat64x2GetY: |
4375 __ vmovd(dresult0, dvalue1); | 4375 __ vmovd(dresult0, dvalue1); |
4376 break; | 4376 break; |
4377 default: UNREACHABLE(); | 4377 default: UNREACHABLE(); |
4378 } | 4378 } |
4379 } | 4379 } |
4380 | 4380 |
4381 | 4381 |
4382 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(bool opt) const { | 4382 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(bool opt) const { |
4383 const intptr_t kNumInputs = 0; | 4383 const intptr_t kNumInputs = 0; |
4384 const intptr_t kNumTemps = 0; | 4384 const intptr_t kNumTemps = 0; |
4385 LocationSummary* summary = | 4385 LocationSummary* summary = |
4386 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4386 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4387 summary->set_out(0, Location::RequiresFpuRegister()); | 4387 summary->set_out(0, Location::RequiresFpuRegister()); |
4388 return summary; | 4388 return summary; |
4389 } | 4389 } |
4390 | 4390 |
4391 | 4391 |
4392 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4392 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4393 QRegister q = locs()->out(0).fpu_reg(); | 4393 const QRegister q = locs()->out(0).fpu_reg(); |
4394 __ veorq(q, q, q); | 4394 __ veorq(q, q, q); |
4395 } | 4395 } |
4396 | 4396 |
4397 | 4397 |
4398 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(bool opt) const { | 4398 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(bool opt) const { |
4399 const intptr_t kNumInputs = 1; | 4399 const intptr_t kNumInputs = 1; |
4400 const intptr_t kNumTemps = 0; | 4400 const intptr_t kNumTemps = 0; |
4401 LocationSummary* summary = | 4401 LocationSummary* summary = |
4402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4402 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4403 summary->set_in(0, Location::RequiresFpuRegister()); | 4403 summary->set_in(0, Location::RequiresFpuRegister()); |
4404 summary->set_out(0, Location::RequiresFpuRegister()); | 4404 summary->set_out(0, Location::RequiresFpuRegister()); |
4405 return summary; | 4405 return summary; |
4406 } | 4406 } |
4407 | 4407 |
4408 | 4408 |
4409 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4409 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4410 QRegister value = locs()->in(0).fpu_reg(); | 4410 const QRegister value = locs()->in(0).fpu_reg(); |
4411 | 4411 |
4412 DRegister dvalue = EvenDRegisterOf(value); | 4412 const DRegister dvalue = EvenDRegisterOf(value); |
4413 | 4413 |
4414 QRegister result = locs()->out(0).fpu_reg(); | 4414 const QRegister result = locs()->out(0).fpu_reg(); |
4415 | 4415 |
4416 DRegister dresult0 = EvenDRegisterOf(result); | 4416 const DRegister dresult0 = EvenDRegisterOf(result); |
4417 DRegister dresult1 = OddDRegisterOf(result); | 4417 const DRegister dresult1 = OddDRegisterOf(result); |
4418 | 4418 |
4419 // Splat across all lanes. | 4419 // Splat across all lanes. |
4420 __ vmovd(dresult0, dvalue); | 4420 __ vmovd(dresult0, dvalue); |
4421 __ vmovd(dresult1, dvalue); | 4421 __ vmovd(dresult1, dvalue); |
4422 } | 4422 } |
4423 | 4423 |
4424 | 4424 |
4425 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4425 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
4426 bool opt) const { | 4426 bool opt) const { |
4427 const intptr_t kNumInputs = 2; | 4427 const intptr_t kNumInputs = 2; |
4428 const intptr_t kNumTemps = 0; | 4428 const intptr_t kNumTemps = 0; |
4429 LocationSummary* summary = | 4429 LocationSummary* summary = |
4430 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4430 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4431 summary->set_in(0, Location::RequiresFpuRegister()); | 4431 summary->set_in(0, Location::RequiresFpuRegister()); |
4432 summary->set_in(1, Location::RequiresFpuRegister()); | 4432 summary->set_in(1, Location::RequiresFpuRegister()); |
4433 summary->set_out(0, Location::RequiresFpuRegister()); | 4433 summary->set_out(0, Location::RequiresFpuRegister()); |
4434 return summary; | 4434 return summary; |
4435 } | 4435 } |
4436 | 4436 |
4437 | 4437 |
4438 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4438 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4439 QRegister q0 = locs()->in(0).fpu_reg(); | 4439 const QRegister q0 = locs()->in(0).fpu_reg(); |
4440 QRegister q1 = locs()->in(1).fpu_reg(); | 4440 const QRegister q1 = locs()->in(1).fpu_reg(); |
4441 QRegister r = locs()->out(0).fpu_reg(); | 4441 const QRegister r = locs()->out(0).fpu_reg(); |
4442 | 4442 |
4443 DRegister d0 = EvenDRegisterOf(q0); | 4443 const DRegister d0 = EvenDRegisterOf(q0); |
4444 DRegister d1 = EvenDRegisterOf(q1); | 4444 const DRegister d1 = EvenDRegisterOf(q1); |
4445 | 4445 |
4446 DRegister dr0 = EvenDRegisterOf(r); | 4446 const DRegister dr0 = EvenDRegisterOf(r); |
4447 DRegister dr1 = OddDRegisterOf(r); | 4447 const DRegister dr1 = OddDRegisterOf(r); |
4448 | 4448 |
4449 __ vmovd(dr0, d0); | 4449 __ vmovd(dr0, d0); |
4450 __ vmovd(dr1, d1); | 4450 __ vmovd(dr1, d1); |
4451 } | 4451 } |
4452 | 4452 |
4453 | 4453 |
4454 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4454 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
4455 bool opt) const { | 4455 bool opt) const { |
4456 const intptr_t kNumInputs = 1; | 4456 const intptr_t kNumInputs = 1; |
4457 const intptr_t kNumTemps = 0; | 4457 const intptr_t kNumTemps = 0; |
4458 LocationSummary* summary = | 4458 LocationSummary* summary = |
4459 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4459 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4460 summary->set_in(0, Location::RequiresFpuRegister()); | 4460 summary->set_in(0, Location::RequiresFpuRegister()); |
4461 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 4461 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
4462 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4462 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4463 return summary; | 4463 return summary; |
4464 } | 4464 } |
4465 | 4465 |
4466 | 4466 |
4467 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4467 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4468 QRegister q = locs()->in(0).fpu_reg(); | 4468 const QRegister q = locs()->in(0).fpu_reg(); |
4469 QRegister r = locs()->out(0).fpu_reg(); | 4469 const QRegister r = locs()->out(0).fpu_reg(); |
4470 | 4470 |
4471 DRegister dq0 = EvenDRegisterOf(q); | 4471 const DRegister dq0 = EvenDRegisterOf(q); |
4472 DRegister dq1 = OddDRegisterOf(q); | 4472 const DRegister dq1 = OddDRegisterOf(q); |
4473 | 4473 |
4474 DRegister dr0 = EvenDRegisterOf(r); | 4474 const DRegister dr0 = EvenDRegisterOf(r); |
4475 | 4475 |
4476 // Zero register. | 4476 // Zero register. |
4477 __ veorq(r, r, r); | 4477 __ veorq(r, r, r); |
4478 // Set X lane. | 4478 // Set X lane. |
4479 __ vcvtsd(EvenSRegisterOf(dr0), dq0); | 4479 __ vcvtsd(EvenSRegisterOf(dr0), dq0); |
4480 // Set Y lane. | 4480 // Set Y lane. |
4481 __ vcvtsd(OddSRegisterOf(dr0), dq1); | 4481 __ vcvtsd(OddSRegisterOf(dr0), dq1); |
4482 } | 4482 } |
4483 | 4483 |
4484 | 4484 |
4485 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4485 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
4486 bool opt) const { | 4486 bool opt) const { |
4487 const intptr_t kNumInputs = 1; | 4487 const intptr_t kNumInputs = 1; |
4488 const intptr_t kNumTemps = 0; | 4488 const intptr_t kNumTemps = 0; |
4489 LocationSummary* summary = | 4489 LocationSummary* summary = |
4490 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4490 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4491 summary->set_in(0, Location::RequiresFpuRegister()); | 4491 summary->set_in(0, Location::RequiresFpuRegister()); |
4492 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 4492 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
4493 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4493 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4494 return summary; | 4494 return summary; |
4495 } | 4495 } |
4496 | 4496 |
4497 | 4497 |
4498 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4498 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4499 QRegister q = locs()->in(0).fpu_reg(); | 4499 const QRegister q = locs()->in(0).fpu_reg(); |
4500 QRegister r = locs()->out(0).fpu_reg(); | 4500 const QRegister r = locs()->out(0).fpu_reg(); |
4501 | 4501 |
4502 DRegister dq0 = EvenDRegisterOf(q); | 4502 const DRegister dq0 = EvenDRegisterOf(q); |
4503 | 4503 |
4504 DRegister dr0 = EvenDRegisterOf(r); | 4504 const DRegister dr0 = EvenDRegisterOf(r); |
4505 DRegister dr1 = OddDRegisterOf(r); | 4505 const DRegister dr1 = OddDRegisterOf(r); |
4506 | 4506 |
4507 // Set X. | 4507 // Set X. |
4508 __ vcvtds(dr0, EvenSRegisterOf(dq0)); | 4508 __ vcvtds(dr0, EvenSRegisterOf(dq0)); |
4509 // Set Y. | 4509 // Set Y. |
4510 __ vcvtds(dr1, OddSRegisterOf(dq0)); | 4510 __ vcvtds(dr1, OddSRegisterOf(dq0)); |
4511 } | 4511 } |
4512 | 4512 |
4513 | 4513 |
4514 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(bool opt) const { | 4514 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(bool opt) const { |
4515 const intptr_t kNumInputs = 1; | 4515 const intptr_t kNumInputs = 1; |
4516 const intptr_t kNumTemps = 0; | 4516 const intptr_t kNumTemps = 0; |
4517 LocationSummary* summary = | 4517 LocationSummary* summary = |
4518 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4518 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4519 | 4519 |
4520 if (representation() == kTagged) { | 4520 if (representation() == kTagged) { |
4521 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4521 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
4522 // Grabbing the S components means we need a low (< 7) Q. | 4522 // Grabbing the S components means we need a low (< 7) Q. |
4523 summary->set_in(0, Location::FpuRegisterLocation(Q6)); | 4523 summary->set_in(0, Location::FpuRegisterLocation(Q6)); |
4524 summary->set_out(0, Location::RequiresRegister()); | 4524 summary->set_out(0, Location::RequiresRegister()); |
4525 summary->AddTemp(Location::RequiresRegister()); | 4525 summary->AddTemp(Location::RequiresRegister()); |
4526 } else { | 4526 } else { |
4527 summary->set_in(0, Location::RequiresFpuRegister()); | 4527 summary->set_in(0, Location::RequiresFpuRegister()); |
4528 summary->set_out(0, Location::RequiresFpuRegister()); | 4528 summary->set_out(0, Location::RequiresFpuRegister()); |
4529 } | 4529 } |
4530 return summary; | 4530 return summary; |
4531 } | 4531 } |
4532 | 4532 |
4533 | 4533 |
4534 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4534 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4535 QRegister q = locs()->in(0).fpu_reg(); | 4535 const QRegister q = locs()->in(0).fpu_reg(); |
4536 | 4536 |
4537 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { | 4537 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { |
4538 DRegister dvalue0 = EvenDRegisterOf(q); | 4538 const DRegister dvalue0 = EvenDRegisterOf(q); |
4539 DRegister dvalue1 = OddDRegisterOf(q); | 4539 const DRegister dvalue1 = OddDRegisterOf(q); |
4540 | 4540 |
4541 Register out = locs()->out(0).reg(); | 4541 const Register out = locs()->out(0).reg(); |
4542 Register temp = locs()->temp(0).reg(); | 4542 const Register temp = locs()->temp(0).reg(); |
4543 | 4543 |
4544 // Upper 32-bits of X lane. | 4544 // Upper 32-bits of X lane. |
4545 __ vmovrs(out, OddSRegisterOf(dvalue0)); | 4545 __ vmovrs(out, OddSRegisterOf(dvalue0)); |
4546 __ Lsr(out, out, 31); | 4546 __ Lsr(out, out, 31); |
4547 // Upper 32-bits of Y lane. | 4547 // Upper 32-bits of Y lane. |
4548 __ vmovrs(temp, OddSRegisterOf(dvalue1)); | 4548 __ vmovrs(temp, OddSRegisterOf(dvalue1)); |
4549 __ Lsr(temp, temp, 31); | 4549 __ Lsr(temp, temp, 31); |
4550 __ orr(out, out, ShifterOperand(temp, LSL, 1)); | 4550 __ orr(out, out, ShifterOperand(temp, LSL, 1)); |
4551 // Tag. | 4551 // Tag. |
4552 __ SmiTag(out); | 4552 __ SmiTag(out); |
4553 return; | 4553 return; |
4554 } | 4554 } |
4555 ASSERT(representation() == kUnboxedFloat64x2); | 4555 ASSERT(representation() == kUnboxedFloat64x2); |
4556 QRegister r = locs()->out(0).fpu_reg(); | 4556 const QRegister r = locs()->out(0).fpu_reg(); |
4557 | 4557 |
4558 DRegister dvalue0 = EvenDRegisterOf(q); | 4558 const DRegister dvalue0 = EvenDRegisterOf(q); |
4559 DRegister dvalue1 = OddDRegisterOf(q); | 4559 const DRegister dvalue1 = OddDRegisterOf(q); |
4560 DRegister dresult0 = EvenDRegisterOf(r); | 4560 const DRegister dresult0 = EvenDRegisterOf(r); |
4561 DRegister dresult1 = OddDRegisterOf(r); | 4561 const DRegister dresult1 = OddDRegisterOf(r); |
4562 | 4562 |
4563 switch (op_kind()) { | 4563 switch (op_kind()) { |
4564 case MethodRecognizer::kFloat64x2Negate: | 4564 case MethodRecognizer::kFloat64x2Negate: |
4565 __ vnegd(dresult0, dvalue0); | 4565 __ vnegd(dresult0, dvalue0); |
4566 __ vnegd(dresult1, dvalue1); | 4566 __ vnegd(dresult1, dvalue1); |
4567 break; | 4567 break; |
4568 case MethodRecognizer::kFloat64x2Abs: | 4568 case MethodRecognizer::kFloat64x2Abs: |
4569 __ vabsd(dresult0, dvalue0); | 4569 __ vabsd(dresult0, dvalue0); |
4570 __ vabsd(dresult1, dvalue1); | 4570 __ vabsd(dresult1, dvalue1); |
4571 break; | 4571 break; |
(...skipping 12 matching lines...) Expand all Loading... |
4584 LocationSummary* summary = | 4584 LocationSummary* summary = |
4585 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4585 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4586 summary->set_in(0, Location::RequiresFpuRegister()); | 4586 summary->set_in(0, Location::RequiresFpuRegister()); |
4587 summary->set_in(1, Location::RequiresFpuRegister()); | 4587 summary->set_in(1, Location::RequiresFpuRegister()); |
4588 summary->set_out(0, Location::SameAsFirstInput()); | 4588 summary->set_out(0, Location::SameAsFirstInput()); |
4589 return summary; | 4589 return summary; |
4590 } | 4590 } |
4591 | 4591 |
4592 | 4592 |
4593 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4593 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4594 QRegister left = locs()->in(0).fpu_reg(); | 4594 const QRegister left = locs()->in(0).fpu_reg(); |
4595 DRegister left0 = EvenDRegisterOf(left); | 4595 const DRegister left0 = EvenDRegisterOf(left); |
4596 DRegister left1 = OddDRegisterOf(left); | 4596 const DRegister left1 = OddDRegisterOf(left); |
4597 QRegister right = locs()->in(1).fpu_reg(); | 4597 const QRegister right = locs()->in(1).fpu_reg(); |
4598 DRegister right0 = EvenDRegisterOf(right); | 4598 const DRegister right0 = EvenDRegisterOf(right); |
4599 DRegister right1 = OddDRegisterOf(right); | 4599 const DRegister right1 = OddDRegisterOf(right); |
4600 QRegister out = locs()->out(0).fpu_reg(); | 4600 const QRegister out = locs()->out(0).fpu_reg(); |
4601 ASSERT(left == out); | 4601 ASSERT(left == out); |
4602 | 4602 |
4603 switch (op_kind()) { | 4603 switch (op_kind()) { |
4604 case MethodRecognizer::kFloat64x2Scale: | 4604 case MethodRecognizer::kFloat64x2Scale: |
4605 __ vmuld(left0, left0, right0); | 4605 __ vmuld(left0, left0, right0); |
4606 __ vmuld(left1, left1, right0); | 4606 __ vmuld(left1, left1, right0); |
4607 break; | 4607 break; |
4608 case MethodRecognizer::kFloat64x2WithX: | 4608 case MethodRecognizer::kFloat64x2WithX: |
4609 __ vmovd(left0, right0); | 4609 __ vmovd(left0, right0); |
4610 break; | 4610 break; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4661 summary->set_in(2, Location::RequiresRegister()); | 4661 summary->set_in(2, Location::RequiresRegister()); |
4662 summary->set_in(3, Location::RequiresRegister()); | 4662 summary->set_in(3, Location::RequiresRegister()); |
4663 summary->set_temp(0, Location::RequiresRegister()); | 4663 summary->set_temp(0, Location::RequiresRegister()); |
4664 // Low (< 7) Q register needed for the vmovsr instruction. | 4664 // Low (< 7) Q register needed for the vmovsr instruction. |
4665 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4665 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4666 return summary; | 4666 return summary; |
4667 } | 4667 } |
4668 | 4668 |
4669 | 4669 |
4670 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4670 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4671 Register v0 = locs()->in(0).reg(); | 4671 const Register v0 = locs()->in(0).reg(); |
4672 Register v1 = locs()->in(1).reg(); | 4672 const Register v1 = locs()->in(1).reg(); |
4673 Register v2 = locs()->in(2).reg(); | 4673 const Register v2 = locs()->in(2).reg(); |
4674 Register v3 = locs()->in(3).reg(); | 4674 const Register v3 = locs()->in(3).reg(); |
4675 Register temp = locs()->temp(0).reg(); | 4675 const Register temp = locs()->temp(0).reg(); |
4676 QRegister result = locs()->out(0).fpu_reg(); | 4676 const QRegister result = locs()->out(0).fpu_reg(); |
4677 DRegister dresult0 = EvenDRegisterOf(result); | 4677 const DRegister dresult0 = EvenDRegisterOf(result); |
4678 DRegister dresult1 = OddDRegisterOf(result); | 4678 const DRegister dresult1 = OddDRegisterOf(result); |
4679 SRegister sresult0 = EvenSRegisterOf(dresult0); | 4679 const SRegister sresult0 = EvenSRegisterOf(dresult0); |
4680 SRegister sresult1 = OddSRegisterOf(dresult0); | 4680 const SRegister sresult1 = OddSRegisterOf(dresult0); |
4681 SRegister sresult2 = EvenSRegisterOf(dresult1); | 4681 const SRegister sresult2 = EvenSRegisterOf(dresult1); |
4682 SRegister sresult3 = OddSRegisterOf(dresult1); | 4682 const SRegister sresult3 = OddSRegisterOf(dresult1); |
4683 | 4683 |
4684 __ veorq(result, result, result); | 4684 __ veorq(result, result, result); |
4685 __ LoadImmediate(temp, 0xffffffff); | 4685 __ LoadImmediate(temp, 0xffffffff); |
4686 | 4686 |
4687 __ CompareObject(v0, Bool::True()); | 4687 __ CompareObject(v0, Bool::True()); |
4688 __ vmovsr(sresult0, temp, EQ); | 4688 __ vmovsr(sresult0, temp, EQ); |
4689 | 4689 |
4690 __ CompareObject(v1, Bool::True()); | 4690 __ CompareObject(v1, Bool::True()); |
4691 __ vmovsr(sresult1, temp, EQ); | 4691 __ vmovsr(sresult1, temp, EQ); |
4692 | 4692 |
(...skipping 11 matching lines...) Expand all Loading... |
4704 LocationSummary* summary = | 4704 LocationSummary* summary = |
4705 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4705 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4706 // Low (< 7) Q registers are needed for the vmovrs instruction. | 4706 // Low (< 7) Q registers are needed for the vmovrs instruction. |
4707 summary->set_in(0, Location::FpuRegisterLocation(Q6)); | 4707 summary->set_in(0, Location::FpuRegisterLocation(Q6)); |
4708 summary->set_out(0, Location::RequiresRegister()); | 4708 summary->set_out(0, Location::RequiresRegister()); |
4709 return summary; | 4709 return summary; |
4710 } | 4710 } |
4711 | 4711 |
4712 | 4712 |
4713 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4713 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4714 QRegister value = locs()->in(0).fpu_reg(); | 4714 const QRegister value = locs()->in(0).fpu_reg(); |
4715 Register result = locs()->out(0).reg(); | 4715 const Register result = locs()->out(0).reg(); |
4716 | 4716 |
4717 DRegister dvalue0 = EvenDRegisterOf(value); | 4717 const DRegister dvalue0 = EvenDRegisterOf(value); |
4718 DRegister dvalue1 = OddDRegisterOf(value); | 4718 const DRegister dvalue1 = OddDRegisterOf(value); |
4719 SRegister svalue0 = EvenSRegisterOf(dvalue0); | 4719 const SRegister svalue0 = EvenSRegisterOf(dvalue0); |
4720 SRegister svalue1 = OddSRegisterOf(dvalue0); | 4720 const SRegister svalue1 = OddSRegisterOf(dvalue0); |
4721 SRegister svalue2 = EvenSRegisterOf(dvalue1); | 4721 const SRegister svalue2 = EvenSRegisterOf(dvalue1); |
4722 SRegister svalue3 = OddSRegisterOf(dvalue1); | 4722 const SRegister svalue3 = OddSRegisterOf(dvalue1); |
4723 | 4723 |
4724 switch (op_kind()) { | 4724 switch (op_kind()) { |
4725 case MethodRecognizer::kInt32x4GetFlagX: | 4725 case MethodRecognizer::kInt32x4GetFlagX: |
4726 __ vmovrs(result, svalue0); | 4726 __ vmovrs(result, svalue0); |
4727 break; | 4727 break; |
4728 case MethodRecognizer::kInt32x4GetFlagY: | 4728 case MethodRecognizer::kInt32x4GetFlagY: |
4729 __ vmovrs(result, svalue1); | 4729 __ vmovrs(result, svalue1); |
4730 break; | 4730 break; |
4731 case MethodRecognizer::kInt32x4GetFlagZ: | 4731 case MethodRecognizer::kInt32x4GetFlagZ: |
4732 __ vmovrs(result, svalue2); | 4732 __ vmovrs(result, svalue2); |
(...skipping 18 matching lines...) Expand all Loading... |
4751 summary->set_in(0, Location::RequiresFpuRegister()); | 4751 summary->set_in(0, Location::RequiresFpuRegister()); |
4752 summary->set_in(1, Location::RequiresFpuRegister()); | 4752 summary->set_in(1, Location::RequiresFpuRegister()); |
4753 summary->set_in(2, Location::RequiresFpuRegister()); | 4753 summary->set_in(2, Location::RequiresFpuRegister()); |
4754 summary->set_temp(0, Location::RequiresFpuRegister()); | 4754 summary->set_temp(0, Location::RequiresFpuRegister()); |
4755 summary->set_out(0, Location::RequiresFpuRegister()); | 4755 summary->set_out(0, Location::RequiresFpuRegister()); |
4756 return summary; | 4756 return summary; |
4757 } | 4757 } |
4758 | 4758 |
4759 | 4759 |
4760 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4760 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4761 QRegister mask = locs()->in(0).fpu_reg(); | 4761 const QRegister mask = locs()->in(0).fpu_reg(); |
4762 QRegister trueValue = locs()->in(1).fpu_reg(); | 4762 const QRegister trueValue = locs()->in(1).fpu_reg(); |
4763 QRegister falseValue = locs()->in(2).fpu_reg(); | 4763 const QRegister falseValue = locs()->in(2).fpu_reg(); |
4764 QRegister out = locs()->out(0).fpu_reg(); | 4764 const QRegister out = locs()->out(0).fpu_reg(); |
4765 QRegister temp = locs()->temp(0).fpu_reg(); | 4765 const QRegister temp = locs()->temp(0).fpu_reg(); |
4766 | 4766 |
4767 // Copy mask. | 4767 // Copy mask. |
4768 __ vmovq(temp, mask); | 4768 __ vmovq(temp, mask); |
4769 // Invert it. | 4769 // Invert it. |
4770 __ vmvnq(temp, temp); | 4770 __ vmvnq(temp, temp); |
4771 // mask = mask & trueValue. | 4771 // mask = mask & trueValue. |
4772 __ vandq(mask, mask, trueValue); | 4772 __ vandq(mask, mask, trueValue); |
4773 // temp = temp & falseValue. | 4773 // temp = temp & falseValue. |
4774 __ vandq(temp, temp, falseValue); | 4774 __ vandq(temp, temp, falseValue); |
4775 // out = mask | temp. | 4775 // out = mask | temp. |
4776 __ vorrq(out, mask, temp); | 4776 __ vorrq(out, mask, temp); |
4777 } | 4777 } |
4778 | 4778 |
4779 | 4779 |
4780 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const { | 4780 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(bool opt) const { |
4781 const intptr_t kNumInputs = 2; | 4781 const intptr_t kNumInputs = 2; |
4782 const intptr_t kNumTemps = 0; | 4782 const intptr_t kNumTemps = 0; |
4783 LocationSummary* summary = | 4783 LocationSummary* summary = |
4784 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4784 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4785 summary->set_in(0, Location::RequiresFpuRegister()); | 4785 summary->set_in(0, Location::RequiresFpuRegister()); |
4786 summary->set_in(1, Location::RequiresRegister()); | 4786 summary->set_in(1, Location::RequiresRegister()); |
4787 // Low (< 7) Q register needed for the vmovsr instruction. | 4787 // Low (< 7) Q register needed for the vmovsr instruction. |
4788 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4788 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
4789 return summary; | 4789 return summary; |
4790 } | 4790 } |
4791 | 4791 |
4792 | 4792 |
4793 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4793 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4794 QRegister mask = locs()->in(0).fpu_reg(); | 4794 const QRegister mask = locs()->in(0).fpu_reg(); |
4795 Register flag = locs()->in(1).reg(); | 4795 const Register flag = locs()->in(1).reg(); |
4796 QRegister result = locs()->out(0).fpu_reg(); | 4796 const QRegister result = locs()->out(0).fpu_reg(); |
4797 | 4797 |
4798 DRegister dresult0 = EvenDRegisterOf(result); | 4798 const DRegister dresult0 = EvenDRegisterOf(result); |
4799 DRegister dresult1 = OddDRegisterOf(result); | 4799 const DRegister dresult1 = OddDRegisterOf(result); |
4800 SRegister sresult0 = EvenSRegisterOf(dresult0); | 4800 const SRegister sresult0 = EvenSRegisterOf(dresult0); |
4801 SRegister sresult1 = OddSRegisterOf(dresult0); | 4801 const SRegister sresult1 = OddSRegisterOf(dresult0); |
4802 SRegister sresult2 = EvenSRegisterOf(dresult1); | 4802 const SRegister sresult2 = EvenSRegisterOf(dresult1); |
4803 SRegister sresult3 = OddSRegisterOf(dresult1); | 4803 const SRegister sresult3 = OddSRegisterOf(dresult1); |
4804 | 4804 |
4805 if (result != mask) { | 4805 if (result != mask) { |
4806 __ vmovq(result, mask); | 4806 __ vmovq(result, mask); |
4807 } | 4807 } |
4808 | 4808 |
4809 __ CompareObject(flag, Bool::True()); | 4809 __ CompareObject(flag, Bool::True()); |
4810 __ LoadImmediate(TMP, 0xffffffff, EQ); | 4810 __ LoadImmediate(TMP, 0xffffffff, EQ); |
4811 __ LoadImmediate(TMP, 0, NE); | 4811 __ LoadImmediate(TMP, 0, NE); |
4812 switch (op_kind()) { | 4812 switch (op_kind()) { |
4813 case MethodRecognizer::kInt32x4WithFlagX: | 4813 case MethodRecognizer::kInt32x4WithFlagX: |
(...skipping 18 matching lines...) Expand all Loading... |
4832 const intptr_t kNumTemps = 0; | 4832 const intptr_t kNumTemps = 0; |
4833 LocationSummary* summary = | 4833 LocationSummary* summary = |
4834 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4834 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4835 summary->set_in(0, Location::RequiresFpuRegister()); | 4835 summary->set_in(0, Location::RequiresFpuRegister()); |
4836 summary->set_out(0, Location::RequiresFpuRegister()); | 4836 summary->set_out(0, Location::RequiresFpuRegister()); |
4837 return summary; | 4837 return summary; |
4838 } | 4838 } |
4839 | 4839 |
4840 | 4840 |
4841 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4841 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4842 QRegister value = locs()->in(0).fpu_reg(); | 4842 const QRegister value = locs()->in(0).fpu_reg(); |
4843 QRegister result = locs()->out(0).fpu_reg(); | 4843 const QRegister result = locs()->out(0).fpu_reg(); |
4844 | 4844 |
4845 if (value != result) { | 4845 if (value != result) { |
4846 __ vmovq(result, value); | 4846 __ vmovq(result, value); |
4847 } | 4847 } |
4848 } | 4848 } |
4849 | 4849 |
4850 | 4850 |
4851 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const { | 4851 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(bool opt) const { |
4852 const intptr_t kNumInputs = 2; | 4852 const intptr_t kNumInputs = 2; |
4853 const intptr_t kNumTemps = 0; | 4853 const intptr_t kNumTemps = 0; |
4854 LocationSummary* summary = | 4854 LocationSummary* summary = |
4855 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4855 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4856 summary->set_in(0, Location::RequiresFpuRegister()); | 4856 summary->set_in(0, Location::RequiresFpuRegister()); |
4857 summary->set_in(1, Location::RequiresFpuRegister()); | 4857 summary->set_in(1, Location::RequiresFpuRegister()); |
4858 summary->set_out(0, Location::RequiresFpuRegister()); | 4858 summary->set_out(0, Location::RequiresFpuRegister()); |
4859 return summary; | 4859 return summary; |
4860 } | 4860 } |
4861 | 4861 |
4862 | 4862 |
4863 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4863 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4864 QRegister left = locs()->in(0).fpu_reg(); | 4864 const QRegister left = locs()->in(0).fpu_reg(); |
4865 QRegister right = locs()->in(1).fpu_reg(); | 4865 const QRegister right = locs()->in(1).fpu_reg(); |
4866 QRegister result = locs()->out(0).fpu_reg(); | 4866 const QRegister result = locs()->out(0).fpu_reg(); |
4867 switch (op_kind()) { | 4867 switch (op_kind()) { |
4868 case Token::kBIT_AND: { | 4868 case Token::kBIT_AND: { |
4869 __ vandq(result, left, right); | 4869 __ vandq(result, left, right); |
4870 break; | 4870 break; |
4871 } | 4871 } |
4872 case Token::kBIT_OR: { | 4872 case Token::kBIT_OR: { |
4873 __ vorrq(result, left, right); | 4873 __ vorrq(result, left, right); |
4874 break; | 4874 break; |
4875 } | 4875 } |
4876 case Token::kBIT_XOR: { | 4876 case Token::kBIT_XOR: { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4911 LocationSummary* summary = | 4911 LocationSummary* summary = |
4912 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4912 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4913 summary->set_in(0, Location::RequiresFpuRegister()); | 4913 summary->set_in(0, Location::RequiresFpuRegister()); |
4914 summary->set_out(0, Location::RequiresFpuRegister()); | 4914 summary->set_out(0, Location::RequiresFpuRegister()); |
4915 return summary; | 4915 return summary; |
4916 } | 4916 } |
4917 | 4917 |
4918 | 4918 |
4919 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4919 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4920 if (kind() == MathUnaryInstr::kSqrt) { | 4920 if (kind() == MathUnaryInstr::kSqrt) { |
4921 DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 4921 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
4922 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 4922 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
4923 __ vsqrtd(result, val); | 4923 __ vsqrtd(result, val); |
4924 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4924 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
4925 DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 4925 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
4926 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 4926 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
4927 __ vmuld(result, val, val); | 4927 __ vmuld(result, val, val); |
4928 } else { | 4928 } else { |
4929 ASSERT((kind() == MathUnaryInstr::kSin) || | 4929 ASSERT((kind() == MathUnaryInstr::kSin) || |
4930 (kind() == MathUnaryInstr::kCos)); | 4930 (kind() == MathUnaryInstr::kCos)); |
4931 if (TargetCPUFeatures::hardfp_supported()) { | 4931 if (TargetCPUFeatures::hardfp_supported()) { |
4932 __ CallRuntime(TargetFunction(), InputCount()); | 4932 __ CallRuntime(TargetFunction(), InputCount()); |
4933 } else { | 4933 } else { |
4934 // If we aren't doing "hardfp", then we have to move the double arguments | 4934 // If we aren't doing "hardfp", then we have to move the double arguments |
4935 // to the integer registers, and take the results from the integer | 4935 // to the integer registers, and take the results from the integer |
4936 // registers. | 4936 // registers. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4969 return summary; | 4969 return summary; |
4970 } | 4970 } |
4971 | 4971 |
4972 | 4972 |
4973 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4973 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4974 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4974 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
4975 (op_kind() == MethodRecognizer::kMathMax)); | 4975 (op_kind() == MethodRecognizer::kMathMax)); |
4976 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4976 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
4977 if (result_cid() == kDoubleCid) { | 4977 if (result_cid() == kDoubleCid) { |
4978 Label done, returns_nan, are_equal; | 4978 Label done, returns_nan, are_equal; |
4979 DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 4979 const DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
4980 DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 4980 const DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
4981 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 4981 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
4982 Register temp = locs()->temp(0).reg(); | 4982 const Register temp = locs()->temp(0).reg(); |
4983 __ vcmpd(left, right); | 4983 __ vcmpd(left, right); |
4984 __ vmstat(); | 4984 __ vmstat(); |
4985 __ b(&returns_nan, VS); | 4985 __ b(&returns_nan, VS); |
4986 __ b(&are_equal, EQ); | 4986 __ b(&are_equal, EQ); |
4987 const Condition neg_double_condition = | 4987 const Condition neg_double_condition = |
4988 is_min ? TokenKindToDoubleCondition(Token::kGTE) | 4988 is_min ? TokenKindToDoubleCondition(Token::kGTE) |
4989 : TokenKindToDoubleCondition(Token::kLTE); | 4989 : TokenKindToDoubleCondition(Token::kLTE); |
4990 ASSERT(left == result); | 4990 ASSERT(left == result); |
4991 __ vmovd(result, right, neg_double_condition); | 4991 __ vmovd(result, right, neg_double_condition); |
4992 __ b(&done); | 4992 __ b(&done); |
(...skipping 16 matching lines...) Expand all Loading... |
5009 __ vmovd(result, right, GE); | 5009 __ vmovd(result, right, GE); |
5010 } else { | 5010 } else { |
5011 __ vmovd(result, right, LT); | 5011 __ vmovd(result, right, LT); |
5012 ASSERT(left == result); | 5012 ASSERT(left == result); |
5013 } | 5013 } |
5014 __ Bind(&done); | 5014 __ Bind(&done); |
5015 return; | 5015 return; |
5016 } | 5016 } |
5017 | 5017 |
5018 ASSERT(result_cid() == kSmiCid); | 5018 ASSERT(result_cid() == kSmiCid); |
5019 Register left = locs()->in(0).reg(); | 5019 const Register left = locs()->in(0).reg(); |
5020 Register right = locs()->in(1).reg(); | 5020 const Register right = locs()->in(1).reg(); |
5021 Register result = locs()->out(0).reg(); | 5021 const Register result = locs()->out(0).reg(); |
5022 __ cmp(left, ShifterOperand(right)); | 5022 __ cmp(left, ShifterOperand(right)); |
5023 ASSERT(result == left); | 5023 ASSERT(result == left); |
5024 if (is_min) { | 5024 if (is_min) { |
5025 __ mov(result, ShifterOperand(right), GT); | 5025 __ mov(result, ShifterOperand(right), GT); |
5026 } else { | 5026 } else { |
5027 __ mov(result, ShifterOperand(right), LT); | 5027 __ mov(result, ShifterOperand(right), LT); |
5028 } | 5028 } |
5029 } | 5029 } |
5030 | 5030 |
5031 | 5031 |
5032 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { | 5032 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(bool opt) const { |
5033 const intptr_t kNumInputs = 1; | 5033 const intptr_t kNumInputs = 1; |
5034 const intptr_t kNumTemps = 0; | 5034 const intptr_t kNumTemps = 0; |
5035 LocationSummary* summary = | 5035 LocationSummary* summary = |
5036 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5036 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5037 summary->set_in(0, Location::RequiresRegister()); | 5037 summary->set_in(0, Location::RequiresRegister()); |
5038 // We make use of 3-operand instructions by not requiring result register | 5038 // We make use of 3-operand instructions by not requiring result register |
5039 // to be identical to first input register as on Intel. | 5039 // to be identical to first input register as on Intel. |
5040 summary->set_out(0, Location::RequiresRegister()); | 5040 summary->set_out(0, Location::RequiresRegister()); |
5041 return summary; | 5041 return summary; |
5042 } | 5042 } |
5043 | 5043 |
5044 | 5044 |
5045 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5045 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5046 Register value = locs()->in(0).reg(); | 5046 const Register value = locs()->in(0).reg(); |
5047 Register result = locs()->out(0).reg(); | 5047 const Register result = locs()->out(0).reg(); |
5048 switch (op_kind()) { | 5048 switch (op_kind()) { |
5049 case Token::kNEGATE: { | 5049 case Token::kNEGATE: { |
5050 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 5050 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
5051 __ rsbs(result, value, ShifterOperand(0)); | 5051 __ rsbs(result, value, ShifterOperand(0)); |
5052 __ b(deopt, VS); | 5052 __ b(deopt, VS); |
5053 break; | 5053 break; |
5054 } | 5054 } |
5055 case Token::kBIT_NOT: | 5055 case Token::kBIT_NOT: |
5056 __ mvn(result, ShifterOperand(value)); | 5056 __ mvn(result, ShifterOperand(value)); |
5057 // Remove inverted smi-tag. | 5057 // Remove inverted smi-tag. |
(...skipping 10 matching lines...) Expand all Loading... |
5068 const intptr_t kNumTemps = 0; | 5068 const intptr_t kNumTemps = 0; |
5069 LocationSummary* summary = | 5069 LocationSummary* summary = |
5070 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5070 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5071 summary->set_in(0, Location::RequiresFpuRegister()); | 5071 summary->set_in(0, Location::RequiresFpuRegister()); |
5072 summary->set_out(0, Location::RequiresFpuRegister()); | 5072 summary->set_out(0, Location::RequiresFpuRegister()); |
5073 return summary; | 5073 return summary; |
5074 } | 5074 } |
5075 | 5075 |
5076 | 5076 |
5077 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5077 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5078 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5078 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5079 DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5079 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5080 __ vnegd(result, value); | 5080 __ vnegd(result, value); |
5081 } | 5081 } |
5082 | 5082 |
5083 | 5083 |
5084 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { | 5084 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { |
5085 const intptr_t kNumInputs = 1; | 5085 const intptr_t kNumInputs = 1; |
5086 const intptr_t kNumTemps = 0; | 5086 const intptr_t kNumTemps = 0; |
5087 LocationSummary* result = | 5087 LocationSummary* result = |
5088 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5088 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5089 result->set_in(0, Location::WritableRegister()); | 5089 result->set_in(0, Location::WritableRegister()); |
5090 result->set_out(0, Location::RequiresFpuRegister()); | 5090 result->set_out(0, Location::RequiresFpuRegister()); |
5091 return result; | 5091 return result; |
5092 } | 5092 } |
5093 | 5093 |
5094 | 5094 |
5095 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5095 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5096 Register value = locs()->in(0).reg(); | 5096 const Register value = locs()->in(0).reg(); |
5097 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5097 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5098 __ SmiUntag(value); | 5098 __ SmiUntag(value); |
5099 __ vmovsr(STMP, value); | 5099 __ vmovsr(STMP, value); |
5100 __ vcvtdi(result, STMP); | 5100 __ vcvtdi(result, STMP); |
5101 } | 5101 } |
5102 | 5102 |
5103 | 5103 |
5104 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { | 5104 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { |
5105 const intptr_t kNumInputs = 1; | 5105 const intptr_t kNumInputs = 1; |
5106 const intptr_t kNumTemps = 0; | 5106 const intptr_t kNumTemps = 0; |
5107 LocationSummary* result = | 5107 LocationSummary* result = |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5200 LocationSummary* result = | 5200 LocationSummary* result = |
5201 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5201 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5202 // Low (<= Q7) Q registers are needed for the conversion instructions. | 5202 // Low (<= Q7) Q registers are needed for the conversion instructions. |
5203 result->set_in(0, Location::RequiresFpuRegister()); | 5203 result->set_in(0, Location::RequiresFpuRegister()); |
5204 result->set_out(0, Location::FpuRegisterLocation(Q7)); | 5204 result->set_out(0, Location::FpuRegisterLocation(Q7)); |
5205 return result; | 5205 return result; |
5206 } | 5206 } |
5207 | 5207 |
5208 | 5208 |
5209 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5209 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5210 DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5210 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5211 SRegister result = EvenSRegisterOf(EvenDRegisterOf(locs()->out(0).fpu_reg())); | 5211 const SRegister result = |
| 5212 EvenSRegisterOf(EvenDRegisterOf(locs()->out(0).fpu_reg())); |
5212 __ vcvtsd(result, value); | 5213 __ vcvtsd(result, value); |
5213 } | 5214 } |
5214 | 5215 |
5215 | 5216 |
5216 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { | 5217 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(bool opt) const { |
5217 const intptr_t kNumInputs = 1; | 5218 const intptr_t kNumInputs = 1; |
5218 const intptr_t kNumTemps = 0; | 5219 const intptr_t kNumTemps = 0; |
5219 LocationSummary* result = | 5220 LocationSummary* result = |
5220 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5221 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5221 // Low (<= Q7) Q registers are needed for the conversion instructions. | 5222 // Low (<= Q7) Q registers are needed for the conversion instructions. |
5222 result->set_in(0, Location::FpuRegisterLocation(Q7)); | 5223 result->set_in(0, Location::FpuRegisterLocation(Q7)); |
5223 result->set_out(0, Location::RequiresFpuRegister()); | 5224 result->set_out(0, Location::RequiresFpuRegister()); |
5224 return result; | 5225 return result; |
5225 } | 5226 } |
5226 | 5227 |
5227 | 5228 |
5228 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5229 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5229 SRegister value = EvenSRegisterOf(EvenDRegisterOf(locs()->in(0).fpu_reg())); | 5230 const SRegister value = |
5230 DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5231 EvenSRegisterOf(EvenDRegisterOf(locs()->in(0).fpu_reg())); |
| 5232 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5231 __ vcvtds(result, value); | 5233 __ vcvtds(result, value); |
5232 } | 5234 } |
5233 | 5235 |
5234 | 5236 |
5235 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { | 5237 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { |
5236 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5238 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
5237 const intptr_t kNumTemps = 0; | 5239 const intptr_t kNumTemps = 0; |
5238 LocationSummary* result = | 5240 LocationSummary* result = |
5239 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); | 5241 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
5240 result->set_in(0, Location::FpuRegisterLocation(Q0)); | 5242 result->set_in(0, Location::FpuRegisterLocation(Q0)); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5445 } | 5447 } |
5446 return summary; | 5448 return summary; |
5447 } | 5449 } |
5448 | 5450 |
5449 | 5451 |
5450 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5452 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5451 ASSERT(locs()->in(0).IsPairLocation()); | 5453 ASSERT(locs()->in(0).IsPairLocation()); |
5452 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5454 PairLocation* pair = locs()->in(0).AsPairLocation(); |
5453 Location in_loc = pair->At(index()); | 5455 Location in_loc = pair->At(index()); |
5454 if (representation() == kUnboxedDouble) { | 5456 if (representation() == kUnboxedDouble) { |
5455 QRegister out = locs()->out(0).fpu_reg(); | 5457 const QRegister out = locs()->out(0).fpu_reg(); |
5456 QRegister in = in_loc.fpu_reg(); | 5458 const QRegister in = in_loc.fpu_reg(); |
5457 __ vmovq(out, in); | 5459 __ vmovq(out, in); |
5458 } else { | 5460 } else { |
5459 ASSERT(representation() == kTagged); | 5461 ASSERT(representation() == kTagged); |
5460 Register out = locs()->out(0).reg(); | 5462 const Register out = locs()->out(0).reg(); |
5461 Register in = in_loc.reg(); | 5463 const Register in = in_loc.reg(); |
5462 __ mov(out, ShifterOperand(in)); | 5464 __ mov(out, ShifterOperand(in)); |
5463 } | 5465 } |
5464 } | 5466 } |
5465 | 5467 |
5466 | 5468 |
5467 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 5469 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
5468 if (kind() == MergedMathInstr::kTruncDivMod) { | 5470 if (kind() == MergedMathInstr::kTruncDivMod) { |
5469 const intptr_t kNumInputs = 2; | 5471 const intptr_t kNumInputs = 2; |
5470 const intptr_t kNumTemps = 2; | 5472 const intptr_t kNumTemps = 2; |
5471 LocationSummary* summary = | 5473 LocationSummary* summary = |
(...skipping 11 matching lines...) Expand all Loading... |
5483 return NULL; | 5485 return NULL; |
5484 } | 5486 } |
5485 | 5487 |
5486 | 5488 |
5487 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5489 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5488 Label* deopt = NULL; | 5490 Label* deopt = NULL; |
5489 if (CanDeoptimize()) { | 5491 if (CanDeoptimize()) { |
5490 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5492 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
5491 } | 5493 } |
5492 if (kind() == MergedMathInstr::kTruncDivMod) { | 5494 if (kind() == MergedMathInstr::kTruncDivMod) { |
5493 Register left = locs()->in(0).reg(); | 5495 const Register left = locs()->in(0).reg(); |
5494 Register right = locs()->in(1).reg(); | 5496 const Register right = locs()->in(1).reg(); |
5495 ASSERT(locs()->out(0).IsPairLocation()); | 5497 ASSERT(locs()->out(0).IsPairLocation()); |
5496 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5498 PairLocation* pair = locs()->out(0).AsPairLocation(); |
5497 Register result_div = pair->At(0).reg(); | 5499 const Register result_div = pair->At(0).reg(); |
5498 Register result_mod = pair->At(1).reg(); | 5500 const Register result_mod = pair->At(1).reg(); |
5499 Range* right_range = InputAt(1)->definition()->range(); | 5501 Range* right_range = InputAt(1)->definition()->range(); |
5500 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 5502 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
5501 // Handle divide by zero in runtime. | 5503 // Handle divide by zero in runtime. |
5502 __ cmp(right, ShifterOperand(0)); | 5504 __ cmp(right, ShifterOperand(0)); |
5503 __ b(deopt, EQ); | 5505 __ b(deopt, EQ); |
5504 } | 5506 } |
5505 Register temp = locs()->temp(0).reg(); | 5507 const Register temp = locs()->temp(0).reg(); |
5506 DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 5508 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
5507 | 5509 |
5508 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 5510 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
5509 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 5511 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. |
5510 | 5512 |
5511 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); | 5513 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); |
5512 | 5514 |
5513 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5515 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
5514 // case we cannot tag the result. | 5516 // case we cannot tag the result. |
5515 __ CompareImmediate(result_div, 0x40000000); | 5517 __ CompareImmediate(result_div, 0x40000000); |
5516 __ b(deopt, EQ); | 5518 __ b(deopt, EQ); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5622 if (IsNullCheck()) { | 5624 if (IsNullCheck()) { |
5623 Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason); | 5625 Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason); |
5624 __ CompareImmediate(locs()->in(0).reg(), | 5626 __ CompareImmediate(locs()->in(0).reg(), |
5625 reinterpret_cast<intptr_t>(Object::null())); | 5627 reinterpret_cast<intptr_t>(Object::null())); |
5626 __ b(deopt, EQ); | 5628 __ b(deopt, EQ); |
5627 return; | 5629 return; |
5628 } | 5630 } |
5629 | 5631 |
5630 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5632 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
5631 (unary_checks().NumberOfChecks() > 1)); | 5633 (unary_checks().NumberOfChecks() > 1)); |
5632 Register value = locs()->in(0).reg(); | 5634 const Register value = locs()->in(0).reg(); |
5633 Register temp = locs()->temp(0).reg(); | 5635 const Register temp = locs()->temp(0).reg(); |
5634 Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason); | 5636 Label* deopt = compiler->AddDeoptStub(deopt_id(), deopt_reason); |
5635 Label is_ok; | 5637 Label is_ok; |
5636 intptr_t cix = 0; | 5638 intptr_t cix = 0; |
5637 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { | 5639 if (unary_checks().GetReceiverClassIdAt(cix) == kSmiCid) { |
5638 __ tst(value, ShifterOperand(kSmiTagMask)); | 5640 __ tst(value, ShifterOperand(kSmiTagMask)); |
5639 __ b(&is_ok, EQ); | 5641 __ b(&is_ok, EQ); |
5640 cix++; // Skip first check. | 5642 cix++; // Skip first check. |
5641 } else { | 5643 } else { |
5642 __ tst(value, ShifterOperand(kSmiTagMask)); | 5644 __ tst(value, ShifterOperand(kSmiTagMask)); |
5643 __ b(deopt, EQ); | 5645 __ b(deopt, EQ); |
(...skipping 17 matching lines...) Expand all Loading... |
5661 const intptr_t kNumInputs = 1; | 5663 const intptr_t kNumInputs = 1; |
5662 const intptr_t kNumTemps = 0; | 5664 const intptr_t kNumTemps = 0; |
5663 LocationSummary* summary = | 5665 LocationSummary* summary = |
5664 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5666 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5665 summary->set_in(0, Location::RequiresRegister()); | 5667 summary->set_in(0, Location::RequiresRegister()); |
5666 return summary; | 5668 return summary; |
5667 } | 5669 } |
5668 | 5670 |
5669 | 5671 |
5670 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5672 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5671 Register value = locs()->in(0).reg(); | 5673 const Register value = locs()->in(0).reg(); |
5672 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi); | 5674 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi); |
5673 __ tst(value, ShifterOperand(kSmiTagMask)); | 5675 __ tst(value, ShifterOperand(kSmiTagMask)); |
5674 __ b(deopt, NE); | 5676 __ b(deopt, NE); |
5675 } | 5677 } |
5676 | 5678 |
5677 | 5679 |
5678 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const { | 5680 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(bool opt) const { |
5679 const intptr_t kNumInputs = 2; | 5681 const intptr_t kNumInputs = 2; |
5680 const intptr_t kNumTemps = 0; | 5682 const intptr_t kNumTemps = 0; |
5681 LocationSummary* locs = | 5683 LocationSummary* locs = |
(...skipping 15 matching lines...) Expand all Loading... |
5697 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 5699 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
5698 Smi::Cast(index_loc.constant()).Value()) || | 5700 Smi::Cast(index_loc.constant()).Value()) || |
5699 (Smi::Cast(index_loc.constant()).Value() < 0)); | 5701 (Smi::Cast(index_loc.constant()).Value() < 0)); |
5700 // Unconditionally deoptimize for constant bounds checks because they | 5702 // Unconditionally deoptimize for constant bounds checks because they |
5701 // only occur only when index is out-of-bounds. | 5703 // only occur only when index is out-of-bounds. |
5702 __ b(deopt); | 5704 __ b(deopt); |
5703 return; | 5705 return; |
5704 } | 5706 } |
5705 | 5707 |
5706 if (index_loc.IsConstant()) { | 5708 if (index_loc.IsConstant()) { |
5707 Register length = length_loc.reg(); | 5709 const Register length = length_loc.reg(); |
5708 const Smi& index = Smi::Cast(index_loc.constant()); | 5710 const Smi& index = Smi::Cast(index_loc.constant()); |
5709 __ CompareImmediate(length, reinterpret_cast<int32_t>(index.raw())); | 5711 __ CompareImmediate(length, reinterpret_cast<int32_t>(index.raw())); |
5710 __ b(deopt, LS); | 5712 __ b(deopt, LS); |
5711 } else if (length_loc.IsConstant()) { | 5713 } else if (length_loc.IsConstant()) { |
5712 const Smi& length = Smi::Cast(length_loc.constant()); | 5714 const Smi& length = Smi::Cast(length_loc.constant()); |
5713 Register index = index_loc.reg(); | 5715 const Register index = index_loc.reg(); |
5714 __ CompareImmediate(index, reinterpret_cast<int32_t>(length.raw())); | 5716 __ CompareImmediate(index, reinterpret_cast<int32_t>(length.raw())); |
5715 __ b(deopt, CS); | 5717 __ b(deopt, CS); |
5716 } else { | 5718 } else { |
5717 Register length = length_loc.reg(); | 5719 const Register length = length_loc.reg(); |
5718 Register index = index_loc.reg(); | 5720 const Register index = index_loc.reg(); |
5719 __ cmp(index, ShifterOperand(length)); | 5721 __ cmp(index, ShifterOperand(length)); |
5720 __ b(deopt, CS); | 5722 __ b(deopt, CS); |
5721 } | 5723 } |
5722 } | 5724 } |
5723 | 5725 |
5724 | 5726 |
5725 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, | 5727 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, |
5726 Label* overflow, | 5728 Label* overflow, |
5727 QRegister result, | 5729 QRegister result, |
5728 Register tmp_hi, Register tmp_lo) { | 5730 Register tmp_hi, Register tmp_lo) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5767 const intptr_t value_cid = value()->Type()->ToCid(); | 5769 const intptr_t value_cid = value()->Type()->ToCid(); |
5768 const Register value = locs()->in(0).reg(); | 5770 const Register value = locs()->in(0).reg(); |
5769 const QRegister result = locs()->out(0).fpu_reg(); | 5771 const QRegister result = locs()->out(0).fpu_reg(); |
5770 | 5772 |
5771 __ Comment("UnboxIntegerInstr"); | 5773 __ Comment("UnboxIntegerInstr"); |
5772 __ veorq(result, result, result); | 5774 __ veorq(result, result, result); |
5773 if (value_cid == kMintCid) { | 5775 if (value_cid == kMintCid) { |
5774 __ LoadDFromOffset(EvenDRegisterOf(result), value, | 5776 __ LoadDFromOffset(EvenDRegisterOf(result), value, |
5775 Mint::value_offset() - kHeapObjectTag); | 5777 Mint::value_offset() - kHeapObjectTag); |
5776 } else if (value_cid == kSmiCid) { | 5778 } else if (value_cid == kSmiCid) { |
5777 Register temp = locs()->temp(0).reg(); | 5779 const Register temp = locs()->temp(0).reg(); |
5778 __ SmiUntag(value); | 5780 __ SmiUntag(value); |
5779 // Sign extend value into temp. | 5781 // Sign extend value into temp. |
5780 __ Asr(temp, value, 31); | 5782 __ Asr(temp, value, 31); |
5781 __ vmovdrr(EvenDRegisterOf(result), value, temp); | 5783 __ vmovdrr(EvenDRegisterOf(result), value, temp); |
5782 } else { | 5784 } else { |
5783 Register temp = locs()->temp(0).reg(); | 5785 const Register temp = locs()->temp(0).reg(); |
5784 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5786 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
5785 ICData::kDeoptUnboxInteger); | 5787 ICData::kDeoptUnboxInteger); |
5786 Label is_smi, done; | 5788 Label is_smi, done; |
5787 __ tst(value, ShifterOperand(kSmiTagMask)); | 5789 __ tst(value, ShifterOperand(kSmiTagMask)); |
5788 __ b(&is_smi, EQ); | 5790 __ b(&is_smi, EQ); |
5789 __ CompareClassId(value, kMintCid, temp); | 5791 __ CompareClassId(value, kMintCid, temp); |
5790 __ b(deopt, NE); | 5792 __ b(deopt, NE); |
5791 | 5793 |
5792 // It's a Mint. | 5794 // It's a Mint. |
5793 __ LoadDFromOffset(EvenDRegisterOf(result), value, | 5795 __ LoadDFromOffset(EvenDRegisterOf(result), value, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5850 | 5852 |
5851 private: | 5853 private: |
5852 BoxIntegerInstr* instruction_; | 5854 BoxIntegerInstr* instruction_; |
5853 }; | 5855 }; |
5854 | 5856 |
5855 | 5857 |
5856 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5858 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5857 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); | 5859 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
5858 compiler->AddSlowPathCode(slow_path); | 5860 compiler->AddSlowPathCode(slow_path); |
5859 | 5861 |
5860 Register out_reg = locs()->out(0).reg(); | 5862 const Register out_reg = locs()->out(0).reg(); |
5861 QRegister value = locs()->in(0).fpu_reg(); | 5863 const QRegister value = locs()->in(0).fpu_reg(); |
5862 DRegister dvalue0 = EvenDRegisterOf(value); | 5864 const DRegister dvalue0 = EvenDRegisterOf(value); |
5863 Register lo = locs()->temp(0).reg(); | 5865 const Register lo = locs()->temp(0).reg(); |
5864 Register hi = locs()->temp(1).reg(); | 5866 const Register hi = locs()->temp(1).reg(); |
5865 | 5867 |
5866 // Unboxed operations produce smis or mint-sized values. | 5868 // Unboxed operations produce smis or mint-sized values. |
5867 // Check if value fits into a smi. | 5869 // Check if value fits into a smi. |
5868 __ Comment("BoxIntegerInstr"); | 5870 __ Comment("BoxIntegerInstr"); |
5869 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; | 5871 Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi; |
5870 __ vmovrrd(lo, hi, dvalue0); | 5872 __ vmovrrd(lo, hi, dvalue0); |
5871 __ CompareImmediate(hi, 0); | 5873 __ CompareImmediate(hi, 0); |
5872 __ b(&maybe_pos_smi, EQ); | 5874 __ b(&maybe_pos_smi, EQ); |
5873 | 5875 |
5874 __ CompareImmediate(hi, -1); | 5876 __ CompareImmediate(hi, -1); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5921 // Need another temp for checking for overflow. | 5923 // Need another temp for checking for overflow. |
5922 summary->AddTemp(Location::RequiresFpuRegister()); | 5924 summary->AddTemp(Location::RequiresFpuRegister()); |
5923 summary->AddTemp(Location::FpuRegisterLocation(Q7)); | 5925 summary->AddTemp(Location::FpuRegisterLocation(Q7)); |
5924 } | 5926 } |
5925 summary->set_out(0, Location::RequiresFpuRegister()); | 5927 summary->set_out(0, Location::RequiresFpuRegister()); |
5926 return summary; | 5928 return summary; |
5927 } | 5929 } |
5928 | 5930 |
5929 | 5931 |
5930 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5932 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5931 QRegister left = locs()->in(0).fpu_reg(); | 5933 const QRegister left = locs()->in(0).fpu_reg(); |
5932 QRegister right = locs()->in(1).fpu_reg(); | 5934 const QRegister right = locs()->in(1).fpu_reg(); |
5933 QRegister out = locs()->out(0).fpu_reg(); | 5935 const QRegister out = locs()->out(0).fpu_reg(); |
5934 | 5936 |
5935 Label* deopt = NULL; | 5937 Label* deopt = NULL; |
5936 if (FLAG_throw_on_javascript_int_overflow) { | 5938 if (FLAG_throw_on_javascript_int_overflow) { |
5937 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5939 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5938 } | 5940 } |
5939 switch (op_kind()) { | 5941 switch (op_kind()) { |
5940 case Token::kBIT_AND: __ vandq(out, left, right); break; | 5942 case Token::kBIT_AND: __ vandq(out, left, right); break; |
5941 case Token::kBIT_OR: __ vorrq(out, left, right); break; | 5943 case Token::kBIT_OR: __ vorrq(out, left, right); break; |
5942 case Token::kBIT_XOR: __ veorq(out, left, right); break; | 5944 case Token::kBIT_XOR: __ veorq(out, left, right); break; |
5943 case Token::kADD: | 5945 case Token::kADD: |
5944 case Token::kSUB: { | 5946 case Token::kSUB: { |
5945 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0; | 5947 const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0; |
5946 QRegister tmp = locs()->temp(tmpidx).fpu_reg(); | 5948 const QRegister tmp = locs()->temp(tmpidx).fpu_reg(); |
5947 QRegister ro = locs()->temp(tmpidx + 1).fpu_reg(); | 5949 const QRegister ro = locs()->temp(tmpidx + 1).fpu_reg(); |
5948 ASSERT(ro == Q7); | 5950 ASSERT(ro == Q7); |
5949 if (!FLAG_throw_on_javascript_int_overflow) { | 5951 if (!FLAG_throw_on_javascript_int_overflow) { |
5950 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5952 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
5951 } | 5953 } |
5952 if (op_kind() == Token::kADD) { | 5954 if (op_kind() == Token::kADD) { |
5953 __ vaddqi(kWordPair, out, left, right); | 5955 __ vaddqi(kWordPair, out, left, right); |
5954 } else { | 5956 } else { |
5955 ASSERT(op_kind() == Token::kSUB); | 5957 ASSERT(op_kind() == Token::kSUB); |
5956 __ vsubqi(kWordPair, out, left, right); | 5958 __ vsubqi(kWordPair, out, left, right); |
5957 } | 5959 } |
5958 __ veorq(ro, out, left); | 5960 __ veorq(ro, out, left); |
5959 __ veorq(tmp, left, right); | 5961 __ veorq(tmp, left, right); |
5960 __ vandq(ro, tmp, ro); | 5962 __ vandq(ro, tmp, ro); |
5961 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro))); | 5963 __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro))); |
5962 // If TMP < 0, there was overflow. | 5964 // If TMP < 0, there was overflow. |
5963 __ cmp(TMP, ShifterOperand(0)); | 5965 __ cmp(TMP, ShifterOperand(0)); |
5964 __ b(deopt, LT); | 5966 __ b(deopt, LT); |
5965 break; | 5967 break; |
5966 } | 5968 } |
5967 default: UNREACHABLE(); break; | 5969 default: UNREACHABLE(); break; |
5968 } | 5970 } |
5969 if (FLAG_throw_on_javascript_int_overflow) { | 5971 if (FLAG_throw_on_javascript_int_overflow) { |
5970 Register tmp1 = locs()->temp(0).reg(); | 5972 const Register tmp1 = locs()->temp(0).reg(); |
5971 Register tmp2 = locs()->temp(1).reg(); | 5973 const Register tmp2 = locs()->temp(1).reg(); |
5972 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); | 5974 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); |
5973 } | 5975 } |
5974 } | 5976 } |
5975 | 5977 |
5976 | 5978 |
5977 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { | 5979 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const { |
5978 const intptr_t kNumInputs = 2; | 5980 const intptr_t kNumInputs = 2; |
5979 const intptr_t kNumTemps = | 5981 const intptr_t kNumTemps = |
5980 FLAG_throw_on_javascript_int_overflow ? 2 : 1; | 5982 FLAG_throw_on_javascript_int_overflow ? 2 : 1; |
5981 LocationSummary* summary = | 5983 LocationSummary* summary = |
5982 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5984 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5983 summary->set_in(0, Location::RequiresFpuRegister()); | 5985 summary->set_in(0, Location::RequiresFpuRegister()); |
5984 summary->set_in(1, Location::WritableRegister()); | 5986 summary->set_in(1, Location::WritableRegister()); |
5985 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); | 5987 summary->set_temp(0, Location::FpuRegisterLocation(Q7)); |
5986 if (FLAG_throw_on_javascript_int_overflow) { | 5988 if (FLAG_throw_on_javascript_int_overflow) { |
5987 summary->set_temp(1, Location::RequiresRegister()); | 5989 summary->set_temp(1, Location::RequiresRegister()); |
5988 } | 5990 } |
5989 summary->set_out(0, Location::RequiresFpuRegister()); | 5991 summary->set_out(0, Location::RequiresFpuRegister()); |
5990 return summary; | 5992 return summary; |
5991 } | 5993 } |
5992 | 5994 |
5993 | 5995 |
5994 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5996 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5995 QRegister value = locs()->in(0).fpu_reg(); | 5997 const QRegister value = locs()->in(0).fpu_reg(); |
5996 Register shift = locs()->in(1).reg(); | 5998 const Register shift = locs()->in(1).reg(); |
5997 QRegister temp = locs()->temp(0).fpu_reg(); | 5999 const QRegister temp = locs()->temp(0).fpu_reg(); |
5998 ASSERT(temp == Q7); | 6000 ASSERT(temp == Q7); |
5999 QRegister out = locs()->out(0).fpu_reg(); | 6001 const QRegister out = locs()->out(0).fpu_reg(); |
6000 DRegister dtemp0 = EvenDRegisterOf(temp); | 6002 const DRegister dtemp0 = EvenDRegisterOf(temp); |
6001 SRegister stemp0 = EvenSRegisterOf(dtemp0); | 6003 const SRegister stemp0 = EvenSRegisterOf(dtemp0); |
6002 SRegister stemp1 = OddSRegisterOf(dtemp0); | 6004 const SRegister stemp1 = OddSRegisterOf(dtemp0); |
6003 | 6005 |
6004 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 6006 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
6005 Label done; | 6007 Label done; |
6006 | 6008 |
6007 __ CompareImmediate(shift, 0); | 6009 __ CompareImmediate(shift, 0); |
6008 __ vmovq(out, value); | 6010 __ vmovq(out, value); |
6009 __ b(&done, EQ); | 6011 __ b(&done, EQ); |
6010 __ SmiUntag(shift); | 6012 __ SmiUntag(shift); |
6011 | 6013 |
6012 // vshlq takes the shift value from low byte. Deopt if shift is | 6014 // vshlq takes the shift value from low byte. Deopt if shift is |
(...skipping 30 matching lines...) Expand all Loading... |
6043 __ b(deopt, NE); | 6045 __ b(deopt, NE); |
6044 break; | 6046 break; |
6045 } | 6047 } |
6046 default: | 6048 default: |
6047 UNREACHABLE(); | 6049 UNREACHABLE(); |
6048 break; | 6050 break; |
6049 } | 6051 } |
6050 | 6052 |
6051 __ Bind(&done); | 6053 __ Bind(&done); |
6052 if (FLAG_throw_on_javascript_int_overflow) { | 6054 if (FLAG_throw_on_javascript_int_overflow) { |
6053 Register tmp1 = locs()->in(1).reg(); | 6055 const Register tmp1 = locs()->in(1).reg(); |
6054 Register tmp2 = locs()->temp(1).reg(); | 6056 const Register tmp2 = locs()->temp(1).reg(); |
6055 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); | 6057 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); |
6056 } | 6058 } |
6057 } | 6059 } |
6058 | 6060 |
6059 | 6061 |
6060 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { | 6062 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const { |
6061 const intptr_t kNumInputs = 1; | 6063 const intptr_t kNumInputs = 1; |
6062 const intptr_t kNumTemps = | 6064 const intptr_t kNumTemps = |
6063 FLAG_throw_on_javascript_int_overflow ? 2 : 0; | 6065 FLAG_throw_on_javascript_int_overflow ? 2 : 0; |
6064 LocationSummary* summary = | 6066 LocationSummary* summary = |
6065 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6067 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6066 summary->set_in(0, Location::RequiresFpuRegister()); | 6068 summary->set_in(0, Location::RequiresFpuRegister()); |
6067 summary->set_out(0, Location::RequiresFpuRegister()); | 6069 summary->set_out(0, Location::RequiresFpuRegister()); |
6068 if (FLAG_throw_on_javascript_int_overflow) { | 6070 if (FLAG_throw_on_javascript_int_overflow) { |
6069 summary->set_temp(0, Location::RequiresRegister()); | 6071 summary->set_temp(0, Location::RequiresRegister()); |
6070 summary->set_temp(1, Location::RequiresRegister()); | 6072 summary->set_temp(1, Location::RequiresRegister()); |
6071 } | 6073 } |
6072 return summary; | 6074 return summary; |
6073 } | 6075 } |
6074 | 6076 |
6075 | 6077 |
6076 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6078 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6077 ASSERT(op_kind() == Token::kBIT_NOT); | 6079 ASSERT(op_kind() == Token::kBIT_NOT); |
6078 QRegister value = locs()->in(0).fpu_reg(); | 6080 const QRegister value = locs()->in(0).fpu_reg(); |
6079 QRegister out = locs()->out(0).fpu_reg(); | 6081 const QRegister out = locs()->out(0).fpu_reg(); |
6080 Label* deopt = NULL; | 6082 Label* deopt = NULL; |
6081 if (FLAG_throw_on_javascript_int_overflow) { | 6083 if (FLAG_throw_on_javascript_int_overflow) { |
6082 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); | 6084 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp); |
6083 } | 6085 } |
6084 __ vmvnq(out, value); | 6086 __ vmvnq(out, value); |
6085 if (FLAG_throw_on_javascript_int_overflow) { | 6087 if (FLAG_throw_on_javascript_int_overflow) { |
6086 Register tmp1 = locs()->temp(0).reg(); | 6088 const Register tmp1 = locs()->temp(0).reg(); |
6087 Register tmp2 = locs()->temp(1).reg(); | 6089 const Register tmp2 = locs()->temp(1).reg(); |
6088 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); | 6090 EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2); |
6089 } | 6091 } |
6090 } | 6092 } |
6091 | 6093 |
6092 | 6094 |
6093 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { | 6095 LocationSummary* ThrowInstr::MakeLocationSummary(bool opt) const { |
6094 return new LocationSummary(0, 0, LocationSummary::kCall); | 6096 return new LocationSummary(0, 0, LocationSummary::kCall); |
6095 } | 6097 } |
6096 | 6098 |
6097 | 6099 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6237 } | 6239 } |
6238 | 6240 |
6239 | 6241 |
6240 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6242 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6241 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6243 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
6242 | 6244 |
6243 // The ARM code does not use true- and false-labels here. | 6245 // The ARM code does not use true- and false-labels here. |
6244 BranchLabels labels = { NULL, NULL, NULL }; | 6246 BranchLabels labels = { NULL, NULL, NULL }; |
6245 Condition true_condition = EmitComparisonCode(compiler, labels); | 6247 Condition true_condition = EmitComparisonCode(compiler, labels); |
6246 | 6248 |
6247 Register result = locs()->out(0).reg(); | 6249 const Register result = locs()->out(0).reg(); |
6248 __ LoadObject(result, Bool::True(), true_condition); | 6250 __ LoadObject(result, Bool::True(), true_condition); |
6249 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 6251 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
6250 } | 6252 } |
6251 | 6253 |
6252 | 6254 |
6253 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 6255 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
6254 BranchInstr* branch) { | 6256 BranchInstr* branch) { |
6255 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6257 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
6256 | 6258 |
6257 BranchLabels labels = compiler->CreateBranchLabels(branch); | 6259 BranchLabels labels = compiler->CreateBranchLabels(branch); |
6258 Condition true_condition = EmitComparisonCode(compiler, labels); | 6260 Condition true_condition = EmitComparisonCode(compiler, labels); |
6259 EmitBranchOnCondition(compiler, true_condition, labels); | 6261 EmitBranchOnCondition(compiler, true_condition, labels); |
6260 } | 6262 } |
6261 | 6263 |
6262 | 6264 |
6263 LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const { | 6265 LocationSummary* BooleanNegateInstr::MakeLocationSummary(bool opt) const { |
6264 return LocationSummary::Make(1, | 6266 return LocationSummary::Make(1, |
6265 Location::RequiresRegister(), | 6267 Location::RequiresRegister(), |
6266 LocationSummary::kNoCall); | 6268 LocationSummary::kNoCall); |
6267 } | 6269 } |
6268 | 6270 |
6269 | 6271 |
6270 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6272 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6271 Register value = locs()->in(0).reg(); | 6273 const Register value = locs()->in(0).reg(); |
6272 Register result = locs()->out(0).reg(); | 6274 const Register result = locs()->out(0).reg(); |
6273 | 6275 |
6274 __ LoadObject(result, Bool::True()); | 6276 __ LoadObject(result, Bool::True()); |
6275 __ cmp(result, ShifterOperand(value)); | 6277 __ cmp(result, ShifterOperand(value)); |
6276 __ LoadObject(result, Bool::False(), EQ); | 6278 __ LoadObject(result, Bool::False(), EQ); |
6277 } | 6279 } |
6278 | 6280 |
6279 | 6281 |
6280 LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const { | 6282 LocationSummary* AllocateObjectInstr::MakeLocationSummary(bool opt) const { |
6281 return MakeCallSummary(); | 6283 return MakeCallSummary(); |
6282 } | 6284 } |
6283 | 6285 |
6284 | 6286 |
6285 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6287 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6286 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls())); | 6288 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls())); |
6287 const ExternalLabel label(cls().ToCString(), stub.EntryPoint()); | 6289 const ExternalLabel label(cls().ToCString(), stub.EntryPoint()); |
6288 compiler->GenerateCall(token_pos(), | 6290 compiler->GenerateCall(token_pos(), |
6289 &label, | 6291 &label, |
6290 PcDescriptors::kOther, | 6292 PcDescriptors::kOther, |
6291 locs()); | 6293 locs()); |
6292 __ Drop(ArgumentCount()); // Discard arguments. | 6294 __ Drop(ArgumentCount()); // Discard arguments. |
6293 } | 6295 } |
6294 | 6296 |
6295 } // namespace dart | 6297 } // namespace dart |
6296 | 6298 |
6297 #endif // defined TARGET_ARCH_ARM | 6299 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |