From: Julian Seward Date: Wed, 16 Jan 2013 22:11:13 +0000 (+0000) Subject: mips32 equivalent to r2636: fix up the mips32 back end to be in sync X-Git-Tag: svn/VALGRIND_3_9_0^2~152^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=822bab640d7adb9f434e814a17204580187bb5d5;p=thirdparty%2Fvalgrind.git mips32 equivalent to r2636: fix up the mips32 back end to be in sync with infrastructural changes w.r.t. conditional dirty helpers that return values. Does not actually handle such cases since the mips32 front end does not generate them. git-svn-id: svn://svn.valgrind.org/vex/branches/COMEM@2641 --- diff --git a/VEX/priv/host_mips_defs.c b/VEX/priv/host_mips_defs.c index 1f5151d22e..9f0a602be3 100644 --- a/VEX/priv/host_mips_defs.c +++ b/VEX/priv/host_mips_defs.c @@ -1217,7 +1217,7 @@ MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg srcL, HReg srcR) } MIPSInstr *MIPSInstr_Call(MIPSCondCode cond, Addr32 target, UInt argiregs, - HReg src) + HReg src, RetLoc rloc) { UInt mask; MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); @@ -1226,13 +1226,16 @@ MIPSInstr *MIPSInstr_Call(MIPSCondCode cond, Addr32 target, UInt argiregs, i->Min.Call.target = target; i->Min.Call.argiregs = argiregs; i->Min.Call.src = src; + i->Min.Call.rloc = rloc; /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */ mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); vassert(0 == (argiregs & ~mask)); + vassert(rloc != RetLocINVALID); return i; } -MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs) +MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs, + RetLoc rloc) { UInt mask; MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); @@ -1240,9 +1243,11 @@ MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs) i->Min.Call.cond = cond; i->Min.Call.target = target; i->Min.Call.argiregs = argiregs; + i->Min.Call.rloc = rloc; /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */ mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); vassert(0 == (argiregs & ~mask)); + vassert(rloc != RetLocINVALID); return i; } @@ -1611,6 +1616,8 @@ void ppMIPSInstr(MIPSInstr * i, Bool mode64) vex_printf(","); } } + vex_printf(","); + ppRetLoc(i->Min.Call.rloc); vex_printf("] }"); break; } @@ -3118,6 +3125,16 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc, } case Min_Call: { + if (i->Min.Call.cond != MIPScc_AL && i->Min.Call.rloc != RetLocNone) { + /* The call might not happen (it isn't unconditional) and + it returns a result. In this case we will need to + generate a control flow diamond to put 0x555..555 in + the return register(s) in the case where the call + doesn't happen. If this ever becomes necessary, maybe + copy code from the ARM equivalent. Until that day, + just give up. */ + goto bad; + } MIPSCondCode cond = i->Min.Call.cond; UInt r_dst = 25; /* using %r25 as address temporary - see getRegUsage_MIPSInstr */ diff --git a/VEX/priv/host_mips_defs.h b/VEX/priv/host_mips_defs.h index 6de01d21c1..fbcf3fb337 100644 --- a/VEX/priv/host_mips_defs.h +++ b/VEX/priv/host_mips_defs.h @@ -493,6 +493,7 @@ typedef struct { Addr32 target; UInt argiregs; HReg src; + RetLoc rloc; /* where the return value will be */ } Call; /* Update the guest EIP value, then exit requesting to chain to it. May be conditional. Urr, use of Addr32 implicitly @@ -654,8 +655,8 @@ extern MIPSInstr *MIPSInstr_LoadL(UChar sz, HReg dst, MIPSAMode * src, extern MIPSInstr *MIPSInstr_StoreC(UChar sz, MIPSAMode * dst, HReg src, Bool mode64); -extern MIPSInstr *MIPSInstr_Call(MIPSCondCode, Addr32, UInt, HReg); -extern MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode, Addr32, UInt); +extern MIPSInstr *MIPSInstr_Call(MIPSCondCode, Addr32, UInt, HReg, RetLoc); +extern MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode, Addr32, UInt, RetLoc); extern MIPSInstr *MIPSInstr_XDirect(Addr32 dstGA, MIPSAMode* amPC, MIPSCondCode cond, Bool toFastEP); diff --git a/VEX/priv/host_mips_isel.c b/VEX/priv/host_mips_isel.c index 56481d18e5..4bc2242fff 100644 --- a/VEX/priv/host_mips_isel.c +++ b/VEX/priv/host_mips_isel.c @@ -362,7 +362,7 @@ static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo) call is unconditional. */ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard, - IRCallee * cee, IRExpr ** args) + IRCallee * cee, IRExpr ** args, RetLoc rloc) { MIPSCondCode cc; HReg argregs[MIPS_N_REGPARMS]; @@ -526,13 +526,13 @@ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard, /* Finally, the call itself. */ if (mode64) if (cc == MIPScc_AL) { - addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs)); + addInstr(env, MIPSInstr_CallAlways(cc, target, argiregs, rloc)); } else { - addInstr(env, MIPSInstr_Call(cc, target, argiregs, src)); + addInstr(env, MIPSInstr_Call(cc, target, argiregs, src, rloc)); } else if (cc == MIPScc_AL) { - addInstr(env, MIPSInstr_CallAlways(cc, (Addr32) target, argiregs)); + addInstr(env, MIPSInstr_CallAlways(cc, (Addr32) target, argiregs, rloc)); } else { - addInstr(env, MIPSInstr_Call(cc, (Addr32) target, argiregs, src)); + addInstr(env, MIPSInstr_Call(cc, (Addr32) target, argiregs, src, rloc)); } /* restore GuestStatePointer */ addInstr(env, MIPSInstr_Load(4, GuestStatePointer(mode64), @@ -1485,13 +1485,26 @@ static HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e) HReg r_dst = newVRegI(env); vassert(ty == e->Iex.CCall.retty); - /* be very restrictive for now. Only 32/64-bit ints allowed - for args, and 32 bits for return type. */ + /* be very restrictive for now. Only 32/64-bit ints allowed for + args, and 32 bits for return type. Don't forget to change + the RetLoc if more return types are allowed in future. */ if (e->Iex.CCall.retty != Ity_I32 && !mode64) goto irreducible; + /* What's the retloc? */ + RetLoc rloc = RetLocINVALID; + if (ty == Ity_I32) { + rloc = RetLocInt; + } + else if (ty == Ity_I64) { + rloc = mode64 ? RetLocInt : RetLoc2Int; + } + else { + goto irreducible; + } + /* Marshal args, do the call, clear stack. */ - doHelperCall(env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args); + doHelperCall(env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args, rloc); addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64))); return r_dst; } @@ -2895,23 +2908,47 @@ static void iselStmt(ISelEnv * env, IRStmt * stmt) /* --------- Call to DIRTY helper --------- */ case Ist_Dirty: { - IRType retty; IRDirty *d = stmt->Ist.Dirty.details; Bool passBBP = False; if (d->nFxState == 0) vassert(!d->needsBBP); + passBBP = toBool(d->nFxState > 0 && d->needsBBP); + /* Figure out the return type, if any. */ + IRType retty = Ity_INVALID; + if (d->tmp != IRTemp_INVALID) + retty = typeOfIRTemp(env->type_env, d->tmp); + + /* Marshal args, do the call, clear stack, set the return + value to 0x555..555 if this is a conditional call that + returns a value and the call is skipped. We need to set + the ret-loc correctly in order to implement the IRDirty + semantics that the return value is 0x555..555 if the call + doesn't happen. */ + RetLoc rloc = RetLocINVALID; + switch (retty) { + case Ity_INVALID: /* function doesn't return anything */ + rloc = RetLocNone; break; + case Ity_I64: + rloc = mode64 ? RetLocInt : RetLoc2Int; break; + case Ity_I32: case Ity_I16: case Ity_I8: + rloc = RetLocInt; break; + default: + break; + } + if (rloc == RetLocINVALID) + break; /* will go to stmt_fail: */ + /* Marshal args, do the call, clear stack. */ - doHelperCall(env, passBBP, d->guard, d->cee, d->args); + doHelperCall(env, passBBP, d->guard, d->cee, d->args, rloc); /* Now figure out what to do with the returned value, if any. */ if (d->tmp == IRTemp_INVALID) /* No return value. Nothing to do. */ return; - retty = typeOfIRTemp(env->type_env, d->tmp); if (retty == Ity_I64 && !mode64) { HReg rHi = newVRegI(env); HReg rLo = newVRegI(env);