From: Julian Seward Date: Wed, 16 Jan 2013 14:56:06 +0000 (+0000) Subject: ppc32/64 equivalents to r2636: fix up the ppc back end to be in sync X-Git-Tag: svn/VALGRIND_3_9_0^2~152^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b509fdf8ef986f1dad2c5902325dbaf33eda5b9;p=thirdparty%2Fvalgrind.git ppc32/64 equivalents to r2636: fix up the ppc 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 ppc front end does not generate them. git-svn-id: svn://svn.valgrind.org/vex/branches/COMEM@2639 --- diff --git a/VEX/priv/host_ppc_defs.c b/VEX/priv/host_ppc_defs.c index 7cc7312cfe..32e88fa579 100644 --- a/VEX/priv/host_ppc_defs.c +++ b/VEX/priv/host_ppc_defs.c @@ -839,16 +839,18 @@ PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32, return i; } PPCInstr* PPCInstr_Call ( PPCCondCode cond, - Addr64 target, UInt argiregs ) { + Addr64 target, UInt argiregs, RetLoc rloc ) { UInt mask; PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); i->tag = Pin_Call; i->Pin.Call.cond = cond; i->Pin.Call.target = target; i->Pin.Call.argiregs = argiregs; + i->Pin.Call.rloc = rloc; /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */ mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10); vassert(0 == (argiregs & ~mask)); + vassert(rloc != RetLocINVALID); return i; } PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA, @@ -1553,6 +1555,8 @@ void ppPPCInstr ( PPCInstr* i, Bool mode64 ) vex_printf(","); } } + vex_printf(","); + ppRetLoc(i->Pin.Call.rloc); vex_printf("] }"); break; } @@ -3908,6 +3912,16 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc, } case Pin_Call: { + if (i->Pin.Call.cond.test != Pct_ALWAYS + && i->Pin.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; + } PPCCondCode cond = i->Pin.Call.cond; UInt r_dst = 10; /* As per detailed comment for Pin_Call in diff --git a/VEX/priv/host_ppc_defs.h b/VEX/priv/host_ppc_defs.h index 344b4acd0e..b1a567c03e 100644 --- a/VEX/priv/host_ppc_defs.h +++ b/VEX/priv/host_ppc_defs.h @@ -616,6 +616,7 @@ typedef PPCCondCode cond; Addr64 target; UInt argiregs; + RetLoc rloc; /* where the return value will be */ } Call; /* Update the guest CIA value, then exit requesting to chain to it. May be conditional. Use of Addr64 in order to cope @@ -971,7 +972,7 @@ extern PPCInstr* PPCInstr_Cmp ( Bool, Bool, UInt, HReg, PPCRH* ); extern PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ); extern PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi32, Bool sz32, HReg, HReg, HReg ); extern PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32, HReg dst, HReg srcL, HReg srcR ); -extern PPCInstr* PPCInstr_Call ( PPCCondCode, Addr64, UInt ); +extern PPCInstr* PPCInstr_Call ( PPCCondCode, Addr64, UInt, RetLoc ); extern PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA, PPCCondCode cond, Bool toFastEP ); extern PPCInstr* PPCInstr_XIndir ( HReg dstGA, PPCAMode* amCIA, diff --git a/VEX/priv/host_ppc_isel.c b/VEX/priv/host_ppc_isel.c index 7b3b2d7334..5dbf70d7d4 100644 --- a/VEX/priv/host_ppc_isel.c +++ b/VEX/priv/host_ppc_isel.c @@ -1,5 +1,4 @@ - /*---------------------------------------------------------------*/ /*--- begin host_ppc_isel.c ---*/ /*---------------------------------------------------------------*/ @@ -672,7 +671,8 @@ Bool mightRequireFixedRegs ( IRExpr* e ) static void doHelperCall ( ISelEnv* env, Bool passBBP, - IRExpr* guard, IRCallee* cee, IRExpr** args ) + IRExpr* guard, IRCallee* cee, IRExpr** args, + RetLoc rloc ) { PPCCondCode cc; HReg argregs[PPC_N_REGPARMS]; @@ -902,7 +902,7 @@ void doHelperCall ( ISelEnv* env, toUInt(Ptr_to_ULong(cee->addr)); /* Finally, the call itself. */ - addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs )); + addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs, rloc )); } @@ -2008,6 +2008,9 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) break; case Iop_BCDtoDPB: { + /* the following is only valid in 64 bit mode */ + if (!mode64) break; + PPCCondCode cc; UInt argiregs; HReg argregs[1]; @@ -2026,13 +2029,17 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); fdescr = (HWord*)h_BCDtoDPB; - addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), argiregs ) ); + addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), + argiregs, RetLocInt) ); addInstr(env, mk_iMOVds_RR(r_dst, argregs[0])); return r_dst; } case Iop_DPBtoBCD: { + /* the following is only valid in 64 bit mode */ + if (!mode64) break; + PPCCondCode cc; UInt argiregs; HReg argregs[1]; @@ -2051,7 +2058,8 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); fdescr = (HWord*)h_DPBtoBCD; - addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), argiregs ) ); + addInstr(env, PPCInstr_Call( cc, (Addr64)(fdescr[0]), + argiregs, RetLocInt ) ); addInstr(env, mk_iMOVds_RR(r_dst, argregs[0])); return r_dst; @@ -2100,14 +2108,15 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg r_dst = newVRegI(env); vassert(ty == Ity_I32); - /* 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) goto irreducible; /* Marshal args, do the call, clear stack. */ doHelperCall( env, False, NULL, - e->Iex.CCall.cee, e->Iex.CCall.args ); + e->Iex.CCall.cee, e->Iex.CCall.args, RetLocInt ); /* GPR3 now holds the destination address from Pin_Goto */ addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64))); @@ -3262,7 +3271,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, cc = mk_PPCCondCode( Pct_ALWAYS, Pcf_NONE ); target = toUInt( Ptr_to_ULong(h_BCDtoDPB ) ); - addInstr( env, PPCInstr_Call( cc, (Addr64)target, argiregs ) ); + addInstr( env, PPCInstr_Call( cc, (Addr64)target, + argiregs, RetLoc2Int ) ); addInstr( env, mk_iMOVds_RR( tHi, argregs[argreg-1] ) ); addInstr( env, mk_iMOVds_RR( tLo, argregs[argreg] ) ); @@ -3301,7 +3311,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, target = toUInt( Ptr_to_ULong( h_DPBtoBCD ) ); - addInstr(env, PPCInstr_Call( cc, (Addr64)target, argiregs ) ); + addInstr(env, PPCInstr_Call( cc, (Addr64)target, + argiregs, RetLoc2Int ) ); addInstr(env, mk_iMOVds_RR(tHi, argregs[argreg-1])); addInstr(env, mk_iMOVds_RR(tLo, argregs[argreg])); @@ -4973,7 +4984,6 @@ 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; @@ -4981,15 +4991,38 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) 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 (!mode64 && retty == Ity_I64) { HReg r_dstHi, r_dstLo; /* The returned value is in %r3:%r4. Park it in the @@ -4997,6 +5030,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) lookupIRTempPair( &r_dstHi, &r_dstLo, env, d->tmp); addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC_GPR3(mode64))); addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC_GPR4(mode64))); + vassert(rloc == RetLoc2Int); return; } if (retty == Ity_I8 || retty == Ity_I16 || @@ -5005,6 +5039,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) associated with tmp. */ HReg r_dst = lookupIRTemp(env, d->tmp); addInstr(env, mk_iMOVds_RR(r_dst, hregPPC_GPR3(mode64))); + vassert(rloc == RetLocInt); return; } break;