| Index: src/arm64/lithium-codegen-arm64.cc
|
| diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
|
| index 46e038537869493fcbd70cc6fd104b445273819d..4a603836b8a711194843a5e48d0e3bdf65a2c6f4 100644
|
| --- a/src/arm64/lithium-codegen-arm64.cc
|
| +++ b/src/arm64/lithium-codegen-arm64.cc
|
| @@ -3784,9 +3784,15 @@ void LCodeGen::DoMathExp(LMathExp* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoMathFloor(LMathFloor* instr) {
|
| - // TODO(jbramley): If we could provide a double result, we could use frintm
|
| - // and produce a valid double result in a single instruction.
|
| +void LCodeGen::DoMathFloorD(LMathFloorD* instr) {
|
| + DoubleRegister input = ToDoubleRegister(instr->value());
|
| + DoubleRegister result = ToDoubleRegister(instr->result());
|
| +
|
| + __ Frintm(result, input);
|
| +}
|
| +
|
| +
|
| +void LCodeGen::DoMathFloorI(LMathFloorI* instr) {
|
| DoubleRegister input = ToDoubleRegister(instr->value());
|
| Register result = ToRegister(instr->result());
|
|
|
| @@ -4019,8 +4025,40 @@ void LCodeGen::DoPower(LPower* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoMathRound(LMathRound* instr) {
|
| - // TODO(jbramley): We could provide a double result here using frint.
|
| +void LCodeGen::DoMathRoundD(LMathRoundD* instr) {
|
| + DoubleRegister input = ToDoubleRegister(instr->value());
|
| + DoubleRegister result = ToDoubleRegister(instr->result());
|
| + DoubleRegister scratch_d = crankshaft_fp_scratch;
|
| + Register scratch_x = ToRegister(instr->temp());
|
| +
|
| + ASSERT(!AreAliased(input, result, scratch_d));
|
| +
|
| + Label done;
|
| +
|
| + // If the exponent is greater than or equal to the width of the mantissa (52),
|
| + // there is no fractional part.
|
| + __ Fmov(scratch_x, input);
|
| + __ Ubfx(scratch_x, scratch_x, kDoubleMantissaBits, kDoubleExponentBits);
|
| + __ Cmp(scratch_x, Operand(kDoubleExponentBias + kDoubleMantissaBits));
|
| + __ Fmov(result, input);
|
| + __ B(hs, &done);
|
| +
|
| + // Otherwise except for the range yielding -0.0, the result is the same as
|
| + // floor(val + 0.5).
|
| + __ Fmov(scratch_d, 0.5);
|
| + __ Fadd(result, input, scratch_d);
|
| + __ Frintm(result, result);
|
| + __ Fcmp(result, 0.0);
|
| + __ B(ne, &done);
|
| +
|
| + // Frintn computes the correct result for [-0.5, 0.5[.
|
| + __ Frintn(result, input);
|
| +
|
| + __ Bind(&done);
|
| +}
|
| +
|
| +
|
| +void LCodeGen::DoMathRoundI(LMathRoundI* instr) {
|
| DoubleRegister input = ToDoubleRegister(instr->value());
|
| DoubleRegister temp1 = ToDoubleRegister(instr->temp1());
|
| Register result = ToRegister(instr->result());
|
| @@ -4059,7 +4097,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) {
|
| // Since we're providing a 32-bit result, we can implement ties-to-infinity by
|
| // adding 0.5 to the input, then taking the floor of the result. This does not
|
| // work for very large positive doubles because adding 0.5 would cause an
|
| - // intermediate rounding stage, so a different approach will be necessary if a
|
| + // intermediate rounding stage, so a different approach is necessary when a
|
| // double result is needed.
|
| __ Fadd(temp1, input, dot_five);
|
| __ Fcvtms(result, temp1);
|
|
|