| 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 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 __ beq(T2, T7, &checked_ok); | 206 __ beq(T2, T7, &checked_ok); |
| 207 | 207 |
| 208 __ lw(T1, Address(SP, 2 * kWordSize)); // Array. | 208 __ lw(T1, Address(SP, 2 * kWordSize)); // Array. |
| 209 __ lw(T1, FieldAddress(T1, type_args_field_offset)); | 209 __ lw(T1, FieldAddress(T1, type_args_field_offset)); |
| 210 | 210 |
| 211 // T1: Type arguments of array. | 211 // T1: Type arguments of array. |
| 212 __ beq(T1, T7, &checked_ok); | 212 __ beq(T1, T7, &checked_ok); |
| 213 | 213 |
| 214 // Check if it's dynamic. | 214 // Check if it's dynamic. |
| 215 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. | 215 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. |
| 216 __ LoadClassId(TMP, T1); | 216 __ LoadClassId(CMPRES1, T1); |
| 217 __ BranchNotEqual(TMP, kTypeArgumentsCid, &fall_through); | 217 __ BranchNotEqual(CMPRES1, kTypeArgumentsCid, &fall_through); |
| 218 | 218 |
| 219 // Get type at index 0. | 219 // Get type at index 0. |
| 220 __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0))); | 220 __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0))); |
| 221 __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok); | 221 __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok); |
| 222 | 222 |
| 223 // Check for int and num. | 223 // Check for int and num. |
| 224 __ andi(CMPRES, T2, Immediate(kSmiTagMask)); | 224 __ andi(CMPRES, T2, Immediate(kSmiTagMask)); |
| 225 __ bne(CMPRES, ZR, &fall_through); // Non-smi value. | 225 __ bne(CMPRES, ZR, &fall_through); // Non-smi value. |
| 226 | 226 |
| 227 __ BranchEqual(T0, Type::ZoneHandle(Type::IntType()), &checked_ok); | 227 __ BranchEqual(T0, Type::ZoneHandle(Type::IntType()), &checked_ok); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 // On stack: growable array (+1), data (+0). | 417 // On stack: growable array (+1), data (+0). |
| 418 bool Intrinsifier::GrowableArray_setData(Assembler* assembler) { | 418 bool Intrinsifier::GrowableArray_setData(Assembler* assembler) { |
| 419 if (FLAG_enable_type_checks) { | 419 if (FLAG_enable_type_checks) { |
| 420 return false; | 420 return false; |
| 421 } | 421 } |
| 422 Label fall_through; | 422 Label fall_through; |
| 423 __ lw(T1, Address(SP, 0 * kWordSize)); // Data. | 423 __ lw(T1, Address(SP, 0 * kWordSize)); // Data. |
| 424 // Check that data is an ObjectArray. | 424 // Check that data is an ObjectArray. |
| 425 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); | 425 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |
| 426 __ beq(CMPRES, ZR, &fall_through); // Data is Smi. | 426 __ beq(CMPRES, ZR, &fall_through); // Data is Smi. |
| 427 __ LoadClassId(TMP, T1); | 427 __ LoadClassId(CMPRES1, T1); |
| 428 __ BranchNotEqual(TMP, kArrayCid, &fall_through); | 428 __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through); |
| 429 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array. | 429 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array. |
| 430 __ StoreIntoObject(T0, | 430 __ StoreIntoObject(T0, |
| 431 FieldAddress(T0, GrowableObjectArray::data_offset()), | 431 FieldAddress(T0, GrowableObjectArray::data_offset()), |
| 432 T1); | 432 T1); |
| 433 __ Ret(); | 433 __ Ret(); |
| 434 __ Bind(&fall_through); | 434 __ Bind(&fall_through); |
| 435 return false; | 435 return false; |
| 436 } | 436 } |
| 437 | 437 |
| 438 | 438 |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 858 ASSERT(kSmiTag == 0); | 858 ASSERT(kSmiTag == 0); |
| 859 Label fall_through, overflow; | 859 Label fall_through, overflow; |
| 860 | 860 |
| 861 TestBothArgumentsSmis(assembler, &fall_through); | 861 TestBothArgumentsSmis(assembler, &fall_through); |
| 862 __ BranchUnsignedGreater(T0, Smi::RawValue(Smi::kBits), &fall_through); | 862 __ BranchUnsignedGreater(T0, Smi::RawValue(Smi::kBits), &fall_through); |
| 863 __ SmiUntag(T0); | 863 __ SmiUntag(T0); |
| 864 | 864 |
| 865 // Check for overflow by shifting left and shifting back arithmetically. | 865 // Check for overflow by shifting left and shifting back arithmetically. |
| 866 // If the result is different from the original, there was overflow. | 866 // If the result is different from the original, there was overflow. |
| 867 __ sllv(TMP, T1, T0); | 867 __ sllv(TMP, T1, T0); |
| 868 __ srav(TMP, TMP, T0); | 868 __ srav(CMPRES1, TMP, T0); |
| 869 __ bne(TMP, T1, &overflow); | 869 __ bne(CMPRES1, T1, &overflow); |
| 870 | 870 |
| 871 // No overflow, result in V0. | 871 // No overflow, result in V0. |
| 872 __ Ret(); | 872 __ Ret(); |
| 873 __ delay_slot()->sllv(V0, T1, T0); | 873 __ delay_slot()->sllv(V0, T1, T0); |
| 874 | 874 |
| 875 __ Bind(&overflow); | 875 __ Bind(&overflow); |
| 876 // Arguments are Smi but the shift produced an overflow to Mint. | 876 // Arguments are Smi but the shift produced an overflow to Mint. |
| 877 __ bltz(T1, &fall_through); | 877 __ bltz(T1, &fall_through); |
| 878 __ SmiUntag(T1); | 878 __ SmiUntag(T1); |
| 879 | 879 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 __ andi(CMPRES, reg, Immediate(kSmiTagMask)); | 913 __ andi(CMPRES, reg, Immediate(kSmiTagMask)); |
| 914 __ bne(CMPRES, ZR, ¬_smi); | 914 __ bne(CMPRES, ZR, ¬_smi); |
| 915 __ SmiUntag(reg); | 915 __ SmiUntag(reg); |
| 916 | 916 |
| 917 // Sign extend to 64 bit | 917 // Sign extend to 64 bit |
| 918 __ mov(res_lo, reg); | 918 __ mov(res_lo, reg); |
| 919 __ b(&done); | 919 __ b(&done); |
| 920 __ delay_slot()->sra(res_hi, reg, 31); | 920 __ delay_slot()->sra(res_hi, reg, 31); |
| 921 | 921 |
| 922 __ Bind(¬_smi); | 922 __ Bind(¬_smi); |
| 923 __ LoadClassId(TMP, reg); | 923 __ LoadClassId(CMPRES1, reg); |
| 924 __ BranchNotEqual(TMP, kMintCid, not_smi_or_mint); | 924 __ BranchNotEqual(CMPRES1, kMintCid, not_smi_or_mint); |
| 925 | 925 |
| 926 // Mint. | 926 // Mint. |
| 927 __ lw(res_lo, FieldAddress(reg, Mint::value_offset())); | 927 __ lw(res_lo, FieldAddress(reg, Mint::value_offset())); |
| 928 __ lw(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize)); | 928 __ lw(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize)); |
| 929 __ Bind(&done); | 929 __ Bind(&done); |
| 930 return; | 930 return; |
| 931 } | 931 } |
| 932 | 932 |
| 933 | 933 |
| 934 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { | 934 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 Label receiver_not_smi; | 1054 Label receiver_not_smi; |
| 1055 __ Bind(&check_for_mint); | 1055 __ Bind(&check_for_mint); |
| 1056 | 1056 |
| 1057 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); | 1057 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |
| 1058 __ bne(CMPRES, ZR, &receiver_not_smi); // Check receiver. | 1058 __ bne(CMPRES, ZR, &receiver_not_smi); // Check receiver. |
| 1059 | 1059 |
| 1060 // Left (receiver) is Smi, return false if right is not Double. | 1060 // Left (receiver) is Smi, return false if right is not Double. |
| 1061 // Note that an instance of Mint or Bigint never contains a value that can be | 1061 // Note that an instance of Mint or Bigint never contains a value that can be |
| 1062 // represented by Smi. | 1062 // represented by Smi. |
| 1063 | 1063 |
| 1064 __ LoadClassId(TMP, T0); | 1064 __ LoadClassId(CMPRES1, T0); |
| 1065 __ BranchEqual(TMP, kDoubleCid, &fall_through); | 1065 __ BranchEqual(CMPRES1, kDoubleCid, &fall_through); |
| 1066 __ LoadObject(V0, Bool::False()); // Smi == Mint -> false. | 1066 __ LoadObject(V0, Bool::False()); // Smi == Mint -> false. |
| 1067 __ Ret(); | 1067 __ Ret(); |
| 1068 | 1068 |
| 1069 __ Bind(&receiver_not_smi); | 1069 __ Bind(&receiver_not_smi); |
| 1070 // T1:: receiver. | 1070 // T1:: receiver. |
| 1071 | 1071 |
| 1072 __ LoadClassId(TMP, T1); | 1072 __ LoadClassId(CMPRES1, T1); |
| 1073 __ BranchNotEqual(TMP, kMintCid, &fall_through); | 1073 __ BranchNotEqual(CMPRES1, kMintCid, &fall_through); |
| 1074 // Receiver is Mint, return false if right is Smi. | 1074 // Receiver is Mint, return false if right is Smi. |
| 1075 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); | 1075 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |
| 1076 __ bne(CMPRES, ZR, &fall_through); | 1076 __ bne(CMPRES, ZR, &fall_through); |
| 1077 __ LoadObject(V0, Bool::False()); | 1077 __ LoadObject(V0, Bool::False()); |
| 1078 __ Ret(); | 1078 __ Ret(); |
| 1079 // TODO(srdjan): Implement Mint == Mint comparison. | 1079 // TODO(srdjan): Implement Mint == Mint comparison. |
| 1080 | 1080 |
| 1081 __ Bind(&fall_through); | 1081 __ Bind(&fall_through); |
| 1082 return false; | 1082 return false; |
| 1083 } | 1083 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1121 | 1121 |
| 1122 // Check if the last argument is a double, jump to label 'is_smi' if smi | 1122 // Check if the last argument is a double, jump to label 'is_smi' if smi |
| 1123 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 1123 // (easy to convert to double), otherwise jump to label 'not_double_smi', |
| 1124 // Returns the last argument in T0. | 1124 // Returns the last argument in T0. |
| 1125 static void TestLastArgumentIsDouble(Assembler* assembler, | 1125 static void TestLastArgumentIsDouble(Assembler* assembler, |
| 1126 Label* is_smi, | 1126 Label* is_smi, |
| 1127 Label* not_double_smi) { | 1127 Label* not_double_smi) { |
| 1128 __ lw(T0, Address(SP, 0 * kWordSize)); | 1128 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1129 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); | 1129 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |
| 1130 __ beq(CMPRES, ZR, is_smi); | 1130 __ beq(CMPRES, ZR, is_smi); |
| 1131 __ LoadClassId(TMP, T0); | 1131 __ LoadClassId(CMPRES1, T0); |
| 1132 __ BranchNotEqual(TMP, kDoubleCid, not_double_smi); | 1132 __ BranchNotEqual(CMPRES1, kDoubleCid, not_double_smi); |
| 1133 // Fall through with Double in T0. | 1133 // Fall through with Double in T0. |
| 1134 } | 1134 } |
| 1135 | 1135 |
| 1136 | 1136 |
| 1137 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown | 1137 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown |
| 1138 // type. Return true or false object in the register V0. Any NaN argument | 1138 // type. Return true or false object in the register V0. Any NaN argument |
| 1139 // returns false. Any non-double arg1 causes control flow to fall through to the | 1139 // returns false. Any non-double arg1 causes control flow to fall through to the |
| 1140 // slow case (compiled method body). | 1140 // slow case (compiled method body). |
| 1141 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { | 1141 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { |
| 1142 Label is_smi, double_op, no_NaN, fall_through; | 1142 Label is_smi, double_op, no_NaN, fall_through; |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 | 1511 |
| 1512 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. | 1512 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. |
| 1513 __ lw(T0, Address(SP, 1 * kWordSize)); // String. | 1513 __ lw(T0, Address(SP, 1 * kWordSize)); // String. |
| 1514 | 1514 |
| 1515 // Checks. | 1515 // Checks. |
| 1516 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); | 1516 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |
| 1517 __ bne(T1, ZR, &fall_through); // Index is not a Smi. | 1517 __ bne(T1, ZR, &fall_through); // Index is not a Smi. |
| 1518 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. | 1518 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. |
| 1519 // Runtime throws exception. | 1519 // Runtime throws exception. |
| 1520 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); | 1520 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); |
| 1521 __ LoadClassId(TMP1, T0); // Class ID check. | 1521 __ LoadClassId(CMPRES1, T0); // Class ID check. |
| 1522 __ BranchNotEqual(TMP1, kOneByteStringCid, &try_two_byte_string); | 1522 __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string); |
| 1523 | 1523 |
| 1524 // Grab byte and return. | 1524 // Grab byte and return. |
| 1525 __ SmiUntag(T1); | 1525 __ SmiUntag(T1); |
| 1526 __ addu(T2, T0, T1); | 1526 __ addu(T2, T0, T1); |
| 1527 __ lbu(V0, FieldAddress(T2, OneByteString::data_offset())); | 1527 __ lbu(V0, FieldAddress(T2, OneByteString::data_offset())); |
| 1528 __ Ret(); | 1528 __ Ret(); |
| 1529 __ delay_slot()->SmiTag(V0); | 1529 __ delay_slot()->SmiTag(V0); |
| 1530 | 1530 |
| 1531 __ Bind(&try_two_byte_string); | 1531 __ Bind(&try_two_byte_string); |
| 1532 __ BranchNotEqual(TMP1, kTwoByteStringCid, &fall_through); | 1532 __ BranchNotEqual(CMPRES1, kTwoByteStringCid, &fall_through); |
| 1533 ASSERT(kSmiTagShift == 1); | 1533 ASSERT(kSmiTagShift == 1); |
| 1534 __ addu(T2, T0, T1); | 1534 __ addu(T2, T0, T1); |
| 1535 __ lhu(V0, FieldAddress(T2, OneByteString::data_offset())); | 1535 __ lhu(V0, FieldAddress(T2, OneByteString::data_offset())); |
| 1536 __ Ret(); | 1536 __ Ret(); |
| 1537 __ delay_slot()->SmiTag(V0); | 1537 __ delay_slot()->SmiTag(V0); |
| 1538 | 1538 |
| 1539 __ Bind(&fall_through); | 1539 __ Bind(&fall_through); |
| 1540 return false; | 1540 return false; |
| 1541 } | 1541 } |
| 1542 | 1542 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1586 // Add to hash code: (hash_ is uint32) | 1586 // Add to hash code: (hash_ is uint32) |
| 1587 // hash_ += ch; | 1587 // hash_ += ch; |
| 1588 // hash_ += hash_ << 10; | 1588 // hash_ += hash_ << 10; |
| 1589 // hash_ ^= hash_ >> 6; | 1589 // hash_ ^= hash_ >> 6; |
| 1590 // Get one characters (ch). | 1590 // Get one characters (ch). |
| 1591 __ Bind(&loop); | 1591 __ Bind(&loop); |
| 1592 __ lbu(T5, Address(T3)); | 1592 __ lbu(T5, Address(T3)); |
| 1593 // T5: ch. | 1593 // T5: ch. |
| 1594 __ addiu(T3, T3, Immediate(1)); | 1594 __ addiu(T3, T3, Immediate(1)); |
| 1595 __ addu(V0, V0, T5); | 1595 __ addu(V0, V0, T5); |
| 1596 __ sll(TMP, V0, 10); | 1596 __ sll(T6, V0, 10); |
| 1597 __ addu(V0, V0, TMP); | 1597 __ addu(V0, V0, T6); |
| 1598 __ srl(TMP, V0, 6); | 1598 __ srl(T6, V0, 6); |
| 1599 __ bne(T3, T4, &loop); | 1599 __ bne(T3, T4, &loop); |
| 1600 __ delay_slot()->xor_(V0, V0, TMP); | 1600 __ delay_slot()->xor_(V0, V0, T6); |
| 1601 | 1601 |
| 1602 // Finalize. | 1602 // Finalize. |
| 1603 // hash_ += hash_ << 3; | 1603 // hash_ += hash_ << 3; |
| 1604 // hash_ ^= hash_ >> 11; | 1604 // hash_ ^= hash_ >> 11; |
| 1605 // hash_ += hash_ << 15; | 1605 // hash_ += hash_ << 15; |
| 1606 __ sll(TMP, V0, 3); | 1606 __ sll(T6, V0, 3); |
| 1607 __ addu(V0, V0, TMP); | 1607 __ addu(V0, V0, T6); |
| 1608 __ srl(TMP, V0, 11); | 1608 __ srl(T6, V0, 11); |
| 1609 __ xor_(V0, V0, TMP); | 1609 __ xor_(V0, V0, T6); |
| 1610 __ sll(TMP, V0, 15); | 1610 __ sll(T6, V0, 15); |
| 1611 __ addu(V0, V0, TMP); | 1611 __ addu(V0, V0, T6); |
| 1612 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); | 1612 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); |
| 1613 __ LoadImmediate(TMP, (static_cast<intptr_t>(1) << String::kHashBits) - 1); | 1613 __ LoadImmediate(T6, (static_cast<intptr_t>(1) << String::kHashBits) - 1); |
| 1614 __ and_(V0, V0, TMP); | 1614 __ and_(V0, V0, T6); |
| 1615 __ Bind(&done); | 1615 __ Bind(&done); |
| 1616 | 1616 |
| 1617 __ LoadImmediate(T2, 1); | 1617 __ LoadImmediate(T2, 1); |
| 1618 __ movz(V0, T2, V0); // If V0 is 0, set to 1. | 1618 __ movz(V0, T2, V0); // If V0 is 0, set to 1. |
| 1619 __ SmiTag(V0); | 1619 __ SmiTag(V0); |
| 1620 | 1620 |
| 1621 __ Ret(); | 1621 __ Ret(); |
| 1622 __ delay_slot()->sw(V0, FieldAddress(T1, String::hash_offset())); | 1622 __ delay_slot()->sw(V0, FieldAddress(T1, String::hash_offset())); |
| 1623 return true; | 1623 return true; |
| 1624 } | 1624 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 __ Bind(&ok); | 1775 __ Bind(&ok); |
| 1776 __ Ret(); | 1776 __ Ret(); |
| 1777 | 1777 |
| 1778 __ Bind(&fall_through); | 1778 __ Bind(&fall_through); |
| 1779 return false; | 1779 return false; |
| 1780 } | 1780 } |
| 1781 | 1781 |
| 1782 } // namespace dart | 1782 } // namespace dart |
| 1783 | 1783 |
| 1784 #endif // defined TARGET_ARCH_MIPS | 1784 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |