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 |