]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Added new instruction RdWrLR to read/write link register.
authorCerion Armour-Brown <cerion@valgrind.org>
Tue, 22 Feb 2005 20:36:49 +0000 (20:36 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Tue, 22 Feb 2005 20:36:49 +0000 (20:36 +0000)
The LR is saved in ISelEnv at the start of every bb
The LR is restored before any Goto.
This is needed because LR is a caller-saved register on PPC32, so helper functions may kill it.
(Could save/restore around each helper call, but not efficient)

git-svn-id: svn://svn.valgrind.org/vex/trunk@949

VEX/priv/host-ppc32/hdefs.c
VEX/priv/host-ppc32/hdefs.h
VEX/priv/host-ppc32/isel.c
VEX/switchback/switchback.c

index a0d86c71ab57298e1731601d1d93545413e83e74..c96e369420a7faad59d27d4e831de3527f38e557 100644 (file)
@@ -679,6 +679,16 @@ PPC32Instr* PPC32Instr_MFence ( void )
 //..    return i;
 //.. }
 
+/* Read/Write Link Register */
+PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr )
+{
+   PPC32Instr* i      = LibVEX_Alloc(sizeof(PPC32Instr));
+   i->tag             = Pin_RdWrLR;
+   i->Pin.RdWrLR.wrLR = wrLR;
+   i->Pin.RdWrLR.gpr  = gpr;
+   return i;
+}
+
 void ppPPC32Instr ( PPC32Instr* i )
 {
    switch (i->tag) {
@@ -1021,6 +1031,11 @@ void ppPPC32Instr ( PPC32Instr* i )
 //..          ppHRegX86(i->Xin.SseShuf.dst);
 //..          return;
 
+   case Pin_RdWrLR:
+      vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
+      ppHRegPPC32(i->Pin.RdWrLR.gpr);
+      return;
+
    default:
       vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", i->tag);
       vpanic("ppPPC32Instr(ppc32)");
@@ -1250,6 +1265,12 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
 //..          addHRegUse(u, HRmRead,  i->Xin.SseShuf.src);
 //..          addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
 //..          return;
+
+   case Pin_RdWrLR:
+      addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
+                 i->Pin.RdWrLR.gpr);
+      return;
+
    default:
       ppPPC32Instr(i);
       vpanic("getRegUsage_PPC32Instr");
@@ -1400,6 +1421,11 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
 //..          mapReg(m, &i->Xin.SseShuf.src);
 //..          mapReg(m, &i->Xin.SseShuf.dst);
 //..          return;
+
+   case Pin_RdWrLR:
+      mapReg(m, &i->Pin.RdWrLR.gpr);
+      return;
+
    default:
       ppPPC32Instr(i);
       vpanic("mapRegs_PPC32Instr");
@@ -2812,6 +2838,13 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
 //..       *p++ = (UChar)(i->Xin.SseShuf.order);
 //..       goto done;
 
+   case Pin_RdWrLR: {
+      UInt reg = iregNo(i->Pin.RdWrLR.gpr);
+      /* wrLR==True ? mtlr r4 : mflr r4 */
+      p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
+      goto done;
+   }
+
    default: 
       goto bad;
    }
index 9a991e0e841a5d4a969d57d19f8464796a085fbc..966e5a652ae2c4658946469b55504057a25a10e5 100644 (file)
@@ -334,7 +334,8 @@ typedef
 //..       Xin_FpLdStCW,  /* fldcw / fstcw */
 //..       Xin_FpStSW_AX, /* fstsw %ax */
 //..       Xin_FpCmp,     /* FP compare, generating a C320 value into int reg */
-      Pin_Nada // Nix
+
+      Pin_RdWrLR     /* Read/Write Link Register */
    }
    PPC32InstrTag;
 
@@ -506,6 +507,11 @@ typedef
 //..             HReg    dst;
 //..          } FpCmp;
 
+         /* Read/Write Link Register */
+         struct {
+            Bool wrLR;
+            HReg gpr;
+         } RdWrLR;
        } Pin;
    }
    PPC32Instr;
@@ -539,6 +545,8 @@ extern PPC32Instr* PPC32Instr_MFence    ( void );
 //.. extern X86Instr* X86Instr_FpStSW_AX ( void );
 //.. extern X86Instr* X86Instr_FpCmp     ( HReg srcL, HReg srcR, HReg dst );
 
+extern PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr );
+
 
 extern void ppPPC32Instr ( PPC32Instr* );
 
index cd2b0b8dc015f39115a6294076aedb1dede01c25..0599578f0ccf7687c88306be2ad35cfa45ce0755 100644 (file)
@@ -153,7 +153,9 @@ static IRExpr* bind ( Int binder )
               IRTemps.  It holds the identity of a second
               32-bit virtual HReg, which holds the high half
               of the value.
+
+    - A copy of the link reg, so helper functions don't kill it.
+
     - The code array, that is, the insns selected so far.
  
     - A counter, for generating new virtual registers.
@@ -173,6 +175,8 @@ typedef
       HReg*        vregmapHI;
       Int          n_vregmap;
  
+      HReg         savedLR;
+
       HInstrArray* code;
  
       Int          vreg_ctr;
@@ -3354,6 +3358,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
          vpanic("isel_ppc32: Ist_Exit: dst is not a 32-bit value");
       dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
       cc  = iselCondCode(env,stmt->Ist.Exit.guard);
+      addInstr(env, PPC32Instr_RdWrLR(True, env->savedLR));
       addInstr(env, PPC32Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
       return;
    }
@@ -3382,6 +3387,7 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
    }
    cond = mk_PPCCondCode( Pct_ALWAYS,  Pcf_EQ );
    ri = iselIntExpr_RI(env, next);
+   addInstr(env, PPC32Instr_RdWrLR(True, env->savedLR));
    addInstr(env, PPC32Instr_Goto(jk, cond, ri));
 }
 
@@ -3444,6 +3450,10 @@ HInstrArray* iselBB_PPC32 ( IRBB* bb, VexSubArch subarch_host )
    }
    env->vreg_ctr = j;
 
+   /* Keep a copy of the link reg, so helper functions don't kill it. */
+   env->savedLR = newVRegI(env);
+   addInstr(env, PPC32Instr_RdWrLR(False, env->savedLR));
+
    /* Ok, finally we can iterate over the statements. */
    for (i = 0; i < bb->stmts_used; i++)
       if (bb->stmts[i])
index 87f5f1c4ab185bc75a9a6a9b58a574b58ddff4c0..de68c70150016a18c334f15aff11128aa48ea451 100644 (file)
@@ -301,7 +301,7 @@ void switchback ( void )
    sb_helper2 = LibVEX_GuestPPC32_get_flags(&gst);
 
    /* stay sane ... */
-   assert(p[0] == 24<<26);
+   assert(p[0] == 24<<26); /* nop */
 
 #if 0
    printf("addr of first nop = 0x%x\n", addr_of_nop);
@@ -666,6 +666,7 @@ int main ( Int argc, HChar** argv )
    LibVEX_default_VexControl(&vcon);
    vcon.guest_max_insns=1;
    vcon.guest_chase_thresh=0;
+//   vcon.iropt_level=2;
 
    LibVEX_Init( failure_exit, log_bytes, 1, False, &vcon );
    LibVEX_Guest_initialise(&gst);