| Index: src/arm64/lithium-codegen-arm64.cc
|
| diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
|
| index 3ecd2403ba3b6aa0848006d90439a11b746e0bc3..bc57bc938e6ee24fcc72dd2a60f03cca5ac0a7a9 100644
|
| --- a/src/arm64/lithium-codegen-arm64.cc
|
| +++ b/src/arm64/lithium-codegen-arm64.cc
|
| @@ -3761,9 +3761,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());
|
|
|
| @@ -3996,8 +4002,37 @@ 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 = double_scratch();
|
| +
|
| + ASSERT(!AreAliased(input, result, scratch_d));
|
| +
|
| + Label done;
|
| +
|
| + __ Frinta(result, input);
|
| + __ Fcmp(input, 0.0);
|
| + __ Fccmp(result, input, ZFlag, lt);
|
| + // The result is correct if the input was in [-0, +infinity], or was a
|
| + // negative integral value.
|
| + __ B(eq, &done);
|
| +
|
| + // Here the input is negative, non integral, with an exponent lower than 52.
|
| + // We do not have to worry about the 0.49999999999999994 (0x3fdfffffffffffff)
|
| + // case. So we can safely add 0.5.
|
| + __ Fmov(scratch_d, 0.5);
|
| + __ Fadd(result, input, scratch_d);
|
| + __ Frintm(result, result);
|
| + // The range [-0.5, -0.0[ yielded +0.0. Force the sign to negative.
|
| + __ Fabs(result, result);
|
| + __ Fneg(result, result);
|
| +
|
| + __ Bind(&done);
|
| +}
|
| +
|
| +
|
| +void LCodeGen::DoMathRoundI(LMathRoundI* instr) {
|
| DoubleRegister input = ToDoubleRegister(instr->value());
|
| DoubleRegister temp1 = ToDoubleRegister(instr->temp1());
|
| Register result = ToRegister(instr->result());
|
| @@ -4036,7 +4071,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);
|
|
|