Enable truncated floating point feature on ARM
https://bugs.webkit.org/show_bug.cgi?id=44233

Reviewed by Gavin Barraclough.

Enable truncated floating point feature with the help of VCVTR.S32.F64
instruction. If VCVTR.S32.F64 can't fit the result into a 32-bit
integer/register, it saturates at INT_MAX or INT_MIN. Testing this
looks quicker than testing FPSCR for exception.

Inspired by Jacob Bramley's patch from JaegerMonkey

* assembler/ARMAssembler.h:
(JSC::ARMAssembler::):
(JSC::ARMAssembler::cmn_r):
(JSC::ARMAssembler::vcvtr_s32_f64_r):
* assembler/MacroAssemblerARM.h:
(JSC::MacroAssemblerARM::supportsFloatingPointTruncate):
(JSC::MacroAssemblerARM::branchTruncateDoubleToInt32):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65993 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/assembler/MacroAssemblerARM.h b/JavaScriptCore/assembler/MacroAssemblerARM.h
index 48ddf24..5de8b34 100644
--- a/JavaScriptCore/assembler/MacroAssemblerARM.h
+++ b/JavaScriptCore/assembler/MacroAssemblerARM.h
@@ -769,7 +769,7 @@
 
     bool supportsFloatingPointTruncate() const
     {
-        return false;
+        return s_isVFPPresent;
     }
 
     bool supportsFloatingPointSqrt() const
@@ -878,13 +878,17 @@
     // Truncates 'src' to an integer, and places the resulting 'dest'.
     // If the result is not representable as a 32 bit value, branch.
     // May also branch for some values that are representable in 32 bits
-    // (specifically, in this case, INT_MIN).
+    // (specifically, in this case, INT_MIN and INT_MAX).
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
-        UNUSED_PARAM(src);
-        UNUSED_PARAM(dest);
-        ASSERT_NOT_REACHED();
-        return jump();
+        m_assembler.vcvtr_s32_f64_r(ARMRegisters::SD0 << 1, src);
+        // If VCVTR.S32.F64 can't fit the result into a 32-bit
+        // integer, it saturates at INT_MAX or INT_MIN. Testing this is
+        // probably quicker than testing FPSCR for exception.
+        m_assembler.vmov_arm_r(dest, ARMRegisters::SD0 << 1);
+        m_assembler.sub_r(ARMRegisters::S0, dest, ARMAssembler::getOp2(0x80000000));
+        m_assembler.cmn_r(ARMRegisters::S0, ARMAssembler::getOp2(1), ARMCondition(NotEqual));
+        return Jump(m_assembler.jmp(ARMCondition(Equal)));
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.