| 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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 if (FLAG_enable_type_checks) { | 197 if (FLAG_enable_type_checks) { |
| 198 const intptr_t type_args_field_offset = | 198 const intptr_t type_args_field_offset = |
| 199 ComputeObjectArrayTypeArgumentsOffset(); | 199 ComputeObjectArrayTypeArgumentsOffset(); |
| 200 // Inline simple tests (Smi, null), fallthrough if not positive. | 200 // Inline simple tests (Smi, null), fallthrough if not positive. |
| 201 Label checked_ok; | 201 Label checked_ok; |
| 202 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. | 202 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. |
| 203 | 203 |
| 204 // Null value is valid for any type. | 204 // Null value is valid for any type. |
| 205 __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null())); | 205 __ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null())); |
| 206 __ beq(T2, T7, &checked_ok); | 206 __ beq(T2, T7, &checked_ok); |
| 207 __ delay_slot()->lw(T1, Address(SP, 2 * kWordSize)); // Array. | |
| 208 | 207 |
| 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(TMP, T1); |
| 217 __ BranchNotEqual(TMP, kTypeArgumentsCid, &fall_through); | 217 __ BranchNotEqual(TMP, 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); |
| 228 __ BranchNotEqual(T0, Type::ZoneHandle(Type::Number()), &fall_through); | 228 __ BranchNotEqual(T0, Type::ZoneHandle(Type::Number()), &fall_through); |
| 229 __ Bind(&checked_ok); | 229 __ Bind(&checked_ok); |
| 230 } | 230 } |
| 231 __ lw(T1, Address(SP, 1 * kWordSize)); // Index. | 231 __ lw(T1, Address(SP, 1 * kWordSize)); // Index. |
| 232 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); | 232 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |
| 233 // Index not Smi. | 233 // Index not Smi. |
| 234 __ bne(CMPRES, ZR, &fall_through); | 234 __ bne(CMPRES, ZR, &fall_through); |
| 235 __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize)); // Array. | |
| 236 | 235 |
| 236 __ lw(T0, Address(SP, 2 * kWordSize)); // Array. |
| 237 // Range check. | 237 // Range check. |
| 238 __ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length. | 238 __ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length. |
| 239 // Runtime throws exception. | 239 // Runtime throws exception. |
| 240 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); | 240 __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); |
| 241 | 241 |
| 242 // Note that T1 is Smi, i.e, times 2. | 242 // Note that T1 is Smi, i.e, times 2. |
| 243 ASSERT(kSmiTagShift == 1); | 243 ASSERT(kSmiTagShift == 1); |
| 244 // Destroy T2 as we will not continue in the function. | 244 // Destroy T2 as we will not continue in the function. |
| 245 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. | 245 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. |
| 246 __ sll(T1, T1, 1); // T1 is Smi. | 246 __ sll(T1, T1, 1); // T1 is Smi. |
| 247 __ addu(T1, T0, T1); | 247 __ addu(T1, T0, T1); |
| 248 __ StoreIntoObject(T0, | 248 __ StoreIntoObject(T0, |
| 249 FieldAddress(T1, Array::data_offset()), | 249 FieldAddress(T1, Array::data_offset()), |
| 250 T2); | 250 T2); |
| 251 // Caller is responsible of preserving the value if necessary. | 251 // Caller is responsible for preserving the value if necessary. |
| 252 __ Ret(); | 252 __ Ret(); |
| 253 __ Bind(&fall_through); | 253 __ Bind(&fall_through); |
| 254 return false; | 254 return false; |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 // Allocate a GrowableObjectArray using the backing array specified. | 258 // Allocate a GrowableObjectArray using the backing array specified. |
| 259 // On stack: type argument (+1), data (+0). | 259 // On stack: type argument (+1), data (+0). |
| 260 bool Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { | 260 bool Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { |
| 261 // The newly allocated object is returned in V0. | 261 // The newly allocated object is returned in V0. |
| (...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 __ Bind(&is_true); | 1331 __ Bind(&is_true); |
| 1332 __ LoadObject(V0, Bool::True()); | 1332 __ LoadObject(V0, Bool::True()); |
| 1333 __ Ret(); | 1333 __ Ret(); |
| 1334 return true; | 1334 return true; |
| 1335 } | 1335 } |
| 1336 | 1336 |
| 1337 | 1337 |
| 1338 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { | 1338 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { |
| 1339 Label is_false, is_true, is_zero; | 1339 Label is_false, is_true, is_zero; |
| 1340 __ lw(T0, Address(SP, 0 * kWordSize)); | 1340 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1341 __ lwc1(F0, FieldAddress(T0, Double::value_offset())); | 1341 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); |
| 1342 __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); | |
| 1343 | 1342 |
| 1344 __ cund(D0, D0); | 1343 __ cund(D0, D0); |
| 1345 __ bc1t(&is_false); // NaN -> false. | 1344 __ bc1t(&is_false); // NaN -> false. |
| 1346 | 1345 |
| 1346 __ LoadImmediate(D1, 0.0); |
| 1347 __ ceqd(D0, D1); | 1347 __ ceqd(D0, D1); |
| 1348 __ bc1t(&is_zero); // Check for negative zero. | 1348 __ bc1t(&is_zero); // Check for negative zero. |
| 1349 | 1349 |
| 1350 __ LoadImmediate(D1, 0.0); | |
| 1351 __ coled(D1, D0); | 1350 __ coled(D1, D0); |
| 1352 __ bc1t(&is_false); // >= 0 -> false. | 1351 __ bc1t(&is_false); // >= 0 -> false. |
| 1353 | 1352 |
| 1354 __ Bind(&is_true); | 1353 __ Bind(&is_true); |
| 1355 __ LoadObject(V0, Bool::True()); | 1354 __ LoadObject(V0, Bool::True()); |
| 1356 __ Ret(); | 1355 __ Ret(); |
| 1357 | 1356 |
| 1358 __ Bind(&is_false); | 1357 __ Bind(&is_false); |
| 1359 __ LoadObject(V0, Bool::False()); | 1358 __ LoadObject(V0, Bool::False()); |
| 1360 __ Ret(); | 1359 __ Ret(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1441 const Instance& a_value = Instance::Handle(random_A_field.value()); | 1440 const Instance& a_value = Instance::Handle(random_A_field.value()); |
| 1442 const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value(); | 1441 const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value(); |
| 1443 // 'a_int_value' is a mask. | 1442 // 'a_int_value' is a mask. |
| 1444 ASSERT(Utils::IsUint(32, a_int_value)); | 1443 ASSERT(Utils::IsUint(32, a_int_value)); |
| 1445 int32_t a_int32_value = static_cast<int32_t>(a_int_value); | 1444 int32_t a_int32_value = static_cast<int32_t>(a_int_value); |
| 1446 | 1445 |
| 1447 __ lw(T0, Address(SP, 0 * kWordSize)); // Receiver. | 1446 __ lw(T0, Address(SP, 0 * kWordSize)); // Receiver. |
| 1448 __ lw(T1, FieldAddress(T0, state_field.Offset())); // Field '_state'. | 1447 __ lw(T1, FieldAddress(T0, state_field.Offset())); // Field '_state'. |
| 1449 | 1448 |
| 1450 // Addresses of _state[0] and _state[1]. | 1449 // Addresses of _state[0] and _state[1]. |
| 1451 const int64_t disp_0 = | 1450 const Address& addr_0 = FieldAddress(T1, |
| 1452 FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid); | 1451 FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid)); |
| 1453 | 1452 |
| 1454 const int64_t disp_1 = | 1453 const Address& addr_1 = FieldAddress(T1, |
| 1455 FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid) + | 1454 FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid) + |
| 1456 FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid); | 1455 FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid)); |
| 1456 |
| 1457 __ LoadImmediate(T0, a_int32_value); | 1457 __ LoadImmediate(T0, a_int32_value); |
| 1458 __ lw(T2, FieldAddress(T1, disp_0)); | 1458 __ lw(T2, addr_0); |
| 1459 __ lw(T3, FieldAddress(T1, disp_1)); | 1459 __ lw(T3, addr_1); |
| 1460 __ sra(T6, T3, 31); // Sign extend T3 into T6. | 1460 __ sra(T6, T3, 31); // Sign extend T3 into T6. |
| 1461 __ mtlo(T3); | 1461 __ mtlo(T3); |
| 1462 __ mthi(T6); // HI:LO <- T6:T3 | 1462 __ mthi(T6); // HI:LO <- T6:T3 |
| 1463 // 64-bit multiply and accumulate into T6:T3. | 1463 // 64-bit multiply and accumulate into T6:T3. |
| 1464 __ madd(T0, T2); // HI:LO <- HI:LO + T0 * T3. | 1464 __ madd(T0, T2); // HI:LO <- HI:LO + T0 * T2. |
| 1465 __ mflo(T3); | 1465 __ mflo(T3); |
| 1466 __ mfhi(T6); | 1466 __ mfhi(T6); |
| 1467 __ sw(T3, FieldAddress(T1, disp_0)); | 1467 __ sw(T3, addr_0); |
| 1468 __ sw(T6, FieldAddress(T1, disp_1)); | 1468 __ sw(T6, addr_1); |
| 1469 __ Ret(); | 1469 __ Ret(); |
| 1470 return true; | 1470 return true; |
| 1471 } | 1471 } |
| 1472 | 1472 |
| 1473 | 1473 |
| 1474 bool Intrinsifier::Object_equal(Assembler* assembler) { | 1474 bool Intrinsifier::Object_equal(Assembler* assembler) { |
| 1475 Label is_true; | 1475 Label is_true; |
| 1476 | 1476 |
| 1477 __ lw(T0, Address(SP, 0 * kWordSize)); | 1477 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1478 __ lw(T1, Address(SP, 1 * kWordSize)); | 1478 __ lw(T1, Address(SP, 1 * kWordSize)); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 __ Bind(&ok); | 1767 __ Bind(&ok); |
| 1768 __ Ret(); | 1768 __ Ret(); |
| 1769 | 1769 |
| 1770 __ Bind(&fall_through); | 1770 __ Bind(&fall_through); |
| 1771 return false; | 1771 return false; |
| 1772 } | 1772 } |
| 1773 | 1773 |
| 1774 } // namespace dart | 1774 } // namespace dart |
| 1775 | 1775 |
| 1776 #endif // defined TARGET_ARCH_MIPS | 1776 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |