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