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); |