| 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 Register char_code = locs()->in(0).reg(); | 1047 Register char_code = locs()->in(0).reg(); |
| 1048 Register result = locs()->out().reg(); | 1048 Register result = locs()->out().reg(); |
| 1049 __ LoadImmediate(result, | 1049 __ LoadImmediate(result, |
| 1050 reinterpret_cast<uword>(Symbols::PredefinedAddress())); | 1050 reinterpret_cast<uword>(Symbols::PredefinedAddress())); |
| 1051 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1051 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 1052 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. | 1052 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 | 1055 |
| 1056 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { | 1056 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { |
| 1057 UNIMPLEMENTED(); | 1057 const intptr_t kNumInputs = 1; |
| 1058 return NULL; | 1058 return LocationSummary::Make(kNumInputs, |
| 1059 Location::RequiresRegister(), |
| 1060 LocationSummary::kNoCall); |
| 1059 } | 1061 } |
| 1060 | 1062 |
| 1061 | 1063 |
| 1062 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1064 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1063 UNIMPLEMENTED(); | 1065 Register object = locs()->in(0).reg(); |
| 1066 Register result = locs()->out().reg(); |
| 1067 __ LoadFromOffset(kLoadWord, result, object, offset() - kHeapObjectTag); |
| 1064 } | 1068 } |
| 1065 | 1069 |
| 1066 | 1070 |
| 1067 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { | 1071 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { |
| 1068 const intptr_t kNumInputs = 1; | 1072 const intptr_t kNumInputs = 1; |
| 1069 return LocationSummary::Make(kNumInputs, | 1073 return LocationSummary::Make(kNumInputs, |
| 1070 Location::RequiresRegister(), | 1074 Location::RequiresRegister(), |
| 1071 LocationSummary::kNoCall); | 1075 LocationSummary::kNoCall); |
| 1072 } | 1076 } |
| 1073 | 1077 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 case kOneByteStringCid: | 1360 case kOneByteStringCid: |
| 1357 locs->set_in(2, Location::RegisterOrSmiConstant(value())); | 1361 locs->set_in(2, Location::RegisterOrSmiConstant(value())); |
| 1358 break; | 1362 break; |
| 1359 case kTypedDataInt16ArrayCid: | 1363 case kTypedDataInt16ArrayCid: |
| 1360 case kTypedDataUint16ArrayCid: | 1364 case kTypedDataUint16ArrayCid: |
| 1361 case kTypedDataInt32ArrayCid: | 1365 case kTypedDataInt32ArrayCid: |
| 1362 case kTypedDataUint32ArrayCid: | 1366 case kTypedDataUint32ArrayCid: |
| 1363 locs->set_in(2, Location::WritableRegister()); | 1367 locs->set_in(2, Location::WritableRegister()); |
| 1364 break; | 1368 break; |
| 1365 case kTypedDataFloat32ArrayCid: | 1369 case kTypedDataFloat32ArrayCid: |
| 1366 // TODO(regis): Verify. | |
| 1367 // Need temp register for float-to-double conversion. | |
| 1368 locs->AddTemp(Location::RequiresFpuRegister()); | |
| 1369 // Fall through. | |
| 1370 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. | 1370 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 1371 case kTypedDataFloat32x4ArrayCid: | 1371 case kTypedDataFloat32x4ArrayCid: |
| 1372 locs->set_in(2, Location::RequiresFpuRegister()); | 1372 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1373 break; | 1373 break; |
| 1374 default: | 1374 default: |
| 1375 UNREACHABLE(); | 1375 UNREACHABLE(); |
| 1376 return NULL; | 1376 return NULL; |
| 1377 } | 1377 } |
| 1378 return locs; | 1378 return locs; |
| 1379 } | 1379 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1489 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 1490 Register value = locs()->in(2).reg(); | 1490 Register value = locs()->in(2).reg(); |
| 1491 __ SmiUntag(value); | 1491 __ SmiUntag(value); |
| 1492 __ str(value, element_address); | 1492 __ str(value, element_address); |
| 1493 } else { | 1493 } else { |
| 1494 UNIMPLEMENTED(); | 1494 UNIMPLEMENTED(); |
| 1495 } | 1495 } |
| 1496 break; | 1496 break; |
| 1497 } | 1497 } |
| 1498 case kTypedDataFloat32ArrayCid: | 1498 case kTypedDataFloat32ArrayCid: |
| 1499 // Convert to single precision. |
| 1500 __ vcvtsd(STMP, locs()->in(2).fpu_reg()); |
| 1501 // Store. |
| 1502 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1503 __ StoreSToOffset(STMP, index.reg(), 0); |
| 1504 break; |
| 1499 case kTypedDataFloat64ArrayCid: | 1505 case kTypedDataFloat64ArrayCid: |
| 1506 __ add(index.reg(), index.reg(), ShifterOperand(array)); |
| 1507 __ StoreDToOffset(locs()->in(2).fpu_reg(), index.reg(), 0); |
| 1508 break; |
| 1500 case kTypedDataFloat32x4ArrayCid: | 1509 case kTypedDataFloat32x4ArrayCid: |
| 1501 UNIMPLEMENTED(); | 1510 UNIMPLEMENTED(); |
| 1502 break; | 1511 break; |
| 1503 default: | 1512 default: |
| 1504 UNREACHABLE(); | 1513 UNREACHABLE(); |
| 1505 } | 1514 } |
| 1506 } | 1515 } |
| 1507 | 1516 |
| 1508 | 1517 |
| 1509 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { | 1518 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 Range* right_range = shift_left->right()->definition()->range(); | 2128 Range* right_range = shift_left->right()->definition()->range(); |
| 2120 if (shift_left->left()->BindsToConstant() && !is_truncating) { | 2129 if (shift_left->left()->BindsToConstant() && !is_truncating) { |
| 2121 // TODO(srdjan): Implement code below for is_truncating(). | 2130 // TODO(srdjan): Implement code below for is_truncating(). |
| 2122 // If left is constant, we know the maximal allowed size for right. | 2131 // If left is constant, we know the maximal allowed size for right. |
| 2123 const Object& obj = shift_left->left()->BoundConstant(); | 2132 const Object& obj = shift_left->left()->BoundConstant(); |
| 2124 if (obj.IsSmi()) { | 2133 if (obj.IsSmi()) { |
| 2125 const intptr_t left_int = Smi::Cast(obj).Value(); | 2134 const intptr_t left_int = Smi::Cast(obj).Value(); |
| 2126 if (left_int == 0) { | 2135 if (left_int == 0) { |
| 2127 __ cmp(right, ShifterOperand(0)); | 2136 __ cmp(right, ShifterOperand(0)); |
| 2128 __ b(deopt, MI); | 2137 __ b(deopt, MI); |
| 2138 __ mov(result, ShifterOperand(0)); |
| 2129 return; | 2139 return; |
| 2130 } | 2140 } |
| 2131 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2141 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2132 const bool right_needs_check = | 2142 const bool right_needs_check = |
| 2133 (right_range == NULL) || | 2143 (right_range == NULL) || |
| 2134 !right_range->IsWithin(0, max_right - 1); | 2144 !right_range->IsWithin(0, max_right - 1); |
| 2135 if (right_needs_check) { | 2145 if (right_needs_check) { |
| 2136 __ cmp(right, | 2146 __ cmp(right, |
| 2137 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right)))); | 2147 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right)))); |
| 2138 __ b(deopt, CS); | 2148 __ b(deopt, CS); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2332 } | 2342 } |
| 2333 break; | 2343 break; |
| 2334 } | 2344 } |
| 2335 case Token::kSHR: { | 2345 case Token::kSHR: { |
| 2336 // sarl operation masks the count to 5 bits. | 2346 // sarl operation masks the count to 5 bits. |
| 2337 const intptr_t kCountLimit = 0x1F; | 2347 const intptr_t kCountLimit = 0x1F; |
| 2338 intptr_t value = Smi::Cast(constant).Value(); | 2348 intptr_t value = Smi::Cast(constant).Value(); |
| 2339 | 2349 |
| 2340 if (value == 0) { | 2350 if (value == 0) { |
| 2341 // TODO(vegorov): should be handled outside. | 2351 // TODO(vegorov): should be handled outside. |
| 2352 __ MoveRegister(result, left); |
| 2342 break; | 2353 break; |
| 2343 } else if (value < 0) { | 2354 } else if (value < 0) { |
| 2344 // TODO(vegorov): should be handled outside. | 2355 // TODO(vegorov): should be handled outside. |
| 2345 __ b(deopt); | 2356 __ b(deopt); |
| 2346 break; | 2357 break; |
| 2347 } | 2358 } |
| 2348 | 2359 |
| 2349 value = value + kSmiTagSize; | 2360 value = value + kSmiTagSize; |
| 2350 if (value >= kCountLimit) value = kCountLimit; | 2361 if (value >= kCountLimit) value = kCountLimit; |
| 2351 | 2362 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2419 } | 2430 } |
| 2420 __ sdiv(result, left, right); | 2431 __ sdiv(result, left, right); |
| 2421 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2432 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2422 // case we cannot tag the result. | 2433 // case we cannot tag the result. |
| 2423 __ CompareImmediate(result, 0x40000000); | 2434 __ CompareImmediate(result, 0x40000000); |
| 2424 __ b(deopt, EQ); | 2435 __ b(deopt, EQ); |
| 2425 __ SmiTag(result); | 2436 __ SmiTag(result); |
| 2426 break; | 2437 break; |
| 2427 } | 2438 } |
| 2428 case Token::kSHR: { | 2439 case Token::kSHR: { |
| 2429 UNIMPLEMENTED(); | 2440 if (CanDeoptimize()) { |
| 2441 __ CompareImmediate(right, 0); |
| 2442 __ b(deopt, LT); |
| 2443 } |
| 2444 __ SmiUntag(right); |
| 2445 // sarl operation masks the count to 5 bits. |
| 2446 const intptr_t kCountLimit = 0x1F; |
| 2447 Range* right_range = this->right()->definition()->range(); |
| 2448 if ((right_range == NULL) || |
| 2449 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2450 __ CompareImmediate(right, kCountLimit); |
| 2451 __ LoadImmediate(right, kCountLimit, GT); |
| 2452 } |
| 2453 __ SmiUntag(left); |
| 2454 __ Asr(result, left, right); |
| 2455 __ SmiTag(result); |
| 2430 break; | 2456 break; |
| 2431 } | 2457 } |
| 2432 case Token::kDIV: { | 2458 case Token::kDIV: { |
| 2433 // Dispatches to 'Double./'. | 2459 // Dispatches to 'Double./'. |
| 2434 // TODO(srdjan): Implement as conversion to double and double division. | 2460 // TODO(srdjan): Implement as conversion to double and double division. |
| 2435 UNREACHABLE(); | 2461 UNREACHABLE(); |
| 2436 break; | 2462 break; |
| 2437 } | 2463 } |
| 2438 case Token::kMOD: { | 2464 case Token::kMOD: { |
| 2439 // TODO(srdjan): Implement. | 2465 // TODO(srdjan): Implement. |
| (...skipping 1139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3579 compiler->GenerateCall(token_pos(), | 3605 compiler->GenerateCall(token_pos(), |
| 3580 &label, | 3606 &label, |
| 3581 PcDescriptors::kOther, | 3607 PcDescriptors::kOther, |
| 3582 locs()); | 3608 locs()); |
| 3583 __ Drop(2); // Discard type arguments and receiver. | 3609 __ Drop(2); // Discard type arguments and receiver. |
| 3584 } | 3610 } |
| 3585 | 3611 |
| 3586 } // namespace dart | 3612 } // namespace dart |
| 3587 | 3613 |
| 3588 #endif // defined TARGET_ARCH_ARM | 3614 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |