]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
ppc32/64 equivalents to r2636: fix up the ppc back end to be in sync
authorJulian Seward <jseward@acm.org>
Wed, 16 Jan 2013 14:56:06 +0000 (14:56 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 16 Jan 2013 14:56:06 +0000 (14:56 +0000)
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

VEX/priv/host_ppc_defs.c
VEX/priv/host_ppc_defs.h
VEX/priv/host_ppc_isel.c

index 7cc7312cfeb4abeb677a6146209d7942f4abd364..32e88fa5798283c96cc196202aa03485d3982a95 100644 (file)
@@ -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
index 344b4acd0eecda9b89dd906ee9db4f76dcaa1a15..b1a567c03e4815b60439d646516a0a69dfb543df 100644 (file)
@@ -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,
index 7b3b2d7334163716b47715c04af4539ce81c659b..5dbf70d7d47b0eb783c08c080108e4c095fc8765 100644 (file)
@@ -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;