[JAEGER] Implement branchTruncateDoubleToInt32 for ARM. [Bug 585918] [r=dmandelin]
authorJacob Bramley <Jacob.Bramley@arm.com>
Wed, 11 Aug 2010 15:23:22 +0100
changeset 53379 c5754250e81370375b231f18001799920409581c
parent 53378 90ba1507aa4823c90f3f6482ed60ea192044b6c9
child 53380 13495e9f957ed297e21c723764b05ea550f17f41
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmandelin
bugs585918
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
[JAEGER] Implement branchTruncateDoubleToInt32 for ARM. [Bug 585918] [r=dmandelin]
js/src/assembler/assembler/ARMAssembler.h
js/src/assembler/assembler/MacroAssemblerARM.h
--- a/js/src/assembler/assembler/ARMAssembler.h
+++ b/js/src/assembler/assembler/ARMAssembler.h
@@ -200,16 +200,17 @@ namespace JSC {
             BL = 0x0b000000
 #if WTF_ARM_ARCH_VERSION >= 5 || defined(__ARM_ARCH_4T__)
            ,BX = 0x012fff10
 #endif
            ,FMSR = 0x0e000a10,
             FMRS = 0x0e100a10,
             FSITOD = 0x0eb80bc0,
             FTOSID = 0x0ebd0b40,
+            FTOSIZD = 0x0ebd0bc0,
             FMSTAT = 0x0ef1fa10
 #if WTF_ARM_ARCH_VERSION >= 5
            ,CLZ = 0x016f0f10,
             BKPT = 0xe120070,
             BLX = 0x012fff30
 #endif
 #if WTF_ARM_ARCH_VERSION >= 7
            ,MOVW = 0x03000000,
@@ -421,16 +422,22 @@ namespace JSC {
         }
 
         void cmp_r(int rn, ARMWord op2, Condition cc = AL)
         {
             spewInsWithOp2("cmp", cc, rn, op2);
             emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
         }
 
+        void cmn_r(int rn, ARMWord op2, Condition cc = AL)
+        {
+            spewInsWithOp2("cmn", cc, rn, op2);
+            emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2);
+        }
+
         void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
         {
             spewInsWithOp2("orr", cc, rd, rn, op2);
             emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
         }
 
         void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
         {
@@ -668,26 +675,28 @@ namespace JSC {
         {
             js::JaegerSpew(js::JSpew_Insns,
                     IPFX   "%-15s %s, [%s, +%s]\n", MAYBE_PAD, "strh", nameGpReg(rd), nameGpReg(rb), nameGpReg(rm));
             emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rb, rm);
         }
 
         void fdtr_u(bool isLoad, int dd, int rn, ARMWord offset, Condition cc = AL)
         {
+            char const * ins = isLoad ? "vldr.f64" : "vstr.f64";
             js::JaegerSpew(js::JSpew_Insns,
-                    IPFX   "%-15s %s, [%s, #+%u]\n", MAYBE_PAD, "vldr.f64", nameFpRegD(dd), nameGpReg(rn), offset);
+                    IPFX   "%-15s %s, [%s, #+%u]\n", MAYBE_PAD, ins, nameFpRegD(dd), nameGpReg(rn), offset);
             ASSERT(offset <= 0xff);
             emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), dd, rn, offset);
         }
 
         void fdtr_d(bool isLoad, int dd, int rn, ARMWord offset, Condition cc = AL)
         {
+            char const * ins = isLoad ? "vldr.f64" : "vstr.f64";
             js::JaegerSpew(js::JSpew_Insns,
-                    IPFX   "%-15s %s, [%s, #-%u]\n", MAYBE_PAD, "vldr.f64", nameFpRegD(dd), nameGpReg(rn), offset);
+                    IPFX   "%-15s %s, [%s, #-%u]\n", MAYBE_PAD, ins, nameFpRegD(dd), nameGpReg(rn), offset);
             ASSERT(offset <= 0xff);
             emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), dd, rn, offset);
         }
 
         void push_r(int reg, Condition cc = AL)
         {
             js::JaegerSpew(js::JSpew_Insns,
                     IPFX   "%-15s {%s}\n", MAYBE_PAD, "push", nameGpReg(reg));
@@ -736,16 +745,23 @@ namespace JSC {
 
         void ftosid_r(int fd, int dm, Condition cc = AL)
         {
             // TODO: emitInst doesn't work for VFP instructions, though it
             // seems to work for current usage.
             emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
         }
 
+        void ftosizd_r(int fd, int dm, Condition cc = AL)
+        {
+            // TODO: emitInst doesn't work for VFP instructions, though it
+            // seems to work for current usage.
+            emitInst(static_cast<ARMWord>(cc) | FTOSIZD, fd, 0, dm);
+        }
+
         void fmstat(Condition cc = AL)
         {
             // TODO: emitInst doesn't work for VFP instructions, though it
             // seems to work for current usage.
             m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
         }
 
 #if WTF_ARM_ARCH_VERSION >= 5
--- a/js/src/assembler/assembler/MacroAssemblerARM.h
+++ b/js/src/assembler/assembler/MacroAssemblerARM.h
@@ -848,17 +848,17 @@ public:
     // Floating point operators
     bool supportsFloatingPoint() const
     {
         return s_isVFPPresent;
     }
 
     bool supportsFloatingPointTruncate() const
     {
-        return false;
+        return true;
     }
 
     bool supportsFloatingPointSqrt() const
     {
         return s_isVFPPresent;
     }
 
     void moveDouble(FPRegisterID src, FPRegisterID dest)
@@ -967,23 +967,27 @@ public:
         if (cond & DoubleConditionBitSpecial)
             m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
         return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
     }
 
     // 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)
     {
-        (void)(src);
-        (void)(dest);
-        ASSERT_NOT_REACHED();
-        return jump();
+        m_assembler.ftosizd_r(ARMRegisters::SD0, src);
+        // If FTOSIZD (VCVT.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.fmrs_r(dest, ARMRegisters::SD0);
+        m_assembler.cmn_r(dest, ARMAssembler::getOp2(1));
+        m_assembler.cmp_r(dest, ARMAssembler::getOp2(0x80000000), ARMCondition(NonZero));
+        return Jump(m_assembler.jmp(ARMCondition(Zero)));
     }
 
     // Convert '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, 0).
     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
     {