| 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 "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1444 : Location::RegisterOrConstant(value())); | 1444 : Location::RegisterOrConstant(value())); |
| 1445 break; | 1445 break; |
| 1446 case kExternalTypedDataUint8ArrayCid: | 1446 case kExternalTypedDataUint8ArrayCid: |
| 1447 case kExternalTypedDataUint8ClampedArrayCid: | 1447 case kExternalTypedDataUint8ClampedArrayCid: |
| 1448 case kTypedDataInt8ArrayCid: | 1448 case kTypedDataInt8ArrayCid: |
| 1449 case kTypedDataUint8ArrayCid: | 1449 case kTypedDataUint8ArrayCid: |
| 1450 case kTypedDataUint8ClampedArrayCid: | 1450 case kTypedDataUint8ClampedArrayCid: |
| 1451 case kOneByteStringCid: | 1451 case kOneByteStringCid: |
| 1452 case kTypedDataInt16ArrayCid: | 1452 case kTypedDataInt16ArrayCid: |
| 1453 case kTypedDataUint16ArrayCid: | 1453 case kTypedDataUint16ArrayCid: |
| 1454 locs->set_in(2, Location::WritableRegister()); | 1454 locs->set_in(2, Location::RequiresRegister()); |
| 1455 break; | 1455 break; |
| 1456 case kTypedDataInt32ArrayCid: | 1456 case kTypedDataInt32ArrayCid: |
| 1457 case kTypedDataUint32ArrayCid: | 1457 case kTypedDataUint32ArrayCid: |
| 1458 // For smis, use a writable register because the value must be untagged | 1458 // Smis are untagged in TMP register. Mints are stored in register pairs. |
| 1459 // before storing. Mints are stored in register pairs. | |
| 1460 if (value()->IsSmiValue()) { | 1459 if (value()->IsSmiValue()) { |
| 1461 locs->set_in(2, Location::WritableRegister()); | 1460 locs->set_in(2, Location::RequiresRegister()); |
| 1462 } else { | 1461 } else { |
| 1463 // We only move the lower 32-bits so we don't care where the high bits | 1462 // We only move the lower 32-bits so we don't care where the high bits |
| 1464 // are located. | 1463 // are located. |
| 1465 locs->set_in(2, Location::Pair(Location::RequiresRegister(), | 1464 locs->set_in(2, Location::Pair(Location::RequiresRegister(), |
| 1466 Location::Any())); | 1465 Location::Any())); |
| 1467 } | 1466 } |
| 1468 break; | 1467 break; |
| 1469 case kTypedDataFloat32ArrayCid: | 1468 case kTypedDataFloat32ArrayCid: |
| 1470 // Need low register (<= Q7). | 1469 // Need low register (<= Q7). |
| 1471 locs->set_in(2, Location::FpuRegisterLocation(Q7)); | 1470 locs->set_in(2, Location::FpuRegisterLocation(Q7)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 case kTypedDataInt8ArrayCid: | 1512 case kTypedDataInt8ArrayCid: |
| 1514 case kTypedDataUint8ArrayCid: | 1513 case kTypedDataUint8ArrayCid: |
| 1515 case kExternalTypedDataUint8ArrayCid: | 1514 case kExternalTypedDataUint8ArrayCid: |
| 1516 case kOneByteStringCid: { | 1515 case kOneByteStringCid: { |
| 1517 if (locs()->in(2).IsConstant()) { | 1516 if (locs()->in(2).IsConstant()) { |
| 1518 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1517 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1519 __ LoadImmediate(IP, static_cast<int8_t>(constant.Value())); | 1518 __ LoadImmediate(IP, static_cast<int8_t>(constant.Value())); |
| 1520 __ strb(IP, element_address); | 1519 __ strb(IP, element_address); |
| 1521 } else { | 1520 } else { |
| 1522 const Register value = locs()->in(2).reg(); | 1521 const Register value = locs()->in(2).reg(); |
| 1523 __ SmiUntag(value); | 1522 __ SmiUntag(IP, value); |
| 1524 __ strb(value, element_address); | 1523 __ strb(IP, element_address); |
| 1525 } | 1524 } |
| 1526 break; | 1525 break; |
| 1527 } | 1526 } |
| 1528 case kTypedDataUint8ClampedArrayCid: | 1527 case kTypedDataUint8ClampedArrayCid: |
| 1529 case kExternalTypedDataUint8ClampedArrayCid: { | 1528 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1530 if (locs()->in(2).IsConstant()) { | 1529 if (locs()->in(2).IsConstant()) { |
| 1531 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1530 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1532 intptr_t value = constant.Value(); | 1531 intptr_t value = constant.Value(); |
| 1533 // Clamp to 0x0 or 0xFF respectively. | 1532 // Clamp to 0x0 or 0xFF respectively. |
| 1534 if (value > 0xFF) { | 1533 if (value > 0xFF) { |
| 1535 value = 0xFF; | 1534 value = 0xFF; |
| 1536 } else if (value < 0) { | 1535 } else if (value < 0) { |
| 1537 value = 0; | 1536 value = 0; |
| 1538 } | 1537 } |
| 1539 __ LoadImmediate(IP, static_cast<int8_t>(value)); | 1538 __ LoadImmediate(IP, static_cast<int8_t>(value)); |
| 1540 __ strb(IP, element_address); | 1539 __ strb(IP, element_address); |
| 1541 } else { | 1540 } else { |
| 1542 const Register value = locs()->in(2).reg(); | 1541 const Register value = locs()->in(2).reg(); |
| 1543 Label store_value; | 1542 __ LoadImmediate(IP, 0x1FE); // Smi 0xFF. |
| 1544 __ SmiUntag(value); | 1543 __ cmp(value, Operand(IP)); // Compare Smi value and smi 0xFF. |
| 1545 __ cmp(value, Operand(0xFF)); | |
| 1546 // Clamp to 0x00 or 0xFF respectively. | 1544 // Clamp to 0x00 or 0xFF respectively. |
| 1547 __ b(&store_value, LS); | 1545 __ mov(IP, Operand(0), LE); // IP = value <= 0x1FE ? 0 : 0x1FE. |
| 1548 __ mov(value, Operand(0x00), LE); | 1546 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. |
| 1549 __ mov(value, Operand(0xFF), GT); | 1547 __ SmiUntag(IP); |
| 1550 __ Bind(&store_value); | 1548 __ strb(IP, element_address); |
| 1551 __ strb(value, element_address); | |
| 1552 } | 1549 } |
| 1553 break; | 1550 break; |
| 1554 } | 1551 } |
| 1555 case kTypedDataInt16ArrayCid: | 1552 case kTypedDataInt16ArrayCid: |
| 1556 case kTypedDataUint16ArrayCid: { | 1553 case kTypedDataUint16ArrayCid: { |
| 1557 const Register value = locs()->in(2).reg(); | 1554 const Register value = locs()->in(2).reg(); |
| 1558 __ SmiUntag(value); | 1555 __ SmiUntag(IP, value); |
| 1559 __ strh(value, element_address); | 1556 __ strh(IP, element_address); |
| 1560 break; | 1557 break; |
| 1561 } | 1558 } |
| 1562 case kTypedDataInt32ArrayCid: | 1559 case kTypedDataInt32ArrayCid: |
| 1563 case kTypedDataUint32ArrayCid: { | 1560 case kTypedDataUint32ArrayCid: { |
| 1564 if (value()->IsSmiValue()) { | 1561 if (value()->IsSmiValue()) { |
| 1565 ASSERT(RequiredInputRepresentation(2) == kTagged); | 1562 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 1566 const Register value = locs()->in(2).reg(); | 1563 const Register value = locs()->in(2).reg(); |
| 1567 __ SmiUntag(value); | 1564 __ SmiUntag(IP, value); |
| 1568 __ str(value, element_address); | 1565 __ str(IP, element_address); |
| 1569 } else { | 1566 } else { |
| 1570 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); | 1567 ASSERT(RequiredInputRepresentation(2) == kUnboxedMint); |
| 1571 PairLocation* value_pair = locs()->in(2).AsPairLocation(); | 1568 PairLocation* value_pair = locs()->in(2).AsPairLocation(); |
| 1572 Register value1 = value_pair->At(0).reg(); | 1569 Register value1 = value_pair->At(0).reg(); |
| 1573 __ str(value1, element_address); | 1570 __ str(value1, element_address); |
| 1574 } | 1571 } |
| 1575 break; | 1572 break; |
| 1576 } | 1573 } |
| 1577 case kTypedDataFloat32ArrayCid: { | 1574 case kTypedDataFloat32ArrayCid: { |
| 1578 const SRegister value_reg = | 1575 const SRegister value_reg = |
| (...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2982 return; | 2979 return; |
| 2983 } | 2980 } |
| 2984 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2981 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2985 const bool right_needs_check = | 2982 const bool right_needs_check = |
| 2986 (right_range == NULL) || | 2983 (right_range == NULL) || |
| 2987 !right_range->IsWithin(0, max_right - 1); | 2984 !right_range->IsWithin(0, max_right - 1); |
| 2988 if (right_needs_check) { | 2985 if (right_needs_check) { |
| 2989 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); | 2986 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(max_right)))); |
| 2990 __ b(deopt, CS); | 2987 __ b(deopt, CS); |
| 2991 } | 2988 } |
| 2992 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 2989 __ SmiUntag(IP, right); |
| 2993 __ Lsl(result, left, IP); | 2990 __ Lsl(result, left, IP); |
| 2994 } | 2991 } |
| 2995 return; | 2992 return; |
| 2996 } | 2993 } |
| 2997 | 2994 |
| 2998 const bool right_needs_check = | 2995 const bool right_needs_check = |
| 2999 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); | 2996 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); |
| 3000 if (is_truncating) { | 2997 if (is_truncating) { |
| 3001 if (right_needs_check) { | 2998 if (right_needs_check) { |
| 3002 const bool right_may_be_negative = | 2999 const bool right_may_be_negative = |
| 3003 (right_range == NULL) || | 3000 (right_range == NULL) || |
| 3004 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); | 3001 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); |
| 3005 if (right_may_be_negative) { | 3002 if (right_may_be_negative) { |
| 3006 ASSERT(shift_left->CanDeoptimize()); | 3003 ASSERT(shift_left->CanDeoptimize()); |
| 3007 __ cmp(right, Operand(0)); | 3004 __ cmp(right, Operand(0)); |
| 3008 __ b(deopt, MI); | 3005 __ b(deopt, MI); |
| 3009 } | 3006 } |
| 3010 | 3007 |
| 3011 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 3008 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 3012 __ mov(result, Operand(0), CS); | 3009 __ mov(result, Operand(0), CS); |
| 3013 __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC. | 3010 __ SmiUntag(IP, right, CC); // SmiUntag right into IP if CC. |
| 3014 __ Lsl(result, left, IP, CC); | 3011 __ Lsl(result, left, IP, CC); |
| 3015 } else { | 3012 } else { |
| 3016 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3013 __ SmiUntag(IP, right); |
| 3017 __ Lsl(result, left, IP); | 3014 __ Lsl(result, left, IP); |
| 3018 } | 3015 } |
| 3019 } else { | 3016 } else { |
| 3020 if (right_needs_check) { | 3017 if (right_needs_check) { |
| 3021 ASSERT(shift_left->CanDeoptimize()); | 3018 ASSERT(shift_left->CanDeoptimize()); |
| 3022 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 3019 __ cmp(right, Operand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 3023 __ b(deopt, CS); | 3020 __ b(deopt, CS); |
| 3024 } | 3021 } |
| 3025 // Left is not a constant. | 3022 // Left is not a constant. |
| 3026 // Check if count too large for handling it inlined. | 3023 // Check if count too large for handling it inlined. |
| 3027 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3024 __ SmiUntag(IP, right); |
| 3028 // Overflow test (preserve left, right, and IP); | 3025 // Overflow test (preserve left, right, and IP); |
| 3029 const Register temp = locs.temp(0).reg(); | 3026 const Register temp = locs.temp(0).reg(); |
| 3030 __ Lsl(temp, left, IP); | 3027 __ Lsl(temp, left, IP); |
| 3031 __ cmp(left, Operand(temp, ASR, IP)); | 3028 __ cmp(left, Operand(temp, ASR, IP)); |
| 3032 __ b(deopt, NE); // Overflow. | 3029 __ b(deopt, NE); // Overflow. |
| 3033 // Shift for result now we know there is no overflow. | 3030 // Shift for result now we know there is no overflow. |
| 3034 __ Lsl(result, left, IP); | 3031 __ Lsl(result, left, IP); |
| 3035 } | 3032 } |
| 3036 } | 3033 } |
| 3037 | 3034 |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3268 case Token::kSUB: { | 3265 case Token::kSUB: { |
| 3269 if (deopt == NULL) { | 3266 if (deopt == NULL) { |
| 3270 __ sub(result, left, Operand(right)); | 3267 __ sub(result, left, Operand(right)); |
| 3271 } else { | 3268 } else { |
| 3272 __ subs(result, left, Operand(right)); | 3269 __ subs(result, left, Operand(right)); |
| 3273 __ b(deopt, VS); | 3270 __ b(deopt, VS); |
| 3274 } | 3271 } |
| 3275 break; | 3272 break; |
| 3276 } | 3273 } |
| 3277 case Token::kMUL: { | 3274 case Token::kMUL: { |
| 3278 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP. | 3275 __ SmiUntag(IP, left); |
| 3279 if (deopt == NULL) { | 3276 if (deopt == NULL) { |
| 3280 __ mul(result, IP, right); | 3277 __ mul(result, IP, right); |
| 3281 } else { | 3278 } else { |
| 3282 if (TargetCPUFeatures::arm_version() == ARMv7) { | 3279 if (TargetCPUFeatures::arm_version() == ARMv7) { |
| 3283 __ smull(result, IP, IP, right); | 3280 __ smull(result, IP, IP, right); |
| 3284 // IP: result bits 32..63. | 3281 // IP: result bits 32..63. |
| 3285 __ cmp(IP, Operand(result, ASR, 31)); | 3282 __ cmp(IP, Operand(result, ASR, 31)); |
| 3286 __ b(deopt, NE); | 3283 __ b(deopt, NE); |
| 3287 } else { | 3284 } else { |
| 3288 const QRegister qtmp = locs()->temp(0).fpu_reg(); | 3285 const QRegister qtmp = locs()->temp(0).fpu_reg(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3310 break; | 3307 break; |
| 3311 } | 3308 } |
| 3312 case Token::kTRUNCDIV: { | 3309 case Token::kTRUNCDIV: { |
| 3313 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3310 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3314 // Handle divide by zero in runtime. | 3311 // Handle divide by zero in runtime. |
| 3315 __ cmp(right, Operand(0)); | 3312 __ cmp(right, Operand(0)); |
| 3316 __ b(deopt, EQ); | 3313 __ b(deopt, EQ); |
| 3317 } | 3314 } |
| 3318 const Register temp = locs()->temp(0).reg(); | 3315 const Register temp = locs()->temp(0).reg(); |
| 3319 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3316 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 3320 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3317 __ SmiUntag(temp, left); |
| 3321 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3318 __ SmiUntag(IP, right); |
| 3322 | 3319 |
| 3323 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3320 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
| 3324 | 3321 |
| 3325 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3322 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3326 // case we cannot tag the result. | 3323 // case we cannot tag the result. |
| 3327 __ CompareImmediate(result, 0x40000000); | 3324 __ CompareImmediate(result, 0x40000000); |
| 3328 __ b(deopt, EQ); | 3325 __ b(deopt, EQ); |
| 3329 __ SmiTag(result); | 3326 __ SmiTag(result); |
| 3330 break; | 3327 break; |
| 3331 } | 3328 } |
| 3332 case Token::kMOD: { | 3329 case Token::kMOD: { |
| 3333 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3330 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3334 // Handle divide by zero in runtime. | 3331 // Handle divide by zero in runtime. |
| 3335 __ cmp(right, Operand(0)); | 3332 __ cmp(right, Operand(0)); |
| 3336 __ b(deopt, EQ); | 3333 __ b(deopt, EQ); |
| 3337 } | 3334 } |
| 3338 const Register temp = locs()->temp(0).reg(); | 3335 const Register temp = locs()->temp(0).reg(); |
| 3339 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 3336 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 3340 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3337 __ SmiUntag(temp, left); |
| 3341 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3338 __ SmiUntag(IP, right); |
| 3342 | 3339 |
| 3343 __ IntegerDivide(result, temp, IP, dtemp, DTMP); | 3340 __ IntegerDivide(result, temp, IP, dtemp, DTMP); |
| 3344 | 3341 |
| 3345 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3342 __ SmiUntag(IP, right); |
| 3346 __ mls(result, IP, result, temp); // result <- left - right * result | 3343 __ mls(result, IP, result, temp); // result <- left - right * result |
| 3347 __ SmiTag(result); | 3344 __ SmiTag(result); |
| 3348 // res = left % right; | 3345 // res = left % right; |
| 3349 // if (res < 0) { | 3346 // if (res < 0) { |
| 3350 // if (right < 0) { | 3347 // if (right < 0) { |
| 3351 // res = res - right; | 3348 // res = res - right; |
| 3352 // } else { | 3349 // } else { |
| 3353 // res = res + right; | 3350 // res = res + right; |
| 3354 // } | 3351 // } |
| 3355 // } | 3352 // } |
| 3356 Label done; | 3353 Label done; |
| 3357 __ cmp(result, Operand(0)); | 3354 __ cmp(result, Operand(0)); |
| 3358 __ b(&done, GE); | 3355 __ b(&done, GE); |
| 3359 // Result is negative, adjust it. | 3356 // Result is negative, adjust it. |
| 3360 __ cmp(right, Operand(0)); | 3357 __ cmp(right, Operand(0)); |
| 3361 __ sub(result, result, Operand(right), LT); | 3358 __ sub(result, result, Operand(right), LT); |
| 3362 __ add(result, result, Operand(right), GE); | 3359 __ add(result, result, Operand(right), GE); |
| 3363 __ Bind(&done); | 3360 __ Bind(&done); |
| 3364 break; | 3361 break; |
| 3365 } | 3362 } |
| 3366 case Token::kSHR: { | 3363 case Token::kSHR: { |
| 3367 if (CanDeoptimize()) { | 3364 if (CanDeoptimize()) { |
| 3368 __ CompareImmediate(right, 0); | 3365 __ CompareImmediate(right, 0); |
| 3369 __ b(deopt, LT); | 3366 __ b(deopt, LT); |
| 3370 } | 3367 } |
| 3371 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 3368 __ SmiUntag(IP, right); |
| 3372 // sarl operation masks the count to 5 bits. | 3369 // sarl operation masks the count to 5 bits. |
| 3373 const intptr_t kCountLimit = 0x1F; | 3370 const intptr_t kCountLimit = 0x1F; |
| 3374 if ((right_range == NULL) || | 3371 if ((right_range == NULL) || |
| 3375 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 3372 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 3376 __ CompareImmediate(IP, kCountLimit); | 3373 __ CompareImmediate(IP, kCountLimit); |
| 3377 __ LoadImmediate(IP, kCountLimit, GT); | 3374 __ LoadImmediate(IP, kCountLimit, GT); |
| 3378 } | 3375 } |
| 3379 const Register temp = locs()->temp(0).reg(); | 3376 const Register temp = locs()->temp(0).reg(); |
| 3380 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 3377 __ SmiUntag(temp, left); |
| 3381 __ Asr(result, temp, IP); | 3378 __ Asr(result, temp, IP); |
| 3382 __ SmiTag(result); | 3379 __ SmiTag(result); |
| 3383 break; | 3380 break; |
| 3384 } | 3381 } |
| 3385 case Token::kDIV: { | 3382 case Token::kDIV: { |
| 3386 // Dispatches to 'Double./'. | 3383 // Dispatches to 'Double./'. |
| 3387 // TODO(srdjan): Implement as conversion to double and double division. | 3384 // TODO(srdjan): Implement as conversion to double and double division. |
| 3388 UNREACHABLE(); | 3385 UNREACHABLE(); |
| 3389 break; | 3386 break; |
| 3390 } | 3387 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3467 __ Bind(slow_path->exit_label()); | 3464 __ Bind(slow_path->exit_label()); |
| 3468 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); | 3465 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); |
| 3469 } | 3466 } |
| 3470 | 3467 |
| 3471 | 3468 |
| 3472 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, | 3469 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, |
| 3473 bool opt) const { | 3470 bool opt) const { |
| 3474 const intptr_t kNumInputs = 1; | 3471 const intptr_t kNumInputs = 1; |
| 3475 const intptr_t value_cid = value()->Type()->ToCid(); | 3472 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3476 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); | 3473 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid)); |
| 3477 const bool needs_writable_input = (value_cid == kSmiCid); | |
| 3478 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3474 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
| 3479 LocationSummary* summary = new(isolate) LocationSummary( | 3475 LocationSummary* summary = new(isolate) LocationSummary( |
| 3480 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3476 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3481 summary->set_in(0, needs_writable_input | 3477 summary->set_in(0, Location::RequiresRegister()); |
| 3482 ? Location::WritableRegister() | |
| 3483 : Location::RequiresRegister()); | |
| 3484 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); | 3478 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 3485 summary->set_out(0, Location::RequiresFpuRegister()); | 3479 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3486 return summary; | 3480 return summary; |
| 3487 } | 3481 } |
| 3488 | 3482 |
| 3489 | 3483 |
| 3490 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3484 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3491 CompileType* value_type = value()->Type(); | 3485 CompileType* value_type = value()->Type(); |
| 3492 const intptr_t value_cid = value_type->ToCid(); | 3486 const intptr_t value_cid = value_type->ToCid(); |
| 3493 const Register value = locs()->in(0).reg(); | 3487 const Register value = locs()->in(0).reg(); |
| 3494 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 3488 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 3495 | 3489 |
| 3496 if (value_cid == kDoubleCid) { | 3490 if (value_cid == kDoubleCid) { |
| 3497 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); | 3491 __ LoadDFromOffset(result, value, Double::value_offset() - kHeapObjectTag); |
| 3498 } else if (value_cid == kSmiCid) { | 3492 } else if (value_cid == kSmiCid) { |
| 3499 __ SmiUntag(value); // Untag input before conversion. | 3493 __ SmiUntag(IP, value); |
| 3500 __ vmovsr(STMP, value); | 3494 __ vmovsr(STMP, IP); |
| 3501 __ vcvtdi(result, STMP); | 3495 __ vcvtdi(result, STMP); |
| 3502 } else { | 3496 } else { |
| 3503 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 3497 Label* deopt = compiler->AddDeoptStub(deopt_id_, |
| 3504 ICData::kDeoptBinaryDoubleOp); | 3498 ICData::kDeoptBinaryDoubleOp); |
| 3505 const Register temp = locs()->temp(0).reg(); | 3499 const Register temp = locs()->temp(0).reg(); |
| 3506 if (value_type->is_nullable() && | 3500 if (value_type->is_nullable() && |
| 3507 (value_type->ToNullableCid() == kDoubleCid)) { | 3501 (value_type->ToNullableCid() == kDoubleCid)) { |
| 3508 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); | 3502 __ CompareImmediate(value, reinterpret_cast<intptr_t>(Object::null())); |
| 3509 __ b(deopt, EQ); | 3503 __ b(deopt, EQ); |
| 3510 // It must be double now. | 3504 // It must be double now. |
| 3511 __ LoadDFromOffset(result, value, | 3505 __ LoadDFromOffset(result, value, |
| 3512 Double::value_offset() - kHeapObjectTag); | 3506 Double::value_offset() - kHeapObjectTag); |
| 3513 } else { | 3507 } else { |
| 3514 Label is_smi, done; | 3508 Label is_smi, done; |
| 3515 __ tst(value, Operand(kSmiTagMask)); | 3509 __ tst(value, Operand(kSmiTagMask)); |
| 3516 __ b(&is_smi, EQ); | 3510 __ b(&is_smi, EQ); |
| 3517 __ CompareClassId(value, kDoubleCid, temp); | 3511 __ CompareClassId(value, kDoubleCid, temp); |
| 3518 __ b(deopt, NE); | 3512 __ b(deopt, NE); |
| 3519 __ LoadDFromOffset(result, value, | 3513 __ LoadDFromOffset(result, value, |
| 3520 Double::value_offset() - kHeapObjectTag); | 3514 Double::value_offset() - kHeapObjectTag); |
| 3521 __ b(&done); | 3515 __ b(&done); |
| 3522 __ Bind(&is_smi); | 3516 __ Bind(&is_smi); |
| 3523 // TODO(regis): Why do we preserve value here but not above? | 3517 __ SmiUntag(IP, value); |
| 3524 __ mov(IP, Operand(value, ASR, 1)); // Copy and untag. | |
| 3525 __ vmovsr(STMP, IP); | 3518 __ vmovsr(STMP, IP); |
| 3526 __ vcvtdi(result, STMP); | 3519 __ vcvtdi(result, STMP); |
| 3527 __ Bind(&done); | 3520 __ Bind(&done); |
| 3528 } | 3521 } |
| 3529 } | 3522 } |
| 3530 } | 3523 } |
| 3531 | 3524 |
| 3532 | 3525 |
| 3533 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, | 3526 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, |
| 3534 bool opt) const { | 3527 bool opt) const { |
| (...skipping 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5126 __ vnegd(result, value); | 5119 __ vnegd(result, value); |
| 5127 } | 5120 } |
| 5128 | 5121 |
| 5129 | 5122 |
| 5130 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, | 5123 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, |
| 5131 bool opt) const { | 5124 bool opt) const { |
| 5132 const intptr_t kNumInputs = 1; | 5125 const intptr_t kNumInputs = 1; |
| 5133 const intptr_t kNumTemps = 0; | 5126 const intptr_t kNumTemps = 0; |
| 5134 LocationSummary* result = new(isolate) LocationSummary( | 5127 LocationSummary* result = new(isolate) LocationSummary( |
| 5135 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5128 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5136 result->set_in(0, Location::WritableRegister()); | 5129 result->set_in(0, Location::RequiresRegister()); |
| 5137 result->set_out(0, Location::RequiresFpuRegister()); | 5130 result->set_out(0, Location::RequiresFpuRegister()); |
| 5138 return result; | 5131 return result; |
| 5139 } | 5132 } |
| 5140 | 5133 |
| 5141 | 5134 |
| 5142 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5135 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5143 const Register value = locs()->in(0).reg(); | 5136 const Register value = locs()->in(0).reg(); |
| 5144 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5137 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5145 __ SmiUntag(value); | 5138 __ SmiUntag(IP, value); |
| 5146 __ vmovsr(STMP, value); | 5139 __ vmovsr(STMP, IP); |
| 5147 __ vcvtdi(result, STMP); | 5140 __ vcvtdi(result, STMP); |
| 5148 } | 5141 } |
| 5149 | 5142 |
| 5150 | 5143 |
| 5151 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Isolate* isolate, | 5144 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Isolate* isolate, |
| 5152 bool opt) const { | 5145 bool opt) const { |
| 5153 const intptr_t kNumInputs = 1; | 5146 const intptr_t kNumInputs = 1; |
| 5154 const intptr_t kNumTemps = 0; | 5147 const intptr_t kNumTemps = 0; |
| 5155 LocationSummary* result = new(isolate) LocationSummary( | 5148 LocationSummary* result = new(isolate) LocationSummary( |
| 5156 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); | 5149 isolate, kNumInputs, kNumTemps, LocationSummary::kCall); |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5555 const Register result_mod = pair->At(1).reg(); | 5548 const Register result_mod = pair->At(1).reg(); |
| 5556 Range* right_range = InputAt(1)->definition()->range(); | 5549 Range* right_range = InputAt(1)->definition()->range(); |
| 5557 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 5550 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 5558 // Handle divide by zero in runtime. | 5551 // Handle divide by zero in runtime. |
| 5559 __ cmp(right, Operand(0)); | 5552 __ cmp(right, Operand(0)); |
| 5560 __ b(deopt, EQ); | 5553 __ b(deopt, EQ); |
| 5561 } | 5554 } |
| 5562 const Register temp = locs()->temp(0).reg(); | 5555 const Register temp = locs()->temp(0).reg(); |
| 5563 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); | 5556 const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg()); |
| 5564 | 5557 |
| 5565 __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp. | 5558 __ SmiUntag(temp, left); |
| 5566 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 5559 __ SmiUntag(IP, right); |
| 5567 | 5560 |
| 5568 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); | 5561 __ IntegerDivide(result_div, temp, IP, dtemp, DTMP); |
| 5569 | 5562 |
| 5570 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5563 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 5571 // case we cannot tag the result. | 5564 // case we cannot tag the result. |
| 5572 __ CompareImmediate(result_div, 0x40000000); | 5565 __ CompareImmediate(result_div, 0x40000000); |
| 5573 __ b(deopt, EQ); | 5566 __ b(deopt, EQ); |
| 5574 __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP. | 5567 __ SmiUntag(IP, right); |
| 5575 // result_mod <- left - right * result_div. | 5568 // result_mod <- left - right * result_div. |
| 5576 __ mls(result_mod, IP, result_div, temp); | 5569 __ mls(result_mod, IP, result_div, temp); |
| 5577 __ SmiTag(result_div); | 5570 __ SmiTag(result_div); |
| 5578 __ SmiTag(result_mod); | 5571 __ SmiTag(result_mod); |
| 5579 // Correct MOD result: | 5572 // Correct MOD result: |
| 5580 // res = left % right; | 5573 // res = left % right; |
| 5581 // if (res < 0) { | 5574 // if (res < 0) { |
| 5582 // if (right < 0) { | 5575 // if (right < 0) { |
| 5583 // res = res - right; | 5576 // res = res - right; |
| 5584 // } else { | 5577 // } else { |
| (...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6402 compiler->GenerateCall(token_pos(), | 6395 compiler->GenerateCall(token_pos(), |
| 6403 &label, | 6396 &label, |
| 6404 PcDescriptors::kOther, | 6397 PcDescriptors::kOther, |
| 6405 locs()); | 6398 locs()); |
| 6406 __ Drop(ArgumentCount()); // Discard arguments. | 6399 __ Drop(ArgumentCount()); // Discard arguments. |
| 6407 } | 6400 } |
| 6408 | 6401 |
| 6409 } // namespace dart | 6402 } // namespace dart |
| 6410 | 6403 |
| 6411 #endif // defined TARGET_ARCH_ARM | 6404 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |