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 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
563 // Compare lower. | 563 // Compare lower. |
564 __ cmp(left_lo, Operand(right_lo)); | 564 __ cmp(left_lo, Operand(right_lo)); |
565 // Compare upper if lower is equal. | 565 // Compare upper if lower is equal. |
566 __ cmp(left_hi, Operand(right_hi), EQ); | 566 __ cmp(left_hi, Operand(right_hi), EQ); |
567 return TokenKindToMintCondition(kind); | 567 return TokenKindToMintCondition(kind); |
568 } | 568 } |
569 | 569 |
570 | 570 |
571 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 571 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
572 LocationSummary* locs, | 572 LocationSummary* locs, |
573 Token::Kind kind) { | 573 Token::Kind kind, |
574 BranchLabels labels) { | |
574 PairLocation* left_pair = locs->in(0).AsPairLocation(); | 575 PairLocation* left_pair = locs->in(0).AsPairLocation(); |
575 Register left_lo = left_pair->At(0).reg(); | 576 Register left_lo = left_pair->At(0).reg(); |
576 Register left_hi = left_pair->At(1).reg(); | 577 Register left_hi = left_pair->At(1).reg(); |
577 PairLocation* right_pair = locs->in(1).AsPairLocation(); | 578 PairLocation* right_pair = locs->in(1).AsPairLocation(); |
578 Register right_lo = right_pair->At(0).reg(); | 579 Register right_lo = right_pair->At(0).reg(); |
579 Register right_hi = right_pair->At(1).reg(); | 580 Register right_hi = right_pair->At(1).reg(); |
580 | 581 |
581 Register out = locs->temp(0).reg(); | 582 // 64-bit comparison. |
582 | 583 Condition hi_cond, lo_cond; |
583 // 64-bit comparison | |
584 Condition hi_true_cond, hi_false_cond, lo_false_cond; | |
585 switch (kind) { | 584 switch (kind) { |
586 case Token::kLT: | 585 case Token::kLT: |
587 case Token::kLTE: | 586 hi_cond = LT; |
588 hi_true_cond = LT; | 587 lo_cond = CC; |
589 hi_false_cond = GT; | |
590 lo_false_cond = (kind == Token::kLT) ? CS : HI; | |
591 break; | 588 break; |
592 case Token::kGT: | 589 case Token::kGT: |
590 hi_cond = GT; | |
591 lo_cond = HI; | |
592 break; | |
593 case Token::kLTE: | |
594 hi_cond = LT; | |
595 lo_cond = LS; | |
596 break; | |
593 case Token::kGTE: | 597 case Token::kGTE: |
594 hi_true_cond = GT; | 598 hi_cond = GT; |
595 hi_false_cond = LT; | 599 lo_cond = CS; |
596 lo_false_cond = (kind == Token::kGT) ? LS : CC; | |
597 break; | 600 break; |
598 default: | 601 default: |
599 UNREACHABLE(); | 602 UNREACHABLE(); |
600 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 603 hi_cond = lo_cond = VS; |
601 } | 604 } |
602 | |
603 Label done; | |
604 // Compare upper halves first. | 605 // Compare upper halves first. |
605 __ cmp(left_hi, Operand(right_hi)); | 606 __ cmp(left_hi, Operand(right_hi)); |
606 __ LoadImmediate(out, 0, hi_false_cond); | 607 __ b(labels.true_label, hi_cond); |
607 __ LoadImmediate(out, 1, hi_true_cond); | 608 __ b(labels.false_label, FlipCondition(hi_cond)); |
608 // If higher words aren't equal, skip comparing lower words. | |
609 __ b(&done, NE); | |
610 | 609 |
610 // If higher words are equal, compare lower words. | |
611 __ cmp(left_lo, Operand(right_lo)); | 611 __ cmp(left_lo, Operand(right_lo)); |
zra
2014/12/01 21:18:18
Do you need to branch to a label here? Maybe we ne
regis
2014/12/01 22:19:51
No, we only return the condition. The branch itsel
zra
2014/12/01 22:34:47
Ah, I see =) Didn't notice the call to EmitBranchO
regis
2014/12/01 22:44:00
I prefer to leave the code in sync with other plat
| |
612 __ LoadImmediate(out, 1); | 612 return lo_cond; |
613 __ LoadImmediate(out, 0, lo_false_cond); | |
614 __ Bind(&done); | |
615 | |
616 return NegateCondition(lo_false_cond); | |
617 } | 613 } |
618 | 614 |
619 | 615 |
620 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 616 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
621 switch (kind) { | 617 switch (kind) { |
622 case Token::kEQ: return EQ; | 618 case Token::kEQ: return EQ; |
623 case Token::kNE: return NE; | 619 case Token::kNE: return NE; |
624 case Token::kLT: return LT; | 620 case Token::kLT: return LT; |
625 case Token::kGT: return GT; | 621 case Token::kGT: return GT; |
626 case Token::kLTE: return LE; | 622 case Token::kLTE: return LE; |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
815 __ LoadObject(result_reg, Bool::True()); | 811 __ LoadObject(result_reg, Bool::True()); |
816 __ Bind(&done); | 812 __ Bind(&done); |
817 } | 813 } |
818 | 814 |
819 | 815 |
820 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, | 816 LocationSummary* RelationalOpInstr::MakeLocationSummary(Isolate* isolate, |
821 bool opt) const { | 817 bool opt) const { |
822 const intptr_t kNumInputs = 2; | 818 const intptr_t kNumInputs = 2; |
823 const intptr_t kNumTemps = 0; | 819 const intptr_t kNumTemps = 0; |
824 if (operation_cid() == kMintCid) { | 820 if (operation_cid() == kMintCid) { |
825 const intptr_t kNumTemps = 1; | 821 const intptr_t kNumTemps = 0; |
826 LocationSummary* locs = new(isolate) LocationSummary( | 822 LocationSummary* locs = new(isolate) LocationSummary( |
827 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 823 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
828 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 824 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
829 Location::RequiresRegister())); | 825 Location::RequiresRegister())); |
830 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 826 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
831 Location::RequiresRegister())); | 827 Location::RequiresRegister())); |
832 locs->set_temp(0, Location::RequiresRegister()); // TODO(regis): Improve. | |
833 locs->set_out(0, Location::RequiresRegister()); | 828 locs->set_out(0, Location::RequiresRegister()); |
834 return locs; | 829 return locs; |
835 } | 830 } |
836 if (operation_cid() == kDoubleCid) { | 831 if (operation_cid() == kDoubleCid) { |
837 LocationSummary* summary = new(isolate) LocationSummary( | 832 LocationSummary* summary = new(isolate) LocationSummary( |
838 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 833 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
839 summary->set_in(0, Location::RequiresFpuRegister()); | 834 summary->set_in(0, Location::RequiresFpuRegister()); |
840 summary->set_in(1, Location::RequiresFpuRegister()); | 835 summary->set_in(1, Location::RequiresFpuRegister()); |
841 summary->set_out(0, Location::RequiresRegister()); | 836 summary->set_out(0, Location::RequiresRegister()); |
842 return summary; | 837 return summary; |
(...skipping 10 matching lines...) Expand all Loading... | |
853 summary->set_out(0, Location::RequiresRegister()); | 848 summary->set_out(0, Location::RequiresRegister()); |
854 return summary; | 849 return summary; |
855 } | 850 } |
856 | 851 |
857 | 852 |
858 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 853 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
859 BranchLabels labels) { | 854 BranchLabels labels) { |
860 if (operation_cid() == kSmiCid) { | 855 if (operation_cid() == kSmiCid) { |
861 return EmitSmiComparisonOp(compiler, locs(), kind()); | 856 return EmitSmiComparisonOp(compiler, locs(), kind()); |
862 } else if (operation_cid() == kMintCid) { | 857 } else if (operation_cid() == kMintCid) { |
863 return EmitUnboxedMintComparisonOp(compiler, locs(), kind()); | 858 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); |
864 } else { | 859 } else { |
865 ASSERT(operation_cid() == kDoubleCid); | 860 ASSERT(operation_cid() == kDoubleCid); |
866 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 861 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
867 } | 862 } |
868 } | 863 } |
869 | 864 |
870 | 865 |
871 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 866 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
872 // The ARM code does not use true- and false-labels here. | 867 Label is_true, is_false; |
873 BranchLabels labels = { NULL, NULL, NULL }; | 868 BranchLabels labels = { &is_true, &is_false, &is_false }; |
874 Condition true_condition = EmitComparisonCode(compiler, labels); | 869 Condition true_condition = EmitComparisonCode(compiler, labels); |
875 | 870 |
876 const Register result = locs()->out(0).reg(); | 871 const Register result = locs()->out(0).reg(); |
877 if (operation_cid() == kSmiCid) { | 872 if (operation_cid() == kSmiCid) { |
878 __ LoadObject(result, Bool::True(), true_condition); | 873 __ LoadObject(result, Bool::True(), true_condition); |
879 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 874 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
880 } else if (operation_cid() == kMintCid) { | 875 } else if (operation_cid() == kMintCid) { |
881 const Register cr = locs()->temp(0).reg(); | 876 EmitBranchOnCondition(compiler, true_condition, labels); |
877 Label done; | |
878 __ Bind(&is_false); | |
879 __ LoadObject(result, Bool::False()); | |
880 __ b(&done); | |
881 __ Bind(&is_true); | |
882 __ LoadObject(result, Bool::True()); | 882 __ LoadObject(result, Bool::True()); |
883 __ CompareImmediate(cr, 1); | 883 __ Bind(&done); |
884 __ LoadObject(result, Bool::False(), NE); | |
885 } else { | 884 } else { |
886 ASSERT(operation_cid() == kDoubleCid); | 885 ASSERT(operation_cid() == kDoubleCid); |
887 Label done; | 886 Label done; |
888 __ LoadObject(result, Bool::False()); | 887 __ LoadObject(result, Bool::False()); |
889 if (true_condition != NE) { | 888 if (true_condition != NE) { |
890 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 889 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
891 } | 890 } |
892 __ LoadObject(result, Bool::True(), true_condition); | 891 __ LoadObject(result, Bool::True(), true_condition); |
893 __ Bind(&done); | 892 __ Bind(&done); |
894 } | 893 } |
895 } | 894 } |
896 | 895 |
897 | 896 |
898 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 897 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
899 BranchInstr* branch) { | 898 BranchInstr* branch) { |
900 BranchLabels labels = compiler->CreateBranchLabels(branch); | 899 BranchLabels labels = compiler->CreateBranchLabels(branch); |
901 Condition true_condition = EmitComparisonCode(compiler, labels); | 900 Condition true_condition = EmitComparisonCode(compiler, labels); |
902 | 901 |
903 if (operation_cid() == kSmiCid) { | 902 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
904 EmitBranchOnCondition(compiler, true_condition, labels); | 903 EmitBranchOnCondition(compiler, true_condition, labels); |
905 } else if (operation_cid() == kMintCid) { | |
906 const Register result = locs()->temp(0).reg(); // TODO(regis): Improve. | |
907 __ CompareImmediate(result, 1); | |
908 __ b(labels.true_label, EQ); | |
909 __ b(labels.false_label, NE); | |
910 } else if (operation_cid() == kDoubleCid) { | 904 } else if (operation_cid() == kDoubleCid) { |
911 Label* nan_result = (true_condition == NE) ? | 905 Label* nan_result = (true_condition == NE) ? |
912 labels.true_label : labels.false_label; | 906 labels.true_label : labels.false_label; |
913 __ b(nan_result, VS); | 907 __ b(nan_result, VS); |
914 EmitBranchOnCondition(compiler, true_condition, labels); | 908 EmitBranchOnCondition(compiler, true_condition, labels); |
915 } | 909 } |
916 } | 910 } |
917 | 911 |
918 | 912 |
919 LocationSummary* NativeCallInstr::MakeLocationSummary(Isolate* isolate, | 913 LocationSummary* NativeCallInstr::MakeLocationSummary(Isolate* isolate, |
(...skipping 5983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6903 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6897 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
6904 #if defined(DEBUG) | 6898 #if defined(DEBUG) |
6905 __ LoadImmediate(R4, kInvalidObjectPointer); | 6899 __ LoadImmediate(R4, kInvalidObjectPointer); |
6906 __ LoadImmediate(R5, kInvalidObjectPointer); | 6900 __ LoadImmediate(R5, kInvalidObjectPointer); |
6907 #endif | 6901 #endif |
6908 } | 6902 } |
6909 | 6903 |
6910 } // namespace dart | 6904 } // namespace dart |
6911 | 6905 |
6912 #endif // defined TARGET_ARCH_ARM | 6906 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |