From 1b0b34ae5eaa9c8e09e97012c52f0b3bc84ff94c Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sun, 21 Aug 2005 00:48:37 +0000 Subject: [PATCH] On a PPC32Instr_Call, don't merely record how many integer registers carry parameters. Instead record the actual identities of such registers in a bitmask. This is necessary because the PPC calling conventions have "holes" in the register ranges. For example, a routine taking an UInt(32-bit) first param and an ULong(64-bit) second param passes the first arg in r3 but the second one in r5 and r6, and r4 is not used. git-svn-id: svn://svn.valgrind.org/vex/trunk@1340 --- VEX/priv/host-ppc32/hdefs.c | 50 ++++++++++++++++++++++++------------- VEX/priv/host-ppc32/hdefs.h | 9 ++++--- VEX/priv/host-ppc32/isel.c | 9 ++++++- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/VEX/priv/host-ppc32/hdefs.c b/VEX/priv/host-ppc32/hdefs.c index 03a78199a6..adbe238728 100644 --- a/VEX/priv/host-ppc32/hdefs.c +++ b/VEX/priv/host-ppc32/hdefs.c @@ -706,13 +706,16 @@ PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) { return i; } PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, - Addr32 target, Int regparms ) { + Addr32 target, UInt argiregs ) { + UInt mask; PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr)); i->tag = Pin_Call; i->Pin.Call.cond = cond; i->Pin.Call.target = target; - i->Pin.Call.regparms = regparms; - vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS); + i->Pin.Call.argiregs = argiregs; + /* 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)); return i; } PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, @@ -1054,15 +1057,25 @@ void ppPPC32Instr ( PPC32Instr* i ) vex_printf(","); ppHRegPPC32(i->Pin.Div.srcR); return; - case Pin_Call: + case Pin_Call: { + Int n; vex_printf("call: "); if (i->Pin.Call.cond.test != Pct_ALWAYS) { vex_printf("if (%s) ", showPPC32CondCode(i->Pin.Call.cond)); } vex_printf("{ "); ppLoadImm(hregPPC32_GPR12(), i->Pin.Call.target); - vex_printf(" ; mtctr r12 ; bctrl [regparms=%d] }",i->Pin.Call.regparms); + vex_printf(" ; mtctr r12 ; bctrl ["); + for (n = 0; n < 32; n++) { + if (i->Pin.Call.argiregs & (1<Pin.Call.argiregs >> n) > 1) + vex_printf(","); + } + } + vex_printf("] }"); break; + } case Pin_Goto: vex_printf("goto: "); if (i->Pin.Goto.cond.test != Pct_ALWAYS) { @@ -1438,19 +1451,20 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) addHRegUse(u, HRmWrite, hregPPC32_GPR12()); /* Now we have to state any parameter-carrying registers - which might be read. This depends on the regparmness. */ - switch (i->Pin.Call.regparms) { - case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/ - case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/ - case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/ - case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/ - case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/ - case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/ - case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/ - case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/ - case 0: break; - default: vpanic("getRegUsage_PPC32Instr:Call:regparms"); - } + which might be read. This depends on the argiregs field. */ + if (i->Pin.Call.argiregs & (1<<10)) addHRegUse(u, HRmRead, hregPPC32_GPR10()); + if (i->Pin.Call.argiregs & (1<<9)) addHRegUse(u, HRmRead, hregPPC32_GPR9()); + if (i->Pin.Call.argiregs & (1<<8)) addHRegUse(u, HRmRead, hregPPC32_GPR8()); + if (i->Pin.Call.argiregs & (1<<7)) addHRegUse(u, HRmRead, hregPPC32_GPR7()); + if (i->Pin.Call.argiregs & (1<<6)) addHRegUse(u, HRmRead, hregPPC32_GPR6()); + if (i->Pin.Call.argiregs & (1<<5)) addHRegUse(u, HRmRead, hregPPC32_GPR5()); + if (i->Pin.Call.argiregs & (1<<4)) addHRegUse(u, HRmRead, hregPPC32_GPR4()); + if (i->Pin.Call.argiregs & (1<<3)) addHRegUse(u, HRmRead, hregPPC32_GPR3()); + + vassert(0 == (i->Pin.Call.argiregs + & ~((1<<3)|(1<<4)|(1<<5)|(1<<6) + |(1<<7)|(1<<8)|(1<<9)|(1<<10)))); + /* Finally, there is the issue that the insn trashes a register because the literal target address has to be loaded into a register. %r12 seems a suitable victim. diff --git a/VEX/priv/host-ppc32/hdefs.h b/VEX/priv/host-ppc32/hdefs.h index bdc88f0cab..d8f1148bd3 100644 --- a/VEX/priv/host-ppc32/hdefs.h +++ b/VEX/priv/host-ppc32/hdefs.h @@ -494,11 +494,14 @@ typedef HReg srcR; } Div; /* Pseudo-insn. Call target (an absolute address), on given - condition (which could be Pct_ALWAYS). */ + condition (which could be Pct_ALWAYS). argiregs indicates + which of r3 .. r10 carries argument values for this call, + using a bit mask (1<type_env, args[i]) == Ity_I32 || typeOfIRExpr(env->type_env, args[i]) == Ity_I64); if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) { + argiregs |= (1 << (argreg+3)); addInstr(env, mk_iMOVds_RR( argregs[argreg], iselIntExpr_R(env, args[i]) )); } else { // Ity_I64 @@ -535,7 +539,9 @@ void doHelperCall ( ISelEnv* env, argreg++; // XXX: odd argreg => even rN vassert(argreg < PPC32_N_REGPARMS-1); iselInt64Expr(&rHi,&rLo, env, args[i]); + argiregs |= (1 << (argreg+3)); addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi )); + argiregs |= (1 << (argreg+3)); addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo)); } argreg++; @@ -596,6 +602,7 @@ void doHelperCall ( ISelEnv* env, continue; /* None of these insns, including any spill code that might be generated, may alter the condition codes. */ + argiregs |= (1 << (i+3)); addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) ); } @@ -604,7 +611,7 @@ void doHelperCall ( ISelEnv* env, /* Finally, the call itself. */ addInstr(env, PPC32Instr_Call( cc, (Addr32)toUInt(Ptr_to_ULong(cee->addr)), - n_args + (passBBP ? 1 : 0) )); + argiregs )); } -- 2.47.3