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/crankshaft/x64/lithium-codegen-x64.h" | 7 #include "src/crankshaft/x64/lithium-codegen-x64.h" |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 3547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3558 LMathAbs* instr_; | 3558 LMathAbs* instr_; |
3559 }; | 3559 }; |
3560 | 3560 |
3561 DCHECK(instr->value()->Equals(instr->result())); | 3561 DCHECK(instr->value()->Equals(instr->result())); |
3562 Representation r = instr->hydrogen()->value()->representation(); | 3562 Representation r = instr->hydrogen()->value()->representation(); |
3563 | 3563 |
3564 if (r.IsDouble()) { | 3564 if (r.IsDouble()) { |
3565 XMMRegister scratch = double_scratch0(); | 3565 XMMRegister scratch = double_scratch0(); |
3566 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3566 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3567 __ Xorpd(scratch, scratch); | 3567 __ Xorpd(scratch, scratch); |
3568 __ subsd(scratch, input_reg); | 3568 __ Subsd(scratch, input_reg); |
3569 __ andps(input_reg, scratch); | 3569 __ Andpd(input_reg, scratch); |
3570 } else if (r.IsInteger32()) { | 3570 } else if (r.IsInteger32()) { |
3571 EmitIntegerMathAbs(instr); | 3571 EmitIntegerMathAbs(instr); |
3572 } else if (r.IsSmi()) { | 3572 } else if (r.IsSmi()) { |
3573 EmitSmiMathAbs(instr); | 3573 EmitSmiMathAbs(instr); |
3574 } else { // Tagged case. | 3574 } else { // Tagged case. |
3575 DeferredMathAbsTaggedHeapNumber* deferred = | 3575 DeferredMathAbsTaggedHeapNumber* deferred = |
3576 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3576 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
3577 Register input_reg = ToRegister(instr->value()); | 3577 Register input_reg = ToRegister(instr->value()); |
3578 // Smi check. | 3578 // Smi check. |
3579 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3579 __ JumpIfNotSmi(input_reg, deferred->entry()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3651 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3651 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
3652 | 3652 |
3653 Label done, round_to_zero, below_one_half; | 3653 Label done, round_to_zero, below_one_half; |
3654 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3654 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
3655 __ movq(kScratchRegister, one_half); | 3655 __ movq(kScratchRegister, one_half); |
3656 __ Movq(xmm_scratch, kScratchRegister); | 3656 __ Movq(xmm_scratch, kScratchRegister); |
3657 __ Ucomisd(xmm_scratch, input_reg); | 3657 __ Ucomisd(xmm_scratch, input_reg); |
3658 __ j(above, &below_one_half, Label::kNear); | 3658 __ j(above, &below_one_half, Label::kNear); |
3659 | 3659 |
3660 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3660 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
3661 __ addsd(xmm_scratch, input_reg); | 3661 __ Addsd(xmm_scratch, input_reg); |
3662 __ Cvttsd2si(output_reg, xmm_scratch); | 3662 __ Cvttsd2si(output_reg, xmm_scratch); |
3663 // Overflow is signalled with minint. | 3663 // Overflow is signalled with minint. |
3664 __ cmpl(output_reg, Immediate(0x1)); | 3664 __ cmpl(output_reg, Immediate(0x1)); |
3665 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3665 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3666 __ jmp(&done, dist); | 3666 __ jmp(&done, dist); |
3667 | 3667 |
3668 __ bind(&below_one_half); | 3668 __ bind(&below_one_half); |
3669 __ movq(kScratchRegister, minus_one_half); | 3669 __ movq(kScratchRegister, minus_one_half); |
3670 __ Movq(xmm_scratch, kScratchRegister); | 3670 __ Movq(xmm_scratch, kScratchRegister); |
3671 __ Ucomisd(xmm_scratch, input_reg); | 3671 __ Ucomisd(xmm_scratch, input_reg); |
3672 __ j(below_equal, &round_to_zero, Label::kNear); | 3672 __ j(below_equal, &round_to_zero, Label::kNear); |
3673 | 3673 |
3674 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3674 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
3675 // compare and compensate. | 3675 // compare and compensate. |
3676 __ Movapd(input_temp, input_reg); // Do not alter input_reg. | 3676 __ Movapd(input_temp, input_reg); // Do not alter input_reg. |
3677 __ subsd(input_temp, xmm_scratch); | 3677 __ Subsd(input_temp, xmm_scratch); |
3678 __ Cvttsd2si(output_reg, input_temp); | 3678 __ Cvttsd2si(output_reg, input_temp); |
3679 // Catch minint due to overflow, and to prevent overflow when compensating. | 3679 // Catch minint due to overflow, and to prevent overflow when compensating. |
3680 __ cmpl(output_reg, Immediate(0x1)); | 3680 __ cmpl(output_reg, Immediate(0x1)); |
3681 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); | 3681 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); |
3682 | 3682 |
3683 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3683 __ Cvtlsi2sd(xmm_scratch, output_reg); |
3684 __ Ucomisd(xmm_scratch, input_temp); | 3684 __ Ucomisd(xmm_scratch, input_temp); |
3685 __ j(equal, &done, dist); | 3685 __ j(equal, &done, dist); |
3686 __ subl(output_reg, Immediate(1)); | 3686 __ subl(output_reg, Immediate(1)); |
3687 // No overflow because we already ruled out minint. | 3687 // No overflow because we already ruled out minint. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3733 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3733 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
3734 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); | 3734 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); |
3735 __ Movq(xmm_scratch, kScratchRegister); | 3735 __ Movq(xmm_scratch, kScratchRegister); |
3736 __ Ucomisd(xmm_scratch, input_reg); | 3736 __ Ucomisd(xmm_scratch, input_reg); |
3737 // Comparing -Infinity with NaN results in "unordered", which sets the | 3737 // Comparing -Infinity with NaN results in "unordered", which sets the |
3738 // zero flag as if both were equal. However, it also sets the carry flag. | 3738 // zero flag as if both were equal. However, it also sets the carry flag. |
3739 __ j(not_equal, &sqrt, Label::kNear); | 3739 __ j(not_equal, &sqrt, Label::kNear); |
3740 __ j(carry, &sqrt, Label::kNear); | 3740 __ j(carry, &sqrt, Label::kNear); |
3741 // If input is -Infinity, return Infinity. | 3741 // If input is -Infinity, return Infinity. |
3742 __ Xorpd(input_reg, input_reg); | 3742 __ Xorpd(input_reg, input_reg); |
3743 __ subsd(input_reg, xmm_scratch); | 3743 __ Subsd(input_reg, xmm_scratch); |
3744 __ jmp(&done, Label::kNear); | 3744 __ jmp(&done, Label::kNear); |
3745 | 3745 |
3746 // Square root. | 3746 // Square root. |
3747 __ bind(&sqrt); | 3747 __ bind(&sqrt); |
3748 __ Xorpd(xmm_scratch, xmm_scratch); | 3748 __ Xorpd(xmm_scratch, xmm_scratch); |
3749 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. | 3749 __ Addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
3750 __ Sqrtsd(input_reg, input_reg); | 3750 __ Sqrtsd(input_reg, input_reg); |
3751 __ bind(&done); | 3751 __ bind(&done); |
3752 } | 3752 } |
3753 | 3753 |
3754 | 3754 |
3755 void LCodeGen::DoPower(LPower* instr) { | 3755 void LCodeGen::DoPower(LPower* instr) { |
3756 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3756 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3757 // Having marked this as a call, we can use any registers. | 3757 // Having marked this as a call, we can use any registers. |
3758 // Just make sure that the input/output registers are the expected ones. | 3758 // Just make sure that the input/output registers are the expected ones. |
3759 | 3759 |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4252 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && | 4252 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
4253 instr->hydrogen()->IsDehoisted()) { | 4253 instr->hydrogen()->IsDehoisted()) { |
4254 // Sign extend key because it could be a 32 bit negative value | 4254 // Sign extend key because it could be a 32 bit negative value |
4255 // and the dehoisted address computation happens in 64 bits | 4255 // and the dehoisted address computation happens in 64 bits |
4256 __ movsxlq(ToRegister(key), ToRegister(key)); | 4256 __ movsxlq(ToRegister(key), ToRegister(key)); |
4257 } | 4257 } |
4258 if (instr->NeedsCanonicalization()) { | 4258 if (instr->NeedsCanonicalization()) { |
4259 XMMRegister xmm_scratch = double_scratch0(); | 4259 XMMRegister xmm_scratch = double_scratch0(); |
4260 // Turn potential sNaN value into qNaN. | 4260 // Turn potential sNaN value into qNaN. |
4261 __ Xorpd(xmm_scratch, xmm_scratch); | 4261 __ Xorpd(xmm_scratch, xmm_scratch); |
4262 __ subsd(value, xmm_scratch); | 4262 __ Subsd(value, xmm_scratch); |
4263 } | 4263 } |
4264 | 4264 |
4265 Operand double_store_operand = BuildFastArrayOperand( | 4265 Operand double_store_operand = BuildFastArrayOperand( |
4266 instr->elements(), | 4266 instr->elements(), |
4267 key, | 4267 key, |
4268 instr->hydrogen()->key()->representation(), | 4268 instr->hydrogen()->key()->representation(), |
4269 FAST_DOUBLE_ELEMENTS, | 4269 FAST_DOUBLE_ELEMENTS, |
4270 instr->base_offset()); | 4270 instr->base_offset()); |
4271 | 4271 |
4272 __ Movsd(double_store_operand, value); | 4272 __ Movsd(double_store_operand, value); |
(...skipping 1596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5869 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5869 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5870 } | 5870 } |
5871 | 5871 |
5872 | 5872 |
5873 #undef __ | 5873 #undef __ |
5874 | 5874 |
5875 } // namespace internal | 5875 } // namespace internal |
5876 } // namespace v8 | 5876 } // namespace v8 |
5877 | 5877 |
5878 #endif // V8_TARGET_ARCH_X64 | 5878 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |