OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/hydrogen-osr.h" | 10 #include "src/hydrogen-osr.h" |
(...skipping 3586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3597 | 3597 |
3598 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3598 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
3599 XMMRegister xmm_scratch = double_scratch0(); | 3599 XMMRegister xmm_scratch = double_scratch0(); |
3600 Register output_reg = ToRegister(instr->result()); | 3600 Register output_reg = ToRegister(instr->result()); |
3601 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3601 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3602 | 3602 |
3603 if (CpuFeatures::IsSupported(SSE4_1)) { | 3603 if (CpuFeatures::IsSupported(SSE4_1)) { |
3604 CpuFeatureScope scope(masm(), SSE4_1); | 3604 CpuFeatureScope scope(masm(), SSE4_1); |
3605 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3605 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3606 // Deoptimize if minus zero. | 3606 // Deoptimize if minus zero. |
3607 __ movq(output_reg, input_reg); | 3607 __ Movq(output_reg, input_reg); |
3608 __ subq(output_reg, Immediate(1)); | 3608 __ subq(output_reg, Immediate(1)); |
3609 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); | 3609 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); |
3610 } | 3610 } |
3611 __ roundsd(xmm_scratch, input_reg, kRoundDown); | 3611 __ roundsd(xmm_scratch, input_reg, kRoundDown); |
3612 __ cvttsd2si(output_reg, xmm_scratch); | 3612 __ cvttsd2si(output_reg, xmm_scratch); |
3613 __ cmpl(output_reg, Immediate(0x1)); | 3613 __ cmpl(output_reg, Immediate(0x1)); |
3614 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3614 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3615 } else { | 3615 } else { |
3616 Label negative_sign, done; | 3616 Label negative_sign, done; |
3617 // Deoptimize on unordered. | 3617 // Deoptimize on unordered. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3658 const XMMRegister xmm_scratch = double_scratch0(); | 3658 const XMMRegister xmm_scratch = double_scratch0(); |
3659 Register output_reg = ToRegister(instr->result()); | 3659 Register output_reg = ToRegister(instr->result()); |
3660 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3660 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3661 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 3661 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
3662 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 | 3662 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 |
3663 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3663 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
3664 | 3664 |
3665 Label done, round_to_zero, below_one_half; | 3665 Label done, round_to_zero, below_one_half; |
3666 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3666 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
3667 __ movq(kScratchRegister, one_half); | 3667 __ movq(kScratchRegister, one_half); |
3668 __ movq(xmm_scratch, kScratchRegister); | 3668 __ Movq(xmm_scratch, kScratchRegister); |
3669 __ ucomisd(xmm_scratch, input_reg); | 3669 __ ucomisd(xmm_scratch, input_reg); |
3670 __ j(above, &below_one_half, Label::kNear); | 3670 __ j(above, &below_one_half, Label::kNear); |
3671 | 3671 |
3672 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3672 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
3673 __ addsd(xmm_scratch, input_reg); | 3673 __ addsd(xmm_scratch, input_reg); |
3674 __ cvttsd2si(output_reg, xmm_scratch); | 3674 __ cvttsd2si(output_reg, xmm_scratch); |
3675 // Overflow is signalled with minint. | 3675 // Overflow is signalled with minint. |
3676 __ cmpl(output_reg, Immediate(0x1)); | 3676 __ cmpl(output_reg, Immediate(0x1)); |
3677 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3677 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3678 __ jmp(&done, dist); | 3678 __ jmp(&done, dist); |
3679 | 3679 |
3680 __ bind(&below_one_half); | 3680 __ bind(&below_one_half); |
3681 __ movq(kScratchRegister, minus_one_half); | 3681 __ movq(kScratchRegister, minus_one_half); |
3682 __ movq(xmm_scratch, kScratchRegister); | 3682 __ Movq(xmm_scratch, kScratchRegister); |
3683 __ ucomisd(xmm_scratch, input_reg); | 3683 __ ucomisd(xmm_scratch, input_reg); |
3684 __ j(below_equal, &round_to_zero, Label::kNear); | 3684 __ j(below_equal, &round_to_zero, Label::kNear); |
3685 | 3685 |
3686 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3686 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
3687 // compare and compensate. | 3687 // compare and compensate. |
3688 __ movq(input_temp, input_reg); // Do not alter input_reg. | 3688 __ Movapd(input_temp, input_reg); // Do not alter input_reg. |
3689 __ subsd(input_temp, xmm_scratch); | 3689 __ subsd(input_temp, xmm_scratch); |
3690 __ cvttsd2si(output_reg, input_temp); | 3690 __ cvttsd2si(output_reg, input_temp); |
3691 // Catch minint due to overflow, and to prevent overflow when compensating. | 3691 // Catch minint due to overflow, and to prevent overflow when compensating. |
3692 __ cmpl(output_reg, Immediate(0x1)); | 3692 __ cmpl(output_reg, Immediate(0x1)); |
3693 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3693 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3694 | 3694 |
3695 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3695 __ Cvtlsi2sd(xmm_scratch, output_reg); |
3696 __ ucomisd(xmm_scratch, input_temp); | 3696 __ ucomisd(xmm_scratch, input_temp); |
3697 __ j(equal, &done, dist); | 3697 __ j(equal, &done, dist); |
3698 __ subl(output_reg, Immediate(1)); | 3698 __ subl(output_reg, Immediate(1)); |
3699 // No overflow because we already ruled out minint. | 3699 // No overflow because we already ruled out minint. |
3700 __ jmp(&done, dist); | 3700 __ jmp(&done, dist); |
3701 | 3701 |
3702 __ bind(&round_to_zero); | 3702 __ bind(&round_to_zero); |
3703 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3703 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
3704 // we can ignore the difference between a result of -0 and +0. | 3704 // we can ignore the difference between a result of -0 and +0. |
3705 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3705 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3706 __ movq(output_reg, input_reg); | 3706 __ Movq(output_reg, input_reg); |
3707 __ testq(output_reg, output_reg); | 3707 __ testq(output_reg, output_reg); |
3708 DeoptimizeIf(negative, instr, Deoptimizer::kMinusZero); | 3708 DeoptimizeIf(negative, instr, Deoptimizer::kMinusZero); |
3709 } | 3709 } |
3710 __ Set(output_reg, 0); | 3710 __ Set(output_reg, 0); |
3711 __ bind(&done); | 3711 __ bind(&done); |
3712 } | 3712 } |
3713 | 3713 |
3714 | 3714 |
3715 void LCodeGen::DoMathFround(LMathFround* instr) { | 3715 void LCodeGen::DoMathFround(LMathFround* instr) { |
3716 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3716 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
(...skipping 20 matching lines...) Expand all Loading... |
3737 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3737 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3738 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); | 3738 DCHECK(ToDoubleRegister(instr->result()).is(input_reg)); |
3739 | 3739 |
3740 // Note that according to ECMA-262 15.8.2.13: | 3740 // Note that according to ECMA-262 15.8.2.13: |
3741 // Math.pow(-Infinity, 0.5) == Infinity | 3741 // Math.pow(-Infinity, 0.5) == Infinity |
3742 // Math.sqrt(-Infinity) == NaN | 3742 // Math.sqrt(-Infinity) == NaN |
3743 Label done, sqrt; | 3743 Label done, sqrt; |
3744 // Check base for -Infinity. According to IEEE-754, double-precision | 3744 // Check base for -Infinity. According to IEEE-754, double-precision |
3745 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3745 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
3746 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); | 3746 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); |
3747 __ movq(xmm_scratch, kScratchRegister); | 3747 __ Movq(xmm_scratch, kScratchRegister); |
3748 __ ucomisd(xmm_scratch, input_reg); | 3748 __ ucomisd(xmm_scratch, input_reg); |
3749 // Comparing -Infinity with NaN results in "unordered", which sets the | 3749 // Comparing -Infinity with NaN results in "unordered", which sets the |
3750 // zero flag as if both were equal. However, it also sets the carry flag. | 3750 // zero flag as if both were equal. However, it also sets the carry flag. |
3751 __ j(not_equal, &sqrt, Label::kNear); | 3751 __ j(not_equal, &sqrt, Label::kNear); |
3752 __ j(carry, &sqrt, Label::kNear); | 3752 __ j(carry, &sqrt, Label::kNear); |
3753 // If input is -Infinity, return Infinity. | 3753 // If input is -Infinity, return Infinity. |
3754 __ xorps(input_reg, input_reg); | 3754 __ xorps(input_reg, input_reg); |
3755 __ subsd(input_reg, xmm_scratch); | 3755 __ subsd(input_reg, xmm_scratch); |
3756 __ jmp(&done, Label::kNear); | 3756 __ jmp(&done, Label::kNear); |
3757 | 3757 |
(...skipping 1557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5315 __ ClampUint8(input_reg); | 5315 __ ClampUint8(input_reg); |
5316 | 5316 |
5317 __ bind(&done); | 5317 __ bind(&done); |
5318 } | 5318 } |
5319 | 5319 |
5320 | 5320 |
5321 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { | 5321 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { |
5322 XMMRegister value_reg = ToDoubleRegister(instr->value()); | 5322 XMMRegister value_reg = ToDoubleRegister(instr->value()); |
5323 Register result_reg = ToRegister(instr->result()); | 5323 Register result_reg = ToRegister(instr->result()); |
5324 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { | 5324 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { |
5325 __ movq(result_reg, value_reg); | 5325 __ Movq(result_reg, value_reg); |
5326 __ shrq(result_reg, Immediate(32)); | 5326 __ shrq(result_reg, Immediate(32)); |
5327 } else { | 5327 } else { |
5328 __ movd(result_reg, value_reg); | 5328 __ Movd(result_reg, value_reg); |
5329 } | 5329 } |
5330 } | 5330 } |
5331 | 5331 |
5332 | 5332 |
5333 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { | 5333 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { |
5334 Register hi_reg = ToRegister(instr->hi()); | 5334 Register hi_reg = ToRegister(instr->hi()); |
5335 Register lo_reg = ToRegister(instr->lo()); | 5335 Register lo_reg = ToRegister(instr->lo()); |
5336 XMMRegister result_reg = ToDoubleRegister(instr->result()); | 5336 XMMRegister result_reg = ToDoubleRegister(instr->result()); |
5337 XMMRegister xmm_scratch = double_scratch0(); | 5337 XMMRegister xmm_scratch = double_scratch0(); |
5338 __ movd(result_reg, hi_reg); | 5338 __ Movd(result_reg, hi_reg); |
5339 __ psllq(result_reg, 32); | 5339 __ psllq(result_reg, 32); |
5340 __ movd(xmm_scratch, lo_reg); | 5340 __ Movd(xmm_scratch, lo_reg); |
5341 __ orps(result_reg, xmm_scratch); | 5341 __ orps(result_reg, xmm_scratch); |
5342 } | 5342 } |
5343 | 5343 |
5344 | 5344 |
5345 void LCodeGen::DoAllocate(LAllocate* instr) { | 5345 void LCodeGen::DoAllocate(LAllocate* instr) { |
5346 class DeferredAllocate final : public LDeferredCode { | 5346 class DeferredAllocate final : public LDeferredCode { |
5347 public: | 5347 public: |
5348 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5348 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
5349 : LDeferredCode(codegen), instr_(instr) { } | 5349 : LDeferredCode(codegen), instr_(instr) { } |
5350 void Generate() override { codegen()->DoDeferredAllocate(instr_); } | 5350 void Generate() override { codegen()->DoDeferredAllocate(instr_); } |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5905 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5905 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5906 } | 5906 } |
5907 | 5907 |
5908 | 5908 |
5909 #undef __ | 5909 #undef __ |
5910 | 5910 |
5911 } // namespace internal | 5911 } // namespace internal |
5912 } // namespace v8 | 5912 } // namespace v8 |
5913 | 5913 |
5914 #endif // V8_TARGET_ARCH_X64 | 5914 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |