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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
9 | 9 |
10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 __ BranchNotEqual(CMPRES1, Immediate(kMintCid), not_smi_or_mint); | 678 __ BranchNotEqual(CMPRES1, Immediate(kMintCid), not_smi_or_mint); |
679 | 679 |
680 // Mint. | 680 // Mint. |
681 __ lw(res_lo, FieldAddress(reg, Mint::value_offset())); | 681 __ lw(res_lo, FieldAddress(reg, Mint::value_offset())); |
682 __ lw(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize)); | 682 __ lw(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize)); |
683 __ Bind(&done); | 683 __ Bind(&done); |
684 return; | 684 return; |
685 } | 685 } |
686 | 686 |
687 | 687 |
688 static void CompareIntegers(Assembler* assembler, Condition true_condition) { | 688 static void CompareIntegers(Assembler* assembler, RelationOperator rel_op) { |
689 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; | 689 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; |
690 TestBothArgumentsSmis(assembler, &try_mint_smi); | 690 TestBothArgumentsSmis(assembler, &try_mint_smi); |
691 // T0 contains the right argument. T1 contains left argument | 691 // T0 contains the right argument. T1 contains left argument |
692 | 692 |
693 switch (true_condition) { | 693 switch (rel_op) { |
694 case LT: __ BranchSignedLess(T1, T0, &is_true); break; | 694 case LT: __ BranchSignedLess(T1, T0, &is_true); break; |
695 case LE: __ BranchSignedLessEqual(T1, T0, &is_true); break; | 695 case LE: __ BranchSignedLessEqual(T1, T0, &is_true); break; |
696 case GT: __ BranchSignedGreater(T1, T0, &is_true); break; | 696 case GT: __ BranchSignedGreater(T1, T0, &is_true); break; |
697 case GE: __ BranchSignedGreaterEqual(T1, T0, &is_true); break; | 697 case GE: __ BranchSignedGreaterEqual(T1, T0, &is_true); break; |
698 default: | 698 default: |
699 UNREACHABLE(); | 699 UNREACHABLE(); |
700 break; | 700 break; |
701 } | 701 } |
702 | 702 |
703 __ Bind(&is_false); | 703 __ Bind(&is_false); |
704 __ LoadObject(V0, Bool::False()); | 704 __ LoadObject(V0, Bool::False()); |
705 __ Ret(); | 705 __ Ret(); |
706 __ Bind(&is_true); | 706 __ Bind(&is_true); |
707 __ LoadObject(V0, Bool::True()); | 707 __ LoadObject(V0, Bool::True()); |
708 __ Ret(); | 708 __ Ret(); |
709 | 709 |
710 __ Bind(&try_mint_smi); | 710 __ Bind(&try_mint_smi); |
711 // Get left as 64 bit integer. | 711 // Get left as 64 bit integer. |
712 Get64SmiOrMint(assembler, T3, T2, T1, &fall_through); | 712 Get64SmiOrMint(assembler, T3, T2, T1, &fall_through); |
713 // Get right as 64 bit integer. | 713 // Get right as 64 bit integer. |
714 Get64SmiOrMint(assembler, T5, T4, T0, &fall_through); | 714 Get64SmiOrMint(assembler, T5, T4, T0, &fall_through); |
715 // T3: left high. | 715 // T3: left high. |
716 // T2: left low. | 716 // T2: left low. |
717 // T5: right high. | 717 // T5: right high. |
718 // T4: right low. | 718 // T4: right low. |
719 | 719 |
720 // 64-bit comparison | 720 // 64-bit comparison |
721 // Condition hi_true_cond, hi_false_cond, lo_false_cond; | 721 switch (rel_op) { |
722 switch (true_condition) { | |
723 case LT: | 722 case LT: |
724 case LE: { | 723 case LE: { |
725 // Compare left hi, right high. | 724 // Compare left hi, right high. |
726 __ BranchSignedGreater(T3, T5, &is_false); | 725 __ BranchSignedGreater(T3, T5, &is_false); |
727 __ BranchSignedLess(T3, T5, &is_true); | 726 __ BranchSignedLess(T3, T5, &is_true); |
728 // Compare left lo, right lo. | 727 // Compare left lo, right lo. |
729 if (true_condition == LT) { | 728 if (rel_op == LT) { |
730 __ BranchUnsignedGreaterEqual(T2, T4, &is_false); | 729 __ BranchUnsignedGreaterEqual(T2, T4, &is_false); |
731 } else { | 730 } else { |
732 __ BranchUnsignedGreater(T2, T4, &is_false); | 731 __ BranchUnsignedGreater(T2, T4, &is_false); |
733 } | 732 } |
734 break; | 733 break; |
735 } | 734 } |
736 case GT: | 735 case GT: |
737 case GE: { | 736 case GE: { |
738 // Compare left hi, right high. | 737 // Compare left hi, right high. |
739 __ BranchSignedLess(T3, T5, &is_false); | 738 __ BranchSignedLess(T3, T5, &is_false); |
740 __ BranchSignedGreater(T3, T5, &is_true); | 739 __ BranchSignedGreater(T3, T5, &is_true); |
741 // Compare left lo, right lo. | 740 // Compare left lo, right lo. |
742 if (true_condition == GT) { | 741 if (rel_op == GT) { |
743 __ BranchUnsignedLessEqual(T2, T4, &is_false); | 742 __ BranchUnsignedLessEqual(T2, T4, &is_false); |
744 } else { | 743 } else { |
745 __ BranchUnsignedLess(T2, T4, &is_false); | 744 __ BranchUnsignedLess(T2, T4, &is_false); |
746 } | 745 } |
747 break; | 746 break; |
748 } | 747 } |
749 default: | 748 default: |
750 UNREACHABLE(); | 749 UNREACHABLE(); |
751 break; | 750 break; |
752 } | 751 } |
753 // Else is true. | 752 // Else is true. |
754 __ b(&is_true); | 753 __ b(&is_true); |
755 | 754 |
756 __ Bind(&fall_through); | 755 __ Bind(&fall_through); |
757 } | 756 } |
758 | 757 |
759 | 758 |
760 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { | 759 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { |
761 CompareIntegers(assembler, LT); | 760 CompareIntegers(assembler, LT); |
762 } | 761 } |
763 | 762 |
764 | 763 |
765 void Intrinsifier::Integer_lessThan(Assembler* assembler) { | 764 void Intrinsifier::Integer_lessThan(Assembler* assembler) { |
766 Integer_greaterThanFromInt(assembler); | 765 CompareIntegers(assembler, LT); |
767 } | 766 } |
768 | 767 |
769 | 768 |
770 void Intrinsifier::Integer_greaterThan(Assembler* assembler) { | 769 void Intrinsifier::Integer_greaterThan(Assembler* assembler) { |
771 CompareIntegers(assembler, GT); | 770 CompareIntegers(assembler, GT); |
772 } | 771 } |
773 | 772 |
774 | 773 |
775 void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { | 774 void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { |
776 CompareIntegers(assembler, LE); | 775 CompareIntegers(assembler, LE); |
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 __ LoadClassId(CMPRES1, T0); | 1336 __ LoadClassId(CMPRES1, T0); |
1338 __ BranchNotEqual(CMPRES1, Immediate(kDoubleCid), not_double_smi); | 1337 __ BranchNotEqual(CMPRES1, Immediate(kDoubleCid), not_double_smi); |
1339 // Fall through with Double in T0. | 1338 // Fall through with Double in T0. |
1340 } | 1339 } |
1341 | 1340 |
1342 | 1341 |
1343 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown | 1342 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown |
1344 // type. Return true or false object in the register V0. Any NaN argument | 1343 // type. Return true or false object in the register V0. Any NaN argument |
1345 // returns false. Any non-double arg1 causes control flow to fall through to the | 1344 // returns false. Any non-double arg1 causes control flow to fall through to the |
1346 // slow case (compiled method body). | 1345 // slow case (compiled method body). |
1347 static void CompareDoubles(Assembler* assembler, Condition true_condition) { | 1346 static void CompareDoubles(Assembler* assembler, RelationOperator rel_op) { |
1348 Label is_smi, double_op, no_NaN, fall_through; | 1347 Label is_smi, double_op, no_NaN, fall_through; |
1349 __ Comment("CompareDoubles Intrinsic"); | 1348 __ Comment("CompareDoubles Intrinsic"); |
1350 | 1349 |
1351 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1350 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
1352 // Both arguments are double, right operand is in T0. | 1351 // Both arguments are double, right operand is in T0. |
1353 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); | 1352 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); |
1354 __ Bind(&double_op); | 1353 __ Bind(&double_op); |
1355 __ lw(T0, Address(SP, 1 * kWordSize)); // Left argument. | 1354 __ lw(T0, Address(SP, 1 * kWordSize)); // Left argument. |
1356 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); | 1355 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); |
1357 // Now, left is in D0, right is in D1. | 1356 // Now, left is in D0, right is in D1. |
1358 | 1357 |
1359 __ cund(D0, D1); // Check for NaN. | 1358 __ cund(D0, D1); // Check for NaN. |
1360 __ bc1f(&no_NaN); | 1359 __ bc1f(&no_NaN); |
1361 __ LoadObject(V0, Bool::False()); // Return false if either is NaN. | 1360 __ LoadObject(V0, Bool::False()); // Return false if either is NaN. |
1362 __ Ret(); | 1361 __ Ret(); |
1363 __ Bind(&no_NaN); | 1362 __ Bind(&no_NaN); |
1364 | 1363 |
1365 switch (true_condition) { | 1364 switch (rel_op) { |
1366 case EQ: __ ceqd(D0, D1); break; | 1365 case EQ: __ ceqd(D0, D1); break; |
1367 case LT: __ coltd(D0, D1); break; | 1366 case LT: __ coltd(D0, D1); break; |
1368 case LE: __ coled(D0, D1); break; | 1367 case LE: __ coled(D0, D1); break; |
1369 case GT: __ coltd(D1, D0); break; | 1368 case GT: __ coltd(D1, D0); break; |
1370 case GE: __ coled(D1, D0); break; | 1369 case GE: __ coled(D1, D0); break; |
1371 default: { | 1370 default: { |
1372 // Only passing the above conditions to this function. | 1371 // Only passing the above conditions to this function. |
1373 UNREACHABLE(); | 1372 UNREACHABLE(); |
1374 break; | 1373 break; |
1375 } | 1374 } |
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2140 Isolate* isolate = Isolate::Current(); | 2139 Isolate* isolate = Isolate::Current(); |
2141 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); | 2140 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); |
2142 // Set return value. | 2141 // Set return value. |
2143 __ Ret(); | 2142 __ Ret(); |
2144 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); | 2143 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); |
2145 } | 2144 } |
2146 | 2145 |
2147 } // namespace dart | 2146 } // namespace dart |
2148 | 2147 |
2149 #endif // defined TARGET_ARCH_MIPS | 2148 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |