mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 517567: NJ: ARM asm_arg does not handle LIR_ldq in register parameters with softfloat, r=dvander
This commit is contained in:
parent
22715396a4
commit
23b5f8a4b9
@ -1409,72 +1409,103 @@ fsub(jsdouble x, jsdouble 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)
|
||||
{
|
||||
SoftFloatFilter(LirWriter *out) : LirWriter(out)
|
||||
{}
|
||||
|
||||
LIns *hi(LIns *q) {
|
||||
return ins1(LIR_qhi, q);
|
||||
}
|
||||
LIns *lo(LIns *q) {
|
||||
return ins1(LIR_qlo, q);
|
||||
}
|
||||
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
return a;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
return out->insCall(ci, args);
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user