| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 return EmitSmiComparisonOp(compiler, locs(), kind()); | 484 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 485 } else { | 485 } else { |
| 486 ASSERT(operation_cid() == kDoubleCid); | 486 ASSERT(operation_cid() == kDoubleCid); |
| 487 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 487 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 488 } | 488 } |
| 489 } | 489 } |
| 490 | 490 |
| 491 | 491 |
| 492 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 492 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 493 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 493 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 494 | |
| 495 Label is_true, is_false; | 494 Label is_true, is_false; |
| 496 BranchLabels labels = { &is_true, &is_false, &is_false }; | 495 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 497 Condition true_condition = EmitComparisonCode(compiler, labels); | 496 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 497 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 498 // Special case for NaN comparison. Result is always false unless |
| 499 // relational operator is !=. |
| 500 __ b(&is_false, VS); |
| 501 } |
| 498 EmitBranchOnCondition(compiler, true_condition, labels); | 502 EmitBranchOnCondition(compiler, true_condition, labels); |
| 499 | |
| 500 // TODO(zra): instead of branching, use the csel instruction to get | 503 // TODO(zra): instead of branching, use the csel instruction to get |
| 501 // True or False into result. | 504 // True or False into result. |
| 502 Register result = locs()->out(0).reg(); | 505 Register result = locs()->out(0).reg(); |
| 503 Label done; | 506 Label done; |
| 504 __ Bind(&is_false); | 507 __ Bind(&is_false); |
| 505 __ LoadObject(result, Bool::False(), PP); | 508 __ LoadObject(result, Bool::False(), PP); |
| 506 __ b(&done); | 509 __ b(&done); |
| 507 __ Bind(&is_true); | 510 __ Bind(&is_true); |
| 508 __ LoadObject(result, Bool::True(), PP); | 511 __ LoadObject(result, Bool::True(), PP); |
| 509 __ Bind(&done); | 512 __ Bind(&done); |
| 510 } | 513 } |
| 511 | 514 |
| 512 | 515 |
| 513 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 516 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 514 BranchInstr* branch) { | 517 BranchInstr* branch) { |
| 515 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 518 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 516 | 519 |
| 517 BranchLabels labels = compiler->CreateBranchLabels(branch); | 520 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 518 Condition true_condition = EmitComparisonCode(compiler, labels); | 521 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 522 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 523 // Special case for NaN comparison. Result is always false unless |
| 524 // relational operator is !=. |
| 525 __ b(labels.false_label, VS); |
| 526 } |
| 519 EmitBranchOnCondition(compiler, true_condition, labels); | 527 EmitBranchOnCondition(compiler, true_condition, labels); |
| 520 } | 528 } |
| 521 | 529 |
| 522 | 530 |
| 523 LocationSummary* TestSmiInstr::MakeLocationSummary(bool opt) const { | 531 LocationSummary* TestSmiInstr::MakeLocationSummary(bool opt) const { |
| 524 const intptr_t kNumInputs = 2; | 532 const intptr_t kNumInputs = 2; |
| 525 const intptr_t kNumTemps = 0; | 533 const intptr_t kNumTemps = 0; |
| 526 LocationSummary* locs = | 534 LocationSummary* locs = |
| 527 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 535 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 528 locs->set_in(0, Location::RequiresRegister()); | 536 locs->set_in(0, Location::RequiresRegister()); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 ASSERT(operation_cid() == kDoubleCid); | 679 ASSERT(operation_cid() == kDoubleCid); |
| 672 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 680 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 673 } | 681 } |
| 674 } | 682 } |
| 675 | 683 |
| 676 | 684 |
| 677 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 685 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 678 Label is_true, is_false; | 686 Label is_true, is_false; |
| 679 BranchLabels labels = { &is_true, &is_false, &is_false }; | 687 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 680 Condition true_condition = EmitComparisonCode(compiler, labels); | 688 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 689 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 690 // Special case for NaN comparison. Result is always false unless |
| 691 // relational operator is !=. |
| 692 __ b(&is_false, VS); |
| 693 } |
| 681 EmitBranchOnCondition(compiler, true_condition, labels); | 694 EmitBranchOnCondition(compiler, true_condition, labels); |
| 682 // TODO(zra): instead of branching, use the csel instruction to get | 695 // TODO(zra): instead of branching, use the csel instruction to get |
| 683 // True or False into result. | 696 // True or False into result. |
| 684 Register result = locs()->out(0).reg(); | 697 Register result = locs()->out(0).reg(); |
| 685 Label done; | 698 Label done; |
| 686 __ Bind(&is_false); | 699 __ Bind(&is_false); |
| 687 __ LoadObject(result, Bool::False(), PP); | 700 __ LoadObject(result, Bool::False(), PP); |
| 688 __ b(&done); | 701 __ b(&done); |
| 689 __ Bind(&is_true); | 702 __ Bind(&is_true); |
| 690 __ LoadObject(result, Bool::True(), PP); | 703 __ LoadObject(result, Bool::True(), PP); |
| 691 __ Bind(&done); | 704 __ Bind(&done); |
| 692 } | 705 } |
| 693 | 706 |
| 694 | 707 |
| 695 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 708 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 696 BranchInstr* branch) { | 709 BranchInstr* branch) { |
| 697 BranchLabels labels = compiler->CreateBranchLabels(branch); | 710 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 698 Condition true_condition = EmitComparisonCode(compiler, labels); | 711 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 712 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 713 // Special case for NaN comparison. Result is always false unless |
| 714 // relational operator is !=. |
| 715 __ b(labels.false_label, VS); |
| 716 } |
| 699 EmitBranchOnCondition(compiler, true_condition, labels); | 717 EmitBranchOnCondition(compiler, true_condition, labels); |
| 700 } | 718 } |
| 701 | 719 |
| 702 | 720 |
| 703 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { | 721 LocationSummary* NativeCallInstr::MakeLocationSummary(bool opt) const { |
| 704 const intptr_t kNumInputs = 0; | 722 const intptr_t kNumInputs = 0; |
| 705 const intptr_t kNumTemps = 3; | 723 const intptr_t kNumTemps = 3; |
| 706 LocationSummary* locs = | 724 LocationSummary* locs = |
| 707 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 725 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 708 locs->set_temp(0, Location::RegisterLocation(R1)); | 726 locs->set_temp(0, Location::RegisterLocation(R1)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 // TODO(fschneider): Allow immediate operands for the char code. | 784 // TODO(fschneider): Allow immediate operands for the char code. |
| 767 return LocationSummary::Make(kNumInputs, | 785 return LocationSummary::Make(kNumInputs, |
| 768 Location::RequiresRegister(), | 786 Location::RequiresRegister(), |
| 769 LocationSummary::kNoCall); | 787 LocationSummary::kNoCall); |
| 770 } | 788 } |
| 771 | 789 |
| 772 | 790 |
| 773 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 791 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 774 const Register char_code = locs()->in(0).reg(); | 792 const Register char_code = locs()->in(0).reg(); |
| 775 const Register result = locs()->out(0).reg(); | 793 const Register result = locs()->out(0).reg(); |
| 776 __ LoadImmediate(result, | 794 __ LoadImmediate( |
| 777 reinterpret_cast<uword>(Symbols::PredefinedAddress()), PP); | 795 result, reinterpret_cast<uword>(Symbols::PredefinedAddress()), PP); |
| 778 __ AddImmediate( | 796 __ AddImmediate( |
| 779 result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize, PP); | 797 result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize, PP); |
| 780 __ Asr(TMP, char_code, kSmiTagShift); // Untag to use scaled adress mode. | 798 __ Asr(TMP, char_code, kSmiTagShift); // Untag to use scaled adress mode. |
| 781 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); | 799 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); |
| 782 } | 800 } |
| 783 | 801 |
| 784 | 802 |
| 785 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { | 803 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(bool opt) const { |
| 786 const intptr_t kNumInputs = 1; | 804 const intptr_t kNumInputs = 1; |
| 787 return LocationSummary::Make(kNumInputs, | 805 return LocationSummary::Make(kNumInputs, |
| (...skipping 2044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2832 // sarl operation masks the count to 6 bits. | 2850 // sarl operation masks the count to 6 bits. |
| 2833 const intptr_t kCountLimit = 0x3F; | 2851 const intptr_t kCountLimit = 0x3F; |
| 2834 if ((right_range == NULL) || | 2852 if ((right_range == NULL) || |
| 2835 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2853 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2836 __ LoadImmediate(TMP2, kCountLimit, PP); | 2854 __ LoadImmediate(TMP2, kCountLimit, PP); |
| 2837 __ CompareRegisters(TMP, TMP2); | 2855 __ CompareRegisters(TMP, TMP2); |
| 2838 __ csel(TMP, TMP2, TMP, GT); | 2856 __ csel(TMP, TMP2, TMP, GT); |
| 2839 } | 2857 } |
| 2840 Register temp = locs()->temp(0).reg(); | 2858 Register temp = locs()->temp(0).reg(); |
| 2841 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 2859 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. |
| 2842 __ Asr(result, temp, TMP); | 2860 __ asrv(result, temp, TMP); |
| 2843 __ SmiTag(result); | 2861 __ SmiTag(result); |
| 2844 break; | 2862 break; |
| 2845 } | 2863 } |
| 2846 case Token::kDIV: { | 2864 case Token::kDIV: { |
| 2847 // Dispatches to 'Double./'. | 2865 // Dispatches to 'Double./'. |
| 2848 // TODO(srdjan): Implement as conversion to double and double division. | 2866 // TODO(srdjan): Implement as conversion to double and double division. |
| 2849 UNREACHABLE(); | 2867 UNREACHABLE(); |
| 2850 break; | 2868 break; |
| 2851 } | 2869 } |
| 2852 case Token::kOR: | 2870 case Token::kOR: |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3689 LocationSummary* locs = instr->locs(); | 3707 LocationSummary* locs = instr->locs(); |
| 3690 | 3708 |
| 3691 const VRegister base = locs->in(0).fpu_reg(); | 3709 const VRegister base = locs->in(0).fpu_reg(); |
| 3692 const VRegister exp = locs->in(1).fpu_reg(); | 3710 const VRegister exp = locs->in(1).fpu_reg(); |
| 3693 const VRegister result = locs->out(0).fpu_reg(); | 3711 const VRegister result = locs->out(0).fpu_reg(); |
| 3694 const VRegister saved_base = locs->temp(0).fpu_reg(); | 3712 const VRegister saved_base = locs->temp(0).fpu_reg(); |
| 3695 ASSERT((base == result) && (result != saved_base)); | 3713 ASSERT((base == result) && (result != saved_base)); |
| 3696 | 3714 |
| 3697 Label skip_call, try_sqrt, check_base, return_nan, do_pow; | 3715 Label skip_call, try_sqrt, check_base, return_nan, do_pow; |
| 3698 __ fmovdd(saved_base, base); | 3716 __ fmovdd(saved_base, base); |
| 3699 __ b(&do_pow); | |
| 3700 __ LoadDImmediate(result, 1.0, PP); | 3717 __ LoadDImmediate(result, 1.0, PP); |
| 3701 // exponent == 0.0 -> return 1.0; | 3718 // exponent == 0.0 -> return 1.0; |
| 3702 __ fcmpdz(exp); | 3719 __ fcmpdz(exp); |
| 3703 __ b(&check_base, VS); // NaN -> check base. | 3720 __ b(&check_base, VS); // NaN -> check base. |
| 3704 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | 3721 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
| 3705 | 3722 |
| 3706 // exponent == 1.0 ? | 3723 // exponent == 1.0 ? |
| 3707 __ fcmpd(exp, result); | 3724 __ fcmpd(exp, result); |
| 3708 Label return_base; | 3725 Label return_base; |
| 3709 __ b(&return_base, EQ); | 3726 __ b(&return_base, EQ); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3755 // base == -Infinity -> call pow; | 3772 // base == -Infinity -> call pow; |
| 3756 __ fcmpd(saved_base, result); | 3773 __ fcmpd(saved_base, result); |
| 3757 __ b(&do_pow, EQ); | 3774 __ b(&do_pow, EQ); |
| 3758 | 3775 |
| 3759 // exponent == 0.5 ? | 3776 // exponent == 0.5 ? |
| 3760 __ LoadDImmediate(result, 0.5, PP); | 3777 __ LoadDImmediate(result, 0.5, PP); |
| 3761 __ fcmpd(exp, result); | 3778 __ fcmpd(exp, result); |
| 3762 __ b(&do_pow, NE); | 3779 __ b(&do_pow, NE); |
| 3763 | 3780 |
| 3764 // base == 0 -> return 0; | 3781 // base == 0 -> return 0; |
| 3765 __ fcmpdz(base); | 3782 __ fcmpdz(saved_base); |
| 3766 __ b(&return_zero, EQ); | 3783 __ b(&return_zero, EQ); |
| 3767 | 3784 |
| 3768 __ fsqrtd(result, saved_base); | 3785 __ fsqrtd(result, saved_base); |
| 3769 __ b(&skip_call); | 3786 __ b(&skip_call); |
| 3770 | 3787 |
| 3771 __ Bind(&return_zero); | 3788 __ Bind(&return_zero); |
| 3772 __ LoadDImmediate(result, 0.0, PP); | 3789 __ LoadDImmediate(result, 0.0, PP); |
| 3773 __ b(&skip_call); | 3790 __ b(&skip_call); |
| 3774 | 3791 |
| 3775 __ Bind(&do_pow); | 3792 __ Bind(&do_pow); |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4359 compiler->GenerateCall(token_pos(), | 4376 compiler->GenerateCall(token_pos(), |
| 4360 &label, | 4377 &label, |
| 4361 PcDescriptors::kOther, | 4378 PcDescriptors::kOther, |
| 4362 locs()); | 4379 locs()); |
| 4363 __ Drop(ArgumentCount()); // Discard arguments. | 4380 __ Drop(ArgumentCount()); // Discard arguments. |
| 4364 } | 4381 } |
| 4365 | 4382 |
| 4366 } // namespace dart | 4383 } // namespace dart |
| 4367 | 4384 |
| 4368 #endif // defined TARGET_ARCH_ARM64 | 4385 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |