Chromium Code Reviews| Index: src/arm/lithium-codegen-arm.cc |
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
| index 49124497fba7dc5566a77950321e6858ff40f0df..b49981288559817d32a4f5fa3d8e03f96ab95d20 100644 |
| --- a/src/arm/lithium-codegen-arm.cc |
| +++ b/src/arm/lithium-codegen-arm.cc |
| @@ -2861,8 +2861,106 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| Register result = ToRegister(instr->result()); |
| - Register scratch1 = scratch0(); |
| - Register scratch2 = result; |
| + Register scratch1 = ToRegister(instr->TempAt(0)); |
| + Register scratch2 = scratch0(); |
| + Register scratch3 = result; |
| + |
| + // Test for numbers with a decimal fraction of 0.5 first. |
| + // These cannot be rounded with kRoundToNearest, because it rounds |
| + // ties to even numbers instead of to the higher one, as required |
| + // by the ECMA standard. |
| + |
| + // Extract exponent bits. scratch1 holds the upper word |
| + // of the double and scratch2 the lower word. |
| + __ vmov(scratch2, scratch1, input); |
| + __ ubfx(scratch3, |
| + scratch1, |
| + HeapNumber::kExponentShift, |
| + HeapNumber::kExponentBits); |
| + |
| + // Unbias exponent. |
| + __ sub(scratch3, scratch3, Operand(HeapNumber::kExponentBias)); |
| + |
| + // Deoptimize if value is special. |
| + __ cmp(scratch3, Operand(1024)); |
|
Lasse Reichstein
2011/04/14 19:09:04
You can deoptimize for all exponents above or equa
|
| + DeoptimizeIf(eq, instr->environment()); |
| + |
| + Label lower_word, one_half, test, normal_case, adjust_sign_on_zero, done; |
| + |
| + // If the exponent is -1 jump to special check for 0.5. |
| + __ cmp(scratch3, Operand(-1)); |
| + __ b(eq, &one_half); |
| + |
| + // If the exponent is smaller than -1, the result is +0 |
| + // or -0. |
| + __ mov(result, Operand(0), LeaveCC, lt); |
| + __ b(lt, &adjust_sign_on_zero); |
|
Lasse Reichstein
2011/04/14 19:09:04
You can jump to after the zero-test at adjust_sign
|
| + |
| + // If the exponent is greater or equal to HeapNumber::kMantissaBits then |
| + // there is no fractional part. |
| + __ cmp(scratch3, Operand(HeapNumber::kMantissaBits)); |
|
Lasse Reichstein
2011/04/14 19:09:04
If you bailed out for exponent >= 31, this isn't n
|
| + __ b(ge, &normal_case); |
| + |
| + // Exponent is greater or equal zero and below HeapNumber::kMantissaBits. |
|
Søren Thygesen Gjesse
2011/04/15 07:55:35
equal zero -> equal to zero
|
| + // Check if the bit we want to test is in the upper or lower word. |
|
Lasse Reichstein
2011/04/14 19:09:04
The bit we need to test is the one with value 0.5,
|
| + __ cmp(scratch3, Operand(HeapNumber::kMantissaBitsInTopWord - 1)); |
|
Lasse Reichstein
2011/04/14 19:09:04
You might be able to save a few instructions here
|
| + __ b(gt, &lower_word); |
| + |
| + // If the first fractional bit is in the upper word and the fractional part |
| + // is 0.5 then the lower word of the double must be all zeroes. |
| + __ cmp(scratch2, Operand(0)); |
| + __ b(ne, &normal_case); |
| + |
| + // Calculate the bit position of the 1-bit we are looking for. All lower |
| + // bits must be zero. |
| + __ rsb(scratch3, scratch3, Operand(HeapNumber::kMantissaBitsInTopWord - 1)); |
| + __ jmp(&test); |
| + |
| + __ bind(&lower_word); |
| + // Calculate the bit position of the 1-bit we are looking for. All lower |
| + // bits must be zero. Copy lower word into higher word register for the |
| + // test code below. |
| + __ rsb(scratch3, scratch3, Operand(HeapNumber::kMantissaBits - 1)); |
| + __ mov(scratch1, scratch2); |
| + |
| + __ bind(&test); |
| + // Test the bit. |
| + __ mov(scratch2, Operand(1)); |
| + __ mov(scratch3, Operand(scratch2, LSL, scratch3)); |
| + __ tst(scratch1, scratch3); |
| + __ b(eq, &normal_case); |
| + |
| + // Test the rest of the mantissa in the high word. |
| + __ sub(scratch3, scratch3, Operand(1)); |
| + __ tst(scratch1, scratch3); |
| + __ b(ne, &normal_case); |
| + |
| + // We have to round to the higher number, so we add 0.5 and jump to |
| + // the normal case. |
|
Lasse Reichstein
2011/04/14 19:09:04
If you are going to add 0.5 and round in half the
|
| + ExternalReference one_half_adr = ExternalReference::address_of_one_half(); |
| + __ mov(scratch1, Operand(one_half_adr)); |
| + __ vldr(double_scratch0(), MemOperand(scratch1)); |
| + __ vadd(input, input, double_scratch0()); |
| + __ jmp(&normal_case); |
| + |
| + __ bind(&one_half); |
| + // Check for the special case of +0.5 and -0.5: The mantissa |
| + // bits must be all zero. |
| + __ tst(scratch1, Operand(HeapNumber::kMantissaMask)); |
| + __ b(ne, &normal_case); |
| + __ cmp(scratch2, Operand(0)); |
| + __ b(ne, &normal_case); |
| + __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| + __ mov(result, Operand(1), LeaveCC, eq); |
| + __ b(&done, eq); |
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| + DeoptimizeIf(ne, instr->environment()); |
| + } else { |
| + __ mov(result, Operand(0)); |
| + __ jmp(&done); |
| + } |
| + |
| + __ bind(&normal_case); |
| __ EmitVFPTruncate(kRoundToNearest, |
| double_scratch0().low(), |
| input, |
| @@ -2871,16 +2969,16 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| DeoptimizeIf(ne, instr->environment()); |
| __ vmov(result, double_scratch0().low()); |
| + __ bind(&adjust_sign_on_zero); |
| if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| // Test for -0. |
| - Label done; |
| __ cmp(result, Operand(0)); |
| __ b(ne, &done); |
| __ vmov(scratch1, input.high()); |
| __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| DeoptimizeIf(ne, instr->environment()); |
| - __ bind(&done); |
| } |
| + __ bind(&done); |
| } |