From: Cerion Armour-Brown Date: Tue, 22 Feb 2005 20:36:49 +0000 (+0000) Subject: Added new instruction RdWrLR to read/write link register. X-Git-Tag: svn/VALGRIND_3_0_1^2~385 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ee3dba903c03d4f7e8d281c3bd7366abd14975d0;p=thirdparty%2Fvalgrind.git Added new instruction RdWrLR to read/write link register. 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 --- diff --git a/VEX/priv/host-ppc32/hdefs.c b/VEX/priv/host-ppc32/hdefs.c index a0d86c71ab..c96e369420 100644 --- a/VEX/priv/host-ppc32/hdefs.c +++ b/VEX/priv/host-ppc32/hdefs.c @@ -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; } diff --git a/VEX/priv/host-ppc32/hdefs.h b/VEX/priv/host-ppc32/hdefs.h index 9a991e0e84..966e5a652a 100644 --- a/VEX/priv/host-ppc32/hdefs.h +++ b/VEX/priv/host-ppc32/hdefs.h @@ -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* ); diff --git a/VEX/priv/host-ppc32/isel.c b/VEX/priv/host-ppc32/isel.c index cd2b0b8dc0..0599578f0c 100644 --- a/VEX/priv/host-ppc32/isel.c +++ b/VEX/priv/host-ppc32/isel.c @@ -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]) diff --git a/VEX/switchback/switchback.c b/VEX/switchback/switchback.c index 87f5f1c4ab..de68c70150 100644 --- a/VEX/switchback/switchback.c +++ b/VEX/switchback/switchback.c @@ -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);