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