Bug 517567: NJ: ARM asm_arg does not handle LIR_ldq in register parameters with softfloat, r=dvander
authorAndreas Gal <gal@uci.edu>
Mon, 21 Sep 2009 12:35:37 -0700
changeset 32923 0f8644e0ff5511a7f78bbd53545ee25a90b2da0d
parent 32922 ccb1560bb97c58f8af3574f0bb6e7b99c017a667
child 32924 3a6c1c8137f5af1e5583aad3a175eaf136302727
push idunknown
push userunknown
push dateunknown
reviewersdvander
bugs517567
milestone1.9.3a1pre
Bug 517567: NJ: ARM asm_arg does not handle LIR_ldq in register parameters with softfloat, r=dvander
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -1404,82 +1404,113 @@ JS_DEFINE_CALLINFO_2(static, DOUBLE, fdi
 
 static jsdouble FASTCALL
 fsub(jsdouble x, jsdouble y)
 {
     return x - y;
 }
 JS_DEFINE_CALLINFO_2(static, DOUBLE, fsub, DOUBLE, DOUBLE, 1, 1)
 
+// replace fpu ops with function calls
 class SoftFloatFilter: public LirWriter
 {
 public:
-    SoftFloatFilter(LirWriter* out):
-        LirWriter(out)
-    {
-    }
-
-    LIns* quadCall(const CallInfo *ci, LIns* args[]) {
-        LInsp qlo, qhi;
-
-        qlo = out->insCall(ci, args);
-        qhi = out->ins1(LIR_callh, qlo);
-        return out->qjoin(qlo, qhi);
-    }
-
-    LIns* ins1(LOpcode v, LIns* s0)
-    {
-        if (v == LIR_fneg)
-            return quadCall(&fneg_ci, &s0);
-
-        if (v == LIR_i2f)
-            return quadCall(&i2f_ci, &s0);
-
-        if (v == LIR_u2f)
-            return quadCall(&u2f_ci, &s0);
-
-        return out->ins1(v, s0);
-    }
-
-    LIns* ins2(LOpcode v, LIns* s0, LIns* s1)
-    {
-        LIns* args[2];
-        LIns* bv;
-
-        // change the numeric value and order of these LIR opcodes and die
-        if (LIR_fadd <= v && v <= LIR_fdiv) {
-            static const CallInfo *fmap[] = { &fadd_ci, &fsub_ci, &fmul_ci, &fdiv_ci };
-
-            args[0] = s1;
-            args[1] = s0;
-
-            return quadCall(fmap[v - LIR_fadd], args);
-        }
-
-        if (LIR_feq <= v && v <= LIR_fge) {
-            static const CallInfo *fmap[] = { &fcmpeq_ci, &fcmplt_ci, &fcmpgt_ci, &fcmple_ci, &fcmpge_ci };
-
-            args[0] = s1;
-            args[1] = s0;
-
-            bv = out->insCall(fmap[v - LIR_feq], args);
-            return out->ins2(LIR_eq, bv, out->insImm(1));
-        }
-
-        return out->ins2(v, s0, s1);
-    }
-
-    LIns* insCall(const CallInfo *ci, LIns* args[])
-    {
-        // if the return type is ARGSIZE_F, we have
-        // to do a quadCall(qjoin(call,callh))
-        if ((ci->_argtypes & ARGSIZE_MASK_ANY) == ARGSIZE_F)
-            return quadCall(ci, args);
-
-        return out->insCall(ci, args);
+    SoftFloatFilter(LirWriter *out) : LirWriter(out)
+    {}
+
+    LIns *hi(LIns *q) {
+        return ins1(LIR_qhi, q);
+    }
+    LIns *lo(LIns *q) {
+        return ins1(LIR_qlo, q);
+    }
+
+    LIns *split(LIns *a) {
+        if (a->isQuad() && !a->isop(LIR_qjoin)) {
+            // all quad-sized args must be qjoin's for soft-float
+            a = ins2(LIR_qjoin, lo(a), hi(a));
+        }
+        return a;
+    }
+
+    LIns *split(const CallInfo *call, LInsp args[]) {
+        LIns *lo = out->insCall(call, args);
+        LIns *hi = out->ins1(LIR_callh, lo);
+        return out->ins2(LIR_qjoin, lo, hi);
+    }
+
+    LIns *fcall1(const CallInfo *call, LIns *a) {
+        LIns *args[] = { split(a) };
+        return split(call, args);
+    }
+
+    LIns *fcall2(const CallInfo *call, LIns *a, LIns *b) {
+        LIns *args[] = { split(b), split(a) };
+        return split(call, args);
+    }
+
+    LIns *fcmp(const CallInfo *call, LIns *a, LIns *b) {
+        LIns *args[] = { split(b), split(a) };
+        return out->ins2(LIR_eq, out->insCall(call, args), out->insImm(1));
+    }
+
+    LIns *ins1(LOpcode op, LIns *a) {
+        switch (op) {
+        case LIR_i2f:
+            return fcall1(&i2f_ci, a);
+        case LIR_u2f:
+            return fcall1(&u2f_ci, a);
+        case LIR_fneg:
+            return fcall1(&fneg_ci, a);
+        case LIR_fret:
+            return out->ins1(op, split(a));
+        default:
+            return out->ins1(op, a);
+        }
+    }
+
+    LIns *ins2(LOpcode op, LIns *a, LIns *b) {
+        switch (op) {
+        case LIR_fadd:
+            return fcall2(&fadd_ci, a, b);
+        case LIR_fsub:
+            return fcall2(&fsub_ci, a, b);
+        case LIR_fmul:
+            return fcall2(&fmul_ci, a, b);
+        case LIR_fdiv:
+            return fcall2(&fdiv_ci, a, b);
+        case LIR_feq:
+            return fcmp(&fcmpeq_ci, a, b);
+        case LIR_flt:
+            return fcmp(&fcmplt_ci, a, b);
+        case LIR_fgt:
+            return fcmp(&fcmpgt_ci, a, b);
+        case LIR_fle:
+            return fcmp(&fcmple_ci, a, b);
+        case LIR_fge:
+            return fcmp(&fcmpge_ci, a, b);
+        default:
+            ;
+        }
+        return out->ins2(op, a, b);
+    }
+
+    LIns *insCall(const CallInfo *ci, LInsp args[]) {
+        uint32_t argt = ci->_argtypes;
+
+        for (uint32_t i = 0, argsizes = argt >> ARGSIZE_SHIFT; argsizes != 0; i++, argsizes >>= ARGSIZE_SHIFT)
+            args[i] = split(args[i]);
+
+        if ((argt & ARGSIZE_MASK_ANY) == ARGSIZE_F) {
+            // this function returns a double as two 32bit values, so replace
+            // call with qjoin(qhi(call), call)
+            return split(ci, args);
+        } else {
+            return out->insCall(ci, args);
+        }
     }
 };
 
 class FuncFilter: public LirWriter
 {
 public:
     FuncFilter(LirWriter* out):
         LirWriter(out)