| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 // T1: potential next object start. | 64 // T1: potential next object start. |
| 65 // T2: allocation size. | 65 // T2: allocation size. |
| 66 __ LoadImmediate(T4, heap->TopAddress()); | 66 __ LoadImmediate(T4, heap->TopAddress()); |
| 67 __ lw(T4, Address(T4, 0)); | 67 __ lw(T4, Address(T4, 0)); |
| 68 __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); | 68 __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); |
| 69 | 69 |
| 70 // Successfully allocated the object(s), now update top to point to | 70 // Successfully allocated the object(s), now update top to point to |
| 71 // next object start and initialize the object. | 71 // next object start and initialize the object. |
| 72 __ sw(T1, Address(T3, 0)); | 72 __ sw(T1, Address(T3, 0)); |
| 73 __ addiu(T0, T0, Immediate(kHeapObjectTag)); | 73 __ addiu(T0, T0, Immediate(kHeapObjectTag)); |
| 74 __ UpdateAllocationStatsWithSize(kArrayCid, T2, T4); |
| 74 | 75 |
| 75 // Initialize the tags. | 76 // Initialize the tags. |
| 76 // T0: new object start as a tagged pointer. | 77 // T0: new object start as a tagged pointer. |
| 77 // T1: new object end address. | 78 // T1: new object end address. |
| 78 // T2: allocation size. | 79 // T2: allocation size. |
| 79 { | 80 { |
| 80 Label overflow, done; | 81 Label overflow, done; |
| 81 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 82 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
| 82 const Class& cls = Class::Handle(isolate->object_store()->array_class()); | 83 const Class& cls = Class::Handle(isolate->object_store()->array_class()); |
| 83 | 84 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 FieldAddress(V0, GrowableObjectArray::data_offset()), | 300 FieldAddress(V0, GrowableObjectArray::data_offset()), |
| 300 T1); | 301 T1); |
| 301 | 302 |
| 302 // V0: new growable array object start as a tagged pointer. | 303 // V0: new growable array object start as a tagged pointer. |
| 303 // Store the type argument field in the growable array object. | 304 // Store the type argument field in the growable array object. |
| 304 __ lw(T1, Address(SP, kTypeArgumentsOffset)); // Type argument. | 305 __ lw(T1, Address(SP, kTypeArgumentsOffset)); // Type argument. |
| 305 __ StoreIntoObjectNoBarrier( | 306 __ StoreIntoObjectNoBarrier( |
| 306 V0, | 307 V0, |
| 307 FieldAddress(V0, GrowableObjectArray::type_arguments_offset()), | 308 FieldAddress(V0, GrowableObjectArray::type_arguments_offset()), |
| 308 T1); | 309 T1); |
| 309 | 310 __ UpdateAllocationStats(kGrowableObjectArrayCid, T1); |
| 310 // Set the length field in the growable array object to 0. | 311 // Set the length field in the growable array object to 0. |
| 311 __ Ret(); // Returns the newly allocated object in V0. | 312 __ Ret(); // Returns the newly allocated object in V0. |
| 312 __ delay_slot()->sw(ZR, | 313 __ delay_slot()->sw(ZR, |
| 313 FieldAddress(V0, GrowableObjectArray::length_offset())); | 314 FieldAddress(V0, GrowableObjectArray::length_offset())); |
| 314 | 315 |
| 315 __ Bind(&fall_through); | 316 __ Bind(&fall_through); |
| 316 } | 317 } |
| 317 | 318 |
| 318 | 319 |
| 319 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 320 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 /* T2: allocation size. */ \ | 492 /* T2: allocation size. */ \ |
| 492 __ LoadImmediate(T3, heap->EndAddress()); \ | 493 __ LoadImmediate(T3, heap->EndAddress()); \ |
| 493 __ lw(T3, Address(T3, 0)); \ | 494 __ lw(T3, Address(T3, 0)); \ |
| 494 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); \ | 495 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); \ |
| 495 \ | 496 \ |
| 496 /* Successfully allocated the object(s), now update top to point to */ \ | 497 /* Successfully allocated the object(s), now update top to point to */ \ |
| 497 /* next object start and initialize the object. */ \ | 498 /* next object start and initialize the object. */ \ |
| 498 __ LoadImmediate(T3, heap->TopAddress()); \ | 499 __ LoadImmediate(T3, heap->TopAddress()); \ |
| 499 __ sw(T1, Address(T3, 0)); \ | 500 __ sw(T1, Address(T3, 0)); \ |
| 500 __ AddImmediate(V0, kHeapObjectTag); \ | 501 __ AddImmediate(V0, kHeapObjectTag); \ |
| 501 \ | 502 __ UpdateAllocationStatsWithSize(cid, T2, T4); \ |
| 502 /* Initialize the tags. */ \ | 503 /* Initialize the tags. */ \ |
| 503 /* V0: new object start as a tagged pointer. */ \ | 504 /* V0: new object start as a tagged pointer. */ \ |
| 504 /* T1: new object end address. */ \ | 505 /* T1: new object end address. */ \ |
| 505 /* T2: allocation size. */ \ | 506 /* T2: allocation size. */ \ |
| 506 { \ | 507 { \ |
| 507 Label size_tag_overflow, done; \ | 508 Label size_tag_overflow, done; \ |
| 508 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, \ | 509 __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, \ |
| 509 &size_tag_overflow); \ | 510 &size_tag_overflow); \ |
| 510 __ b(&done); \ | 511 __ b(&done); \ |
| 511 __ delay_slot()->sll(T2, T2, \ | 512 __ delay_slot()->sll(T2, T2, \ |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 __ subu(T4, ZR, T0); // T4 <- -T0 | 848 __ subu(T4, ZR, T0); // T4 <- -T0 |
| 848 __ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0 | 849 __ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0 |
| 849 __ sllv(T3, T3, T4); // T3 <- T3 << T4 | 850 __ sllv(T3, T3, T4); // T3 <- T3 << T4 |
| 850 __ and_(T3, T3, T1); // T3 <- T3 & T1 | 851 __ and_(T3, T3, T1); // T3 <- T3 & T1 |
| 851 __ srlv(T3, T3, T4); // T3 <- T3 >> T4 | 852 __ srlv(T3, T3, T4); // T3 <- T3 >> T4 |
| 852 // Now T3 has the bits that fall off of T1 on a left shift. | 853 // Now T3 has the bits that fall off of T1 on a left shift. |
| 853 __ sllv(T0, T1, T0); // T0 gets low bits. | 854 __ sllv(T0, T1, T0); // T0 gets low bits. |
| 854 | 855 |
| 855 const Class& mint_class = Class::Handle( | 856 const Class& mint_class = Class::Handle( |
| 856 Isolate::Current()->object_store()->mint_class()); | 857 Isolate::Current()->object_store()->mint_class()); |
| 857 __ TryAllocate(mint_class, &fall_through, V0); | 858 __ TryAllocate(mint_class, &fall_through, V0, T1); |
| 858 | 859 |
| 859 __ sw(T0, FieldAddress(V0, Mint::value_offset())); | 860 __ sw(T0, FieldAddress(V0, Mint::value_offset())); |
| 860 __ Ret(); | 861 __ Ret(); |
| 861 __ delay_slot()->sw(T3, FieldAddress(V0, Mint::value_offset() + kWordSize)); | 862 __ delay_slot()->sw(T3, FieldAddress(V0, Mint::value_offset() + kWordSize)); |
| 862 __ Bind(&fall_through); | 863 __ Bind(&fall_through); |
| 863 } | 864 } |
| 864 | 865 |
| 865 | 866 |
| 866 static void Get64SmiOrMint(Assembler* assembler, | 867 static void Get64SmiOrMint(Assembler* assembler, |
| 867 Register res_hi, | 868 Register res_hi, |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); | 1188 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); |
| 1188 switch (kind) { | 1189 switch (kind) { |
| 1189 case Token::kADD: __ addd(D0, D0, D1); break; | 1190 case Token::kADD: __ addd(D0, D0, D1); break; |
| 1190 case Token::kSUB: __ subd(D0, D0, D1); break; | 1191 case Token::kSUB: __ subd(D0, D0, D1); break; |
| 1191 case Token::kMUL: __ muld(D0, D0, D1); break; | 1192 case Token::kMUL: __ muld(D0, D0, D1); break; |
| 1192 case Token::kDIV: __ divd(D0, D0, D1); break; | 1193 case Token::kDIV: __ divd(D0, D0, D1); break; |
| 1193 default: UNREACHABLE(); | 1194 default: UNREACHABLE(); |
| 1194 } | 1195 } |
| 1195 const Class& double_class = Class::Handle( | 1196 const Class& double_class = Class::Handle( |
| 1196 Isolate::Current()->object_store()->double_class()); | 1197 Isolate::Current()->object_store()->double_class()); |
| 1197 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1198 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
| 1198 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1199 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
| 1199 __ Ret(); | 1200 __ Ret(); |
| 1200 __ delay_slot()->swc1(F1, | 1201 __ delay_slot()->swc1(F1, |
| 1201 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1202 FieldAddress(V0, Double::value_offset() + kWordSize)); |
| 1202 __ Bind(&fall_through); | 1203 __ Bind(&fall_through); |
| 1203 } | 1204 } |
| 1204 | 1205 |
| 1205 | 1206 |
| 1206 void Intrinsifier::Double_add(Assembler* assembler) { | 1207 void Intrinsifier::Double_add(Assembler* assembler) { |
| 1207 return DoubleArithmeticOperations(assembler, Token::kADD); | 1208 return DoubleArithmeticOperations(assembler, Token::kADD); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1235 __ SmiUntag(T0); | 1236 __ SmiUntag(T0); |
| 1236 __ mtc1(T0, F4); | 1237 __ mtc1(T0, F4); |
| 1237 __ cvtdw(D1, F4); | 1238 __ cvtdw(D1, F4); |
| 1238 | 1239 |
| 1239 __ lw(T0, Address(SP, 1 * kWordSize)); | 1240 __ lw(T0, Address(SP, 1 * kWordSize)); |
| 1240 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); | 1241 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); |
| 1241 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); | 1242 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); |
| 1242 __ muld(D0, D0, D1); | 1243 __ muld(D0, D0, D1); |
| 1243 const Class& double_class = Class::Handle( | 1244 const Class& double_class = Class::Handle( |
| 1244 Isolate::Current()->object_store()->double_class()); | 1245 Isolate::Current()->object_store()->double_class()); |
| 1245 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1246 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
| 1246 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1247 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
| 1247 __ Ret(); | 1248 __ Ret(); |
| 1248 __ delay_slot()->swc1(F1, | 1249 __ delay_slot()->swc1(F1, |
| 1249 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1250 FieldAddress(V0, Double::value_offset() + kWordSize)); |
| 1250 __ Bind(&fall_through); | 1251 __ Bind(&fall_through); |
| 1251 } | 1252 } |
| 1252 | 1253 |
| 1253 | 1254 |
| 1254 void Intrinsifier::Double_fromInteger(Assembler* assembler) { | 1255 void Intrinsifier::Double_fromInteger(Assembler* assembler) { |
| 1255 Label fall_through; | 1256 Label fall_through; |
| 1256 | 1257 |
| 1257 __ lw(T0, Address(SP, 0 * kWordSize)); | 1258 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1258 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 1259 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
| 1259 __ bne(T0, ZR, &fall_through); | 1260 __ bne(T0, ZR, &fall_through); |
| 1260 | 1261 |
| 1261 // Is Smi. | 1262 // Is Smi. |
| 1262 __ SmiUntag(T0); | 1263 __ SmiUntag(T0); |
| 1263 __ mtc1(T0, F4); | 1264 __ mtc1(T0, F4); |
| 1264 __ cvtdw(D0, F4); | 1265 __ cvtdw(D0, F4); |
| 1265 const Class& double_class = Class::Handle( | 1266 const Class& double_class = Class::Handle( |
| 1266 Isolate::Current()->object_store()->double_class()); | 1267 Isolate::Current()->object_store()->double_class()); |
| 1267 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1268 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
| 1268 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1269 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
| 1269 __ Ret(); | 1270 __ Ret(); |
| 1270 __ delay_slot()->swc1(F1, | 1271 __ delay_slot()->swc1(F1, |
| 1271 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1272 FieldAddress(V0, Double::value_offset() + kWordSize)); |
| 1272 __ Bind(&fall_through); | 1273 __ Bind(&fall_through); |
| 1273 } | 1274 } |
| 1274 | 1275 |
| 1275 | 1276 |
| 1276 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { | 1277 void Intrinsifier::Double_getIsNaN(Assembler* assembler) { |
| 1277 Label is_true; | 1278 Label is_true; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 | 1344 |
| 1344 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1345 void Intrinsifier::Math_sqrt(Assembler* assembler) { |
| 1345 Label fall_through, is_smi, double_op; | 1346 Label fall_through, is_smi, double_op; |
| 1346 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1347 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 1347 // Argument is double and is in T0. | 1348 // Argument is double and is in T0. |
| 1348 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); | 1349 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); |
| 1349 __ Bind(&double_op); | 1350 __ Bind(&double_op); |
| 1350 __ sqrtd(D0, D1); | 1351 __ sqrtd(D0, D1); |
| 1351 const Class& double_class = Class::Handle( | 1352 const Class& double_class = Class::Handle( |
| 1352 Isolate::Current()->object_store()->double_class()); | 1353 Isolate::Current()->object_store()->double_class()); |
| 1353 __ TryAllocate(double_class, &fall_through, V0); // Result register. | 1354 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. |
| 1354 __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 1355 __ swc1(F0, FieldAddress(V0, Double::value_offset())); |
| 1355 __ Ret(); | 1356 __ Ret(); |
| 1356 __ delay_slot()->swc1(F1, | 1357 __ delay_slot()->swc1(F1, |
| 1357 FieldAddress(V0, Double::value_offset() + kWordSize)); | 1358 FieldAddress(V0, Double::value_offset() + kWordSize)); |
| 1358 | 1359 |
| 1359 __ Bind(&is_smi); | 1360 __ Bind(&is_smi); |
| 1360 __ SmiUntag(T0); | 1361 __ SmiUntag(T0); |
| 1361 __ mtc1(T0, F2); | 1362 __ mtc1(T0, F2); |
| 1362 __ b(&double_op); | 1363 __ b(&double_op); |
| 1363 __ delay_slot()->cvtdw(D1, F2); | 1364 __ delay_slot()->cvtdw(D1, F2); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 // T3: heap->TopAddress(). | 1593 // T3: heap->TopAddress(). |
| 1593 __ LoadImmediate(T4, heap->EndAddress()); | 1594 __ LoadImmediate(T4, heap->EndAddress()); |
| 1594 __ lw(T4, Address(T4, 0)); | 1595 __ lw(T4, Address(T4, 0)); |
| 1595 __ BranchUnsignedGreaterEqual(T1, T4, failure); | 1596 __ BranchUnsignedGreaterEqual(T1, T4, failure); |
| 1596 | 1597 |
| 1597 // Successfully allocated the object(s), now update top to point to | 1598 // Successfully allocated the object(s), now update top to point to |
| 1598 // next object start and initialize the object. | 1599 // next object start and initialize the object. |
| 1599 __ sw(T1, Address(T3, 0)); | 1600 __ sw(T1, Address(T3, 0)); |
| 1600 __ AddImmediate(V0, kHeapObjectTag); | 1601 __ AddImmediate(V0, kHeapObjectTag); |
| 1601 | 1602 |
| 1603 __ UpdateAllocationStatsWithSize(kOneByteStringCid, T2, T3); |
| 1604 |
| 1602 // Initialize the tags. | 1605 // Initialize the tags. |
| 1603 // V0: new object start as a tagged pointer. | 1606 // V0: new object start as a tagged pointer. |
| 1604 // T1: new object end address. | 1607 // T1: new object end address. |
| 1605 // T2: allocation size. | 1608 // T2: allocation size. |
| 1606 { | 1609 { |
| 1607 Label overflow, done; | 1610 Label overflow, done; |
| 1608 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; | 1611 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; |
| 1609 const Class& cls = | 1612 const Class& cls = |
| 1610 Class::Handle(isolate->object_store()->one_byte_string_class()); | 1613 Class::Handle(isolate->object_store()->one_byte_string_class()); |
| 1611 | 1614 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 } | 1778 } |
| 1776 | 1779 |
| 1777 | 1780 |
| 1778 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { | 1781 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { |
| 1779 StringEquality(assembler, kTwoByteStringCid); | 1782 StringEquality(assembler, kTwoByteStringCid); |
| 1780 } | 1783 } |
| 1781 | 1784 |
| 1782 } // namespace dart | 1785 } // namespace dart |
| 1783 | 1786 |
| 1784 #endif // defined TARGET_ARCH_MIPS | 1787 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |