Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index 202e7a24fcd239a7fe47aacf26ac24f9fce5b33a..9e7e228dadb9138f393f7319128329d8391dffad 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -2721,33 +2721,44 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
Register output_reg = ToRegister(instr->result()); |
XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
+ Label done; |
// xmm_scratch = 0.5 |
__ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
__ movq(xmm_scratch, kScratchRegister); |
- |
+ NearLabel below_half; |
+ __ ucomisd(xmm_scratch, input_reg); |
+ __ j(above, &below_half); // If input_reg is NaN, this doesn't jump. |
// input = input + 0.5 |
+ // This addition might give a result that isn't the correct for |
+ // rounding, due to loss of precission, but only for a number that's |
William Hesse
2011/04/13 09:12:45
precision
Lasse Reichstein
2011/04/13 09:35:23
Fixed, thanks.
|
+ // so big that the conversion below will overflow anyway. |
__ addsd(input_reg, xmm_scratch); |
+ // Compute Math.floor(input). |
+ // Use truncating instruction (OK because input is positive). |
+ __ cvttsd2si(output_reg, input_reg); |
+ // Overflow is signalled with minint. |
+ __ cmpl(output_reg, Immediate(0x80000000)); |
+ DeoptimizeIf(equal, instr->environment()); |
+ __ jmp(&done); |
- // We need to return -0 for the input range [-0.5, 0[, otherwise |
- // compute Math.floor(value + 0.5). |
+ __ bind(&below_half); |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
- __ ucomisd(input_reg, xmm_scratch); |
- DeoptimizeIf(below_equal, instr->environment()); |
+ // Bailout if negative (including -0). |
+ __ movq(output_reg, input_reg); |
+ __ testq(output_reg, output_reg); |
+ DeoptimizeIf(negative, instr->environment()); |
} else { |
- // If we don't need to bailout on -0, we check only bailout |
- // on negative inputs. |
- __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
+ // Bailout if below -0.5, otherwise round to (positive) zero, even |
+ // if negative. |
+ // xmm_scrach = -0.5 |
+ __ movq(kScratchRegister, V8_INT64_C(0xBFE0000000000000), RelocInfo::NONE); |
+ __ movq(xmm_scratch, kScratchRegister); |
__ ucomisd(input_reg, xmm_scratch); |
DeoptimizeIf(below, instr->environment()); |
} |
+ __ xorl(output_reg, output_reg); |
- // Compute Math.floor(value + 0.5). |
- // Use truncating instruction (OK because input is positive). |
- __ cvttsd2si(output_reg, input_reg); |
- |
- // Overflow is signalled with minint. |
- __ cmpl(output_reg, Immediate(0x80000000)); |
- DeoptimizeIf(equal, instr->environment()); |
+ __ bind(&done); |
} |