| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 summary->set_out(0, Location::RequiresRegister()); | 661 summary->set_out(0, Location::RequiresRegister()); |
| 662 return summary; | 662 return summary; |
| 663 } | 663 } |
| 664 | 664 |
| 665 | 665 |
| 666 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 666 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 667 BranchLabels labels) { | 667 BranchLabels labels) { |
| 668 if (operation_cid() == kSmiCid) { | 668 if (operation_cid() == kSmiCid) { |
| 669 return EmitSmiComparisonOp(compiler, locs(), kind()); | 669 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 670 } else { | 670 } else { |
| 671 UNIMPLEMENTED(); | 671 ASSERT(operation_cid() == kDoubleCid); |
| 672 return VS; | 672 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 673 } | 673 } |
| 674 } | 674 } |
| 675 | 675 |
| 676 | 676 |
| 677 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 677 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 678 Label is_true, is_false; | 678 Label is_true, is_false; |
| 679 BranchLabels labels = { &is_true, &is_false, &is_false }; | 679 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 680 Condition true_condition = EmitComparisonCode(compiler, labels); | 680 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 681 EmitBranchOnCondition(compiler, true_condition, labels); | 681 EmitBranchOnCondition(compiler, true_condition, labels); |
| 682 // TODO(zra): instead of branching, use the csel instruction to get | 682 // TODO(zra): instead of branching, use the csel instruction to get |
| (...skipping 1143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 temp2); | 1826 temp2); |
| 1827 __ Bind(©_double); | 1827 __ Bind(©_double); |
| 1828 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset()); | 1828 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset()); |
| 1829 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset()); | 1829 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset()); |
| 1830 __ b(&skip_store); | 1830 __ b(&skip_store); |
| 1831 } | 1831 } |
| 1832 | 1832 |
| 1833 // TODO(zra): Implement these when we add simd loads and stores. | 1833 // TODO(zra): Implement these when we add simd loads and stores. |
| 1834 { | 1834 { |
| 1835 __ Bind(&store_float32x4); | 1835 __ Bind(&store_float32x4); |
| 1836 __ hlt(0); // Unimplemented. | 1836 __ Stop("Float32x4 Unimplemented"); |
| 1837 } | 1837 } |
| 1838 | 1838 |
| 1839 { | 1839 { |
| 1840 __ Bind(&store_float64x2); | 1840 __ Bind(&store_float64x2); |
| 1841 __ hlt(0); // Unimplemented. | 1841 __ Stop("Float64x2 Unimplemented"); |
| 1842 } | 1842 } |
| 1843 | 1843 |
| 1844 __ Bind(&store_pointer); | 1844 __ Bind(&store_pointer); |
| 1845 } | 1845 } |
| 1846 | 1846 |
| 1847 if (ShouldEmitStoreBarrier()) { | 1847 if (ShouldEmitStoreBarrier()) { |
| 1848 Register value_reg = locs()->in(1).reg(); | 1848 Register value_reg = locs()->in(1).reg(); |
| 1849 __ StoreIntoObject(instance_reg, | 1849 __ StoreIntoObject(instance_reg, |
| 1850 FieldAddress(instance_reg, offset_in_bytes_), | 1850 FieldAddress(instance_reg, offset_in_bytes_), |
| 1851 value_reg, | 1851 value_reg, |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2095 __ Bind(slow_path->exit_label()); | 2095 __ Bind(slow_path->exit_label()); |
| 2096 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2096 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 2097 __ LoadDFieldFromOffset(value, temp, Double::value_offset()); | 2097 __ LoadDFieldFromOffset(value, temp, Double::value_offset()); |
| 2098 __ StoreDFieldToOffset(value, result_reg, Double::value_offset()); | 2098 __ StoreDFieldToOffset(value, result_reg, Double::value_offset()); |
| 2099 __ b(&done); | 2099 __ b(&done); |
| 2100 } | 2100 } |
| 2101 | 2101 |
| 2102 // TODO(zra): Implement these when we add simd loads and stores. | 2102 // TODO(zra): Implement these when we add simd loads and stores. |
| 2103 { | 2103 { |
| 2104 __ Bind(&load_float32x4); | 2104 __ Bind(&load_float32x4); |
| 2105 __ hlt(0); // Unimplemented. | 2105 __ Stop("Float32x4 Unimplemented"); |
| 2106 } | 2106 } |
| 2107 | 2107 |
| 2108 { | 2108 { |
| 2109 __ Bind(&load_float64x2); | 2109 __ Bind(&load_float64x2); |
| 2110 __ hlt(0); // Unimplemented. | 2110 __ Stop("Float64x2 Unimplemented"); |
| 2111 } | 2111 } |
| 2112 | 2112 |
| 2113 __ Bind(&load_pointer); | 2113 __ Bind(&load_pointer); |
| 2114 } | 2114 } |
| 2115 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 2115 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
| 2116 __ Bind(&done); | 2116 __ Bind(&done); |
| 2117 } | 2117 } |
| 2118 | 2118 |
| 2119 | 2119 |
| 2120 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 2120 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
| (...skipping 1229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3350 return NULL; | 3350 return NULL; |
| 3351 } | 3351 } |
| 3352 | 3352 |
| 3353 | 3353 |
| 3354 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3354 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3355 UNIMPLEMENTED(); | 3355 UNIMPLEMENTED(); |
| 3356 } | 3356 } |
| 3357 | 3357 |
| 3358 | 3358 |
| 3359 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { | 3359 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { |
| 3360 UNIMPLEMENTED(); | 3360 if ((kind() == MathUnaryInstr::kSin) || (kind() == MathUnaryInstr::kCos)) { |
| 3361 return NULL; | 3361 const intptr_t kNumInputs = 1; |
| 3362 const intptr_t kNumTemps = 0; |
| 3363 LocationSummary* summary = |
| 3364 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 3365 summary->set_in(0, Location::FpuRegisterLocation(V0)); |
| 3366 summary->set_out(0, Location::FpuRegisterLocation(V0)); |
| 3367 return summary; |
| 3368 } |
| 3369 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 3370 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 3371 const intptr_t kNumInputs = 1; |
| 3372 const intptr_t kNumTemps = 0; |
| 3373 LocationSummary* summary = |
| 3374 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3375 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3376 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3377 return summary; |
| 3362 } | 3378 } |
| 3363 | 3379 |
| 3364 | 3380 |
| 3365 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3381 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3366 UNIMPLEMENTED(); | 3382 if (kind() == MathUnaryInstr::kSqrt) { |
| 3383 VRegister val = locs()->in(0).fpu_reg(); |
| 3384 VRegister result = locs()->out(0).fpu_reg(); |
| 3385 __ fsqrtd(result, val); |
| 3386 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 3387 VRegister val = locs()->in(0).fpu_reg(); |
| 3388 VRegister result = locs()->out(0).fpu_reg(); |
| 3389 __ fmuld(result, val, val); |
| 3390 } else { |
| 3391 ASSERT((kind() == MathUnaryInstr::kSin) || |
| 3392 (kind() == MathUnaryInstr::kCos)); |
| 3393 __ CallRuntime(TargetFunction(), InputCount()); |
| 3394 } |
| 3367 } | 3395 } |
| 3368 | 3396 |
| 3369 | 3397 |
| 3370 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { | 3398 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { |
| 3371 UNIMPLEMENTED(); | 3399 UNIMPLEMENTED(); |
| 3372 return NULL; | 3400 return NULL; |
| 3373 } | 3401 } |
| 3374 | 3402 |
| 3375 | 3403 |
| 3376 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3404 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3406 // Remove inverted smi-tag. | 3434 // Remove inverted smi-tag. |
| 3407 __ andi(result, result, ~kSmiTagMask); | 3435 __ andi(result, result, ~kSmiTagMask); |
| 3408 break; | 3436 break; |
| 3409 default: | 3437 default: |
| 3410 UNREACHABLE(); | 3438 UNREACHABLE(); |
| 3411 } | 3439 } |
| 3412 } | 3440 } |
| 3413 | 3441 |
| 3414 | 3442 |
| 3415 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { | 3443 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { |
| 3416 UNIMPLEMENTED(); | 3444 const intptr_t kNumInputs = 1; |
| 3417 return NULL; | 3445 const intptr_t kNumTemps = 0; |
| 3446 LocationSummary* summary = |
| 3447 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3448 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3449 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3450 return summary; |
| 3418 } | 3451 } |
| 3419 | 3452 |
| 3420 | 3453 |
| 3421 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3454 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3422 UNIMPLEMENTED(); | 3455 VRegister result = locs()->out(0).fpu_reg(); |
| 3456 VRegister value = locs()->in(0).fpu_reg(); |
| 3457 __ fnegd(result, value); |
| 3423 } | 3458 } |
| 3424 | 3459 |
| 3425 | 3460 |
| 3426 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { | 3461 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3427 UNIMPLEMENTED(); | 3462 const intptr_t kNumInputs = 1; |
| 3428 return NULL; | 3463 const intptr_t kNumTemps = 0; |
| 3464 LocationSummary* result = |
| 3465 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3466 result->set_in(0, Location::WritableRegister()); |
| 3467 result->set_out(0, Location::RequiresFpuRegister()); |
| 3468 return result; |
| 3429 } | 3469 } |
| 3430 | 3470 |
| 3431 | 3471 |
| 3432 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3472 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3433 UNIMPLEMENTED(); | 3473 Register value = locs()->in(0).reg(); |
| 3474 VRegister result = locs()->out(0).fpu_reg(); |
| 3475 __ SmiUntag(value); |
| 3476 __ scvtfd(result, value); |
| 3434 } | 3477 } |
| 3435 | 3478 |
| 3436 | 3479 |
| 3437 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { | 3480 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { |
| 3438 UNIMPLEMENTED(); | 3481 const intptr_t kNumInputs = 1; |
| 3439 return NULL; | 3482 const intptr_t kNumTemps = 0; |
| 3483 LocationSummary* result = |
| 3484 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 3485 result->set_in(0, Location::RegisterLocation(R1)); |
| 3486 result->set_out(0, Location::RegisterLocation(R0)); |
| 3487 return result; |
| 3440 } | 3488 } |
| 3441 | 3489 |
| 3442 | 3490 |
| 3443 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3491 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3444 UNIMPLEMENTED(); | 3492 const Register result = locs()->out(0).reg(); |
| 3493 const Register value_obj = locs()->in(0).reg(); |
| 3494 ASSERT(result == R0); |
| 3495 ASSERT(result != value_obj); |
| 3496 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset()); |
| 3497 |
| 3498 Label do_call, done; |
| 3499 // First check for NaN. Checking for minint after the conversion doesn't work |
| 3500 // on ARM64 because fcvtzds gives 0 for NaN. |
| 3501 __ fcmpd(VTMP, VTMP); |
| 3502 __ b(&do_call, VS); |
| 3503 |
| 3504 __ fcvtzds(result, VTMP); |
| 3505 // Overflow is signaled with minint. |
| 3506 |
| 3507 // Check for overflow and that it fits into Smi. |
| 3508 __ CompareImmediate(result, 0xC000000000000000, PP); |
| 3509 __ b(&do_call, MI); |
| 3510 __ SmiTag(result); |
| 3511 __ b(&done); |
| 3512 __ Bind(&do_call); |
| 3513 __ Push(value_obj); |
| 3514 ASSERT(instance_call()->HasICData()); |
| 3515 const ICData& ic_data = *instance_call()->ic_data(); |
| 3516 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 3517 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 3518 |
| 3519 const intptr_t kNumberOfArguments = 1; |
| 3520 compiler->GenerateStaticCall(deopt_id(), |
| 3521 instance_call()->token_pos(), |
| 3522 target, |
| 3523 kNumberOfArguments, |
| 3524 Object::null_array(), // No argument names., |
| 3525 locs()); |
| 3526 __ Bind(&done); |
| 3445 } | 3527 } |
| 3446 | 3528 |
| 3447 | 3529 |
| 3448 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { | 3530 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { |
| 3449 UNIMPLEMENTED(); | 3531 const intptr_t kNumInputs = 1; |
| 3450 return NULL; | 3532 const intptr_t kNumTemps = 0; |
| 3533 LocationSummary* result = new LocationSummary( |
| 3534 kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3535 result->set_in(0, Location::RequiresFpuRegister()); |
| 3536 result->set_out(0, Location::RequiresRegister()); |
| 3537 return result; |
| 3451 } | 3538 } |
| 3452 | 3539 |
| 3453 | 3540 |
| 3454 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3541 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3455 UNIMPLEMENTED(); | 3542 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 3543 const Register result = locs()->out(0).reg(); |
| 3544 const VRegister value = locs()->in(0).fpu_reg(); |
| 3545 // First check for NaN. Checking for minint after the conversion doesn't work |
| 3546 // on ARM64 because fcvtzds gives 0 for NaN. |
| 3547 // TODO(zra): Check spec that this is true. |
| 3548 __ fcmpd(value, value); |
| 3549 __ b(deopt, VS); |
| 3550 |
| 3551 __ fcvtzds(result, value); |
| 3552 // Check for overflow and that it fits into Smi. |
| 3553 __ CompareImmediate(result, 0xC000000000000000, PP); |
| 3554 __ b(deopt, MI); |
| 3555 __ SmiTag(result); |
| 3456 } | 3556 } |
| 3457 | 3557 |
| 3458 | 3558 |
| 3459 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { | 3559 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { |
| 3460 UNIMPLEMENTED(); | 3560 UNIMPLEMENTED(); |
| 3461 return NULL; | 3561 return NULL; |
| 3462 } | 3562 } |
| 3463 | 3563 |
| 3464 | 3564 |
| 3465 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3565 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3483 return NULL; | 3583 return NULL; |
| 3484 } | 3584 } |
| 3485 | 3585 |
| 3486 | 3586 |
| 3487 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3587 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3488 UNIMPLEMENTED(); | 3588 UNIMPLEMENTED(); |
| 3489 } | 3589 } |
| 3490 | 3590 |
| 3491 | 3591 |
| 3492 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { | 3592 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { |
| 3493 UNIMPLEMENTED(); | 3593 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 3494 return NULL; | 3594 const intptr_t kNumTemps = 0; |
| 3595 LocationSummary* result = |
| 3596 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall); |
| 3597 result->set_in(0, Location::FpuRegisterLocation(V0)); |
| 3598 if (InputCount() == 2) { |
| 3599 result->set_in(1, Location::FpuRegisterLocation(V1)); |
| 3600 } |
| 3601 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 3602 result->AddTemp(Location::FpuRegisterLocation(V30)); |
| 3603 } |
| 3604 result->set_out(0, Location::FpuRegisterLocation(V0)); |
| 3605 return result; |
| 3495 } | 3606 } |
| 3496 | 3607 |
| 3497 | 3608 |
| 3498 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3609 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3499 UNIMPLEMENTED(); | 3610 // For pow-function return NaN if exponent is NaN. |
| 3611 Label skip_call; |
| 3612 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 3613 // Pseudo code: |
| 3614 // if (exponent == 0.0) return 1.0; |
| 3615 // if (base == 1.0) return 1.0; |
| 3616 // if (base.isNaN || exponent.isNaN) { |
| 3617 // return double.NAN; |
| 3618 // } |
| 3619 // if (base != -Infinity && exponent == 0.5) { |
| 3620 // if (base == 0.0) return 0.0; |
| 3621 // return sqrt(value); |
| 3622 // } |
| 3623 const VRegister base = locs()->in(0).fpu_reg(); |
| 3624 const VRegister exp = locs()->in(1).fpu_reg(); |
| 3625 const VRegister result = locs()->out(0).fpu_reg(); |
| 3626 const VRegister saved_base = locs()->temp(0).fpu_reg(); |
| 3627 ASSERT((base == result) && (result != saved_base)); |
| 3628 |
| 3629 Label try_sqrt, check_base, return_nan; |
| 3630 __ fmovdd(saved_base, base); |
| 3631 __ LoadDImmediate(VTMP, 0.0, PP); |
| 3632 __ LoadDImmediate(result, 1.0, PP); |
| 3633 // exponent == 0.0 -> return 1.0; |
| 3634 __ fcmpd(exp, VTMP); |
| 3635 __ b(&check_base, VS); // NaN -> check base. |
| 3636 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
| 3637 |
| 3638 __ Bind(&check_base); |
| 3639 // Note: 'exp' could be NaN. |
| 3640 // base == 1.0 -> return 1.0; |
| 3641 __ fcmpd(saved_base, result); |
| 3642 __ b(&return_nan, VS); |
| 3643 __ b(&skip_call, EQ); // base is 1.0, result is 1.0. |
| 3644 |
| 3645 __ fcmpd(saved_base, exp); |
| 3646 __ b(&try_sqrt, VC); // // Neither 'exp' nor 'base' is NaN. |
| 3647 |
| 3648 __ Bind(&return_nan); |
| 3649 __ LoadDImmediate(result, NAN, PP); |
| 3650 __ b(&skip_call); |
| 3651 |
| 3652 Label do_pow, return_zero; |
| 3653 __ Bind(&try_sqrt); |
| 3654 |
| 3655 // Before calling pow, check if we could use sqrt instead of pow. |
| 3656 __ LoadDImmediate(result, -INFINITY, PP); |
| 3657 |
| 3658 // base == -Infinity -> call pow; |
| 3659 __ fcmpd(saved_base, result); |
| 3660 __ b(&do_pow, EQ); |
| 3661 |
| 3662 // exponent == 0.5 ? |
| 3663 __ LoadDImmediate(result, 0.5, PP); |
| 3664 __ fcmpd(exp, result); |
| 3665 __ b(&do_pow, NE); |
| 3666 |
| 3667 // base == 0 -> return 0; |
| 3668 __ fcmpd(base, VTMP); |
| 3669 __ b(&return_zero, EQ); |
| 3670 |
| 3671 __ fsqrtd(result, saved_base); |
| 3672 __ b(&skip_call); |
| 3673 |
| 3674 __ Bind(&return_zero); |
| 3675 __ fmovdd(result, VTMP); |
| 3676 __ b(&skip_call); |
| 3677 |
| 3678 __ Bind(&do_pow); |
| 3679 __ fmovdd(base, saved_base); // Restore base. |
| 3680 } |
| 3681 |
| 3682 __ CallRuntime(TargetFunction(), InputCount()); |
| 3683 __ Bind(&skip_call); |
| 3500 } | 3684 } |
| 3501 | 3685 |
| 3502 | 3686 |
| 3503 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { | 3687 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { |
| 3504 // Only use this instruction in optimized code. | 3688 // Only use this instruction in optimized code. |
| 3505 ASSERT(opt); | 3689 ASSERT(opt); |
| 3506 const intptr_t kNumInputs = 1; | 3690 const intptr_t kNumInputs = 1; |
| 3507 LocationSummary* summary = | 3691 LocationSummary* summary = |
| 3508 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); | 3692 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); |
| 3509 if (representation() == kUnboxedDouble) { | 3693 if (representation() == kUnboxedDouble) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3543 } else { | 3727 } else { |
| 3544 ASSERT(representation() == kTagged); | 3728 ASSERT(representation() == kTagged); |
| 3545 Register out = locs()->out(0).reg(); | 3729 Register out = locs()->out(0).reg(); |
| 3546 Register in = in_loc.reg(); | 3730 Register in = in_loc.reg(); |
| 3547 __ mov(out, in); | 3731 __ mov(out, in); |
| 3548 } | 3732 } |
| 3549 } | 3733 } |
| 3550 | 3734 |
| 3551 | 3735 |
| 3552 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { | 3736 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { |
| 3737 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 3738 const intptr_t kNumInputs = 2; |
| 3739 const intptr_t kNumTemps = 0; |
| 3740 LocationSummary* summary = |
| 3741 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3742 summary->set_in(0, Location::RequiresRegister()); |
| 3743 summary->set_in(1, Location::RequiresRegister()); |
| 3744 // Output is a pair of registers. |
| 3745 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 3746 Location::RequiresRegister())); |
| 3747 return summary; |
| 3748 } |
| 3553 UNIMPLEMENTED(); | 3749 UNIMPLEMENTED(); |
| 3554 return NULL; | 3750 return NULL; |
| 3555 } | 3751 } |
| 3556 | 3752 |
| 3557 | 3753 |
| 3558 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3754 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3755 Label* deopt = NULL; |
| 3756 if (CanDeoptimize()) { |
| 3757 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 3758 } |
| 3759 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 3760 const Register left = locs()->in(0).reg(); |
| 3761 const Register right = locs()->in(1).reg(); |
| 3762 ASSERT(locs()->out(0).IsPairLocation()); |
| 3763 const PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 3764 const Register result_div = pair->At(0).reg(); |
| 3765 const Register result_mod = pair->At(1).reg(); |
| 3766 const Range* right_range = InputAt(1)->definition()->range(); |
| 3767 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 3768 // Handle divide by zero in runtime. |
| 3769 __ CompareRegisters(right, ZR); |
| 3770 __ b(deopt, EQ); |
| 3771 } |
| 3772 |
| 3773 __ Asr(result_mod, left, kSmiTagSize); // SmiUntag left. |
| 3774 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right. |
| 3775 |
| 3776 __ sdiv(result_div, result_mod, TMP); |
| 3777 |
| 3778 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3779 // case we cannot tag the result. |
| 3780 __ CompareImmediate(result_div, 0x4000000000000000, PP); |
| 3781 __ b(deopt, EQ); |
| 3782 // result_mod <- left - right * result_div. |
| 3783 __ msub(result_mod, TMP, result_div, result_mod); |
| 3784 __ SmiTag(result_div); |
| 3785 __ SmiTag(result_mod); |
| 3786 // Correct MOD result: |
| 3787 // res = left % right; |
| 3788 // if (res < 0) { |
| 3789 // if (right < 0) { |
| 3790 // res = res - right; |
| 3791 // } else { |
| 3792 // res = res + right; |
| 3793 // } |
| 3794 // } |
| 3795 Label done; |
| 3796 __ CompareRegisters(result_mod, ZR);; |
| 3797 __ b(&done, GE); |
| 3798 // Result is negative, adjust it. |
| 3799 __ CompareRegisters(right, ZR); |
| 3800 __ sub(TMP2, result_mod, Operand(right)); |
| 3801 __ add(TMP, result_mod, Operand(right)); |
| 3802 __ csel(result_mod, TMP, TMP2, GE); |
| 3803 __ Bind(&done); |
| 3804 |
| 3805 return; |
| 3806 } |
| 3807 if (kind() == MergedMathInstr::kSinCos) { |
| 3808 UNIMPLEMENTED(); |
| 3809 } |
| 3559 UNIMPLEMENTED(); | 3810 UNIMPLEMENTED(); |
| 3560 } | 3811 } |
| 3561 | 3812 |
| 3562 | 3813 |
| 3563 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 3814 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 3564 bool opt) const { | 3815 bool opt) const { |
| 3565 return MakeCallSummary(); | 3816 return MakeCallSummary(); |
| 3566 } | 3817 } |
| 3567 | 3818 |
| 3568 | 3819 |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4003 compiler->GenerateCall(token_pos(), | 4254 compiler->GenerateCall(token_pos(), |
| 4004 &label, | 4255 &label, |
| 4005 PcDescriptors::kOther, | 4256 PcDescriptors::kOther, |
| 4006 locs()); | 4257 locs()); |
| 4007 __ Drop(ArgumentCount()); // Discard arguments. | 4258 __ Drop(ArgumentCount()); // Discard arguments. |
| 4008 } | 4259 } |
| 4009 | 4260 |
| 4010 } // namespace dart | 4261 } // namespace dart |
| 4011 | 4262 |
| 4012 #endif // defined TARGET_ARCH_ARM64 | 4263 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |