| 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 |