OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3597 | 3597 |
3598 __ bind(&done); | 3598 __ bind(&done); |
3599 } | 3599 } |
3600 } | 3600 } |
3601 | 3601 |
3602 | 3602 |
3603 void LCodeGen::DoMathRound(LMathRound* instr) { | 3603 void LCodeGen::DoMathRound(LMathRound* instr) { |
3604 const XMMRegister xmm_scratch = double_scratch0(); | 3604 const XMMRegister xmm_scratch = double_scratch0(); |
3605 Register output_reg = ToRegister(instr->result()); | 3605 Register output_reg = ToRegister(instr->result()); |
3606 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3606 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3607 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | |
3607 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 | 3608 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 |
3608 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3609 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
3609 | 3610 |
3610 Label done, round_to_zero, below_one_half, do_not_compensate, restore; | 3611 Label done, round_to_zero, below_one_half, do_not_compensate, restore; |
Jakob Kummerow
2014/03/13 12:50:01
We don't need |restore| anymore. And we don't need
| |
3611 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3612 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
3612 __ movq(kScratchRegister, one_half); | 3613 __ movq(kScratchRegister, one_half); |
3613 __ movq(xmm_scratch, kScratchRegister); | 3614 __ movq(xmm_scratch, kScratchRegister); |
3614 __ ucomisd(xmm_scratch, input_reg); | 3615 __ ucomisd(xmm_scratch, input_reg); |
3615 __ j(above, &below_one_half, Label::kNear); | 3616 __ j(above, &below_one_half, Label::kNear); |
3616 | 3617 |
3617 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3618 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
3618 __ addsd(xmm_scratch, input_reg); | 3619 __ addsd(xmm_scratch, input_reg); |
3619 __ cvttsd2si(output_reg, xmm_scratch); | 3620 __ cvttsd2si(output_reg, xmm_scratch); |
3620 // Overflow is signalled with minint. | 3621 // Overflow is signalled with minint. |
3621 __ cmpl(output_reg, Immediate(0x80000000)); | 3622 __ cmpl(output_reg, Immediate(0x80000000)); |
3622 __ RecordComment("D2I conversion overflow"); | 3623 __ RecordComment("D2I conversion overflow"); |
3623 DeoptimizeIf(equal, instr->environment()); | 3624 DeoptimizeIf(equal, instr->environment()); |
3624 __ jmp(&done, dist); | 3625 __ jmp(&done, dist); |
3625 | 3626 |
3626 __ bind(&below_one_half); | 3627 __ bind(&below_one_half); |
3627 __ movq(kScratchRegister, minus_one_half); | 3628 __ movq(kScratchRegister, minus_one_half); |
3628 __ movq(xmm_scratch, kScratchRegister); | 3629 __ movq(xmm_scratch, kScratchRegister); |
3629 __ ucomisd(xmm_scratch, input_reg); | 3630 __ ucomisd(xmm_scratch, input_reg); |
3630 __ j(below_equal, &round_to_zero, Label::kNear); | 3631 __ j(below_equal, &round_to_zero, Label::kNear); |
3631 | 3632 |
3632 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3633 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
3633 // compare and compensate. | 3634 // compare and compensate. |
3634 __ movq(kScratchRegister, input_reg); // Back up input_reg. | 3635 __ movq(input_temp, input_reg); // Do not alter input_reg. |
3635 __ subsd(input_reg, xmm_scratch); | 3636 __ subsd(input_temp, xmm_scratch); |
3636 __ cvttsd2si(output_reg, input_reg); | 3637 __ cvttsd2si(output_reg, input_temp); |
3637 // Catch minint due to overflow, and to prevent overflow when compensating. | 3638 // Catch minint due to overflow, and to prevent overflow when compensating. |
3638 __ cmpl(output_reg, Immediate(0x80000000)); | 3639 __ cmpl(output_reg, Immediate(0x80000000)); |
3639 __ RecordComment("D2I conversion overflow"); | 3640 __ RecordComment("D2I conversion overflow"); |
3640 DeoptimizeIf(equal, instr->environment()); | 3641 DeoptimizeIf(equal, instr->environment()); |
3641 | 3642 |
3642 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3643 __ Cvtlsi2sd(xmm_scratch, output_reg); |
3643 __ ucomisd(input_reg, xmm_scratch); | 3644 __ ucomisd(xmm_scratch, input_temp); |
3644 __ j(equal, &restore, Label::kNear); | 3645 __ j(equal, &done, dist); |
3645 __ subl(output_reg, Immediate(1)); | 3646 __ subl(output_reg, Immediate(1)); |
3646 // No overflow because we already ruled out minint. | 3647 // No overflow because we already ruled out minint. |
3647 __ bind(&restore); | |
3648 __ movq(input_reg, kScratchRegister); // Restore input_reg. | |
3649 __ jmp(&done, dist); | 3648 __ jmp(&done, dist); |
3650 | 3649 |
3651 __ bind(&round_to_zero); | 3650 __ bind(&round_to_zero); |
3652 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3651 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
3653 // we can ignore the difference between a result of -0 and +0. | 3652 // we can ignore the difference between a result of -0 and +0. |
3654 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3653 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3655 __ movq(output_reg, input_reg); | 3654 __ movq(output_reg, input_reg); |
3656 __ testq(output_reg, output_reg); | 3655 __ testq(output_reg, output_reg); |
3657 __ RecordComment("Minus zero"); | 3656 __ RecordComment("Minus zero"); |
3658 DeoptimizeIf(negative, instr->environment()); | 3657 DeoptimizeIf(negative, instr->environment()); |
(...skipping 1980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5639 FixedArray::kHeaderSize - kPointerSize)); | 5638 FixedArray::kHeaderSize - kPointerSize)); |
5640 __ bind(&done); | 5639 __ bind(&done); |
5641 } | 5640 } |
5642 | 5641 |
5643 | 5642 |
5644 #undef __ | 5643 #undef __ |
5645 | 5644 |
5646 } } // namespace v8::internal | 5645 } } // namespace v8::internal |
5647 | 5646 |
5648 #endif // V8_TARGET_ARCH_X64 | 5647 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |