|
From: <sv...@va...> - 2005-08-21 00:48:42
|
Author: sewardj
Date: 2005-08-21 01:48:37 +0100 (Sun, 21 Aug 2005)
New Revision: 1340
Log:
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.
Modified:
trunk/priv/host-ppc32/hdefs.c
trunk/priv/host-ppc32/hdefs.h
trunk/priv/host-ppc32/isel.c
Modified: trunk/priv/host-ppc32/hdefs.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-ppc32/hdefs.c 2005-08-18 11:50:43 UTC (rev 1339)
+++ trunk/priv/host-ppc32/hdefs.c 2005-08-21 00:48:37 UTC (rev 1340)
@@ -706,13 +706,16 @@
return i;
}
PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond,=20
- Addr32 target, Int regparms ) {
+ Addr32 target, UInt argiregs ) {
+ UInt mask;
PPC32Instr* i =3D LibVEX_Alloc(sizeof(PPC32Instr));
i->tag =3D Pin_Call;
i->Pin.Call.cond =3D cond;
i->Pin.Call.target =3D target;
- i->Pin.Call.regparms =3D regparms;
- vassert(regparms >=3D 0 && regparms < PPC32_N_REGPARMS);
+ i->Pin.Call.argiregs =3D argiregs;
+ /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
+ mask =3D (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
+ vassert(0 =3D=3D (argiregs & ~mask));
return i;
}
PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk,=20
@@ -1054,15 +1057,25 @@
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 !=3D 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=3D%d] }",i->Pin.Call.re=
gparms);
+ vex_printf(" ; mtctr r12 ; bctrl [");
+ for (n =3D 0; n < 32; n++) {
+ if (i->Pin.Call.argiregs & (1<<n)) {
+ vex_printf("r%d", n);
+ if ((i->Pin.Call.argiregs >> n) > 1)
+ vex_printf(",");
+ }
+ }
+ vex_printf("] }");
break;
+ }
case Pin_Goto:
vex_printf("goto: ");
if (i->Pin.Goto.cond.test !=3D Pct_ALWAYS) {
@@ -1438,19 +1451,20 @@
addHRegUse(u, HRmWrite, hregPPC32_GPR12());
=20
/* 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, hregPPC=
32_GPR10());
+ if (i->Pin.Call.argiregs & (1<<9)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR9());
+ if (i->Pin.Call.argiregs & (1<<8)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR8());
+ if (i->Pin.Call.argiregs & (1<<7)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR7());
+ if (i->Pin.Call.argiregs & (1<<6)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR6());
+ if (i->Pin.Call.argiregs & (1<<5)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR5());
+ if (i->Pin.Call.argiregs & (1<<4)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR4());
+ if (i->Pin.Call.argiregs & (1<<3)) addHRegUse(u, HRmRead, hregPPC3=
2_GPR3());
+
+ vassert(0 =3D=3D (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.
Modified: trunk/priv/host-ppc32/hdefs.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-ppc32/hdefs.h 2005-08-18 11:50:43 UTC (rev 1339)
+++ trunk/priv/host-ppc32/hdefs.h 2005-08-21 00:48:37 UTC (rev 1340)
@@ -494,11 +494,14 @@
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<<N is set if rN holds an arg, for N in
+ 3 .. 10 inclusive). */
struct {
PPC32CondCode cond;
Addr32 target;
- Int regparms; /* 0 .. 9 */
+ UInt argiregs;
} Call;
/* Pseudo-insn. Goto dst, on given condition (which could be
Pct_ALWAYS). */
@@ -685,7 +688,7 @@
extern PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HR=
eg src );
extern PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool hi32, HReg, =
HReg, HReg );
extern PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg sr=
cL, HReg srcR );
-extern PPC32Instr* PPC32Instr_Call ( PPC32CondCode, Addr32, Int );
+extern PPC32Instr* PPC32Instr_Call ( PPC32CondCode, Addr32, UInt )=
;
extern PPC32Instr* PPC32Instr_Goto ( IRJumpKind, PPC32CondCode con=
d, PPC32RI* dst );
extern PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode, HReg dst, PPC3=
2RI* src );
extern PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
Modified: trunk/priv/host-ppc32/isel.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/host-ppc32/isel.c 2005-08-18 11:50:43 UTC (rev 1339)
+++ trunk/priv/host-ppc32/isel.c 2005-08-21 00:48:37 UTC (rev 1340)
@@ -411,6 +411,7 @@
HReg tmpregs[PPC32_N_REGPARMS];
Bool go_fast;
Int n_args, i, argreg;
+ UInt argiregs;
=20
/* Marshal args for a call and do the call.
=20
@@ -479,6 +480,7 @@
argregs[5] =3D hregPPC32_GPR8();
argregs[6] =3D hregPPC32_GPR9();
argregs[7] =3D hregPPC32_GPR10();
+ argiregs =3D 0;
=20
tmpregs[0] =3D tmpregs[1] =3D tmpregs[2] =3D
tmpregs[3] =3D tmpregs[4] =3D tmpregs[5] =3D
@@ -518,6 +520,7 @@
/* FAST SCHEME */
argreg =3D 0;
if (passBBP) {
+ argiregs |=3D (1 << (argreg+3));
addInstr(env, mk_iMOVds_RR( argregs[argreg], GuestStatePtr ));
argreg++;
}
@@ -527,6 +530,7 @@
vassert(typeOfIRExpr(env->type_env, args[i]) =3D=3D Ity_I32 ||
typeOfIRExpr(env->type_env, args[i]) =3D=3D Ity_I64);
if (typeOfIRExpr(env->type_env, args[i]) =3D=3D Ity_I32) {=20
+ argiregs |=3D (1 << (argreg+3));
addInstr(env, mk_iMOVds_RR( argregs[argreg],
iselIntExpr_R(env, args[i]) ));
} else { // Ity_I64
@@ -535,7 +539,9 @@
argreg++; // XXX: odd argreg =3D> even rN
vassert(argreg < PPC32_N_REGPARMS-1);
iselInt64Expr(&rHi,&rLo, env, args[i]);
+ argiregs |=3D (1 << (argreg+3));
addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
+ argiregs |=3D (1 << (argreg+3));
addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
}
argreg++;
@@ -596,6 +602,7 @@
continue;
/* None of these insns, including any spill code that might
be generated, may alter the condition codes. */
+ argiregs |=3D (1 << (i+3));
addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) );
}
=20
@@ -604,7 +611,7 @@
/* Finally, the call itself. */
addInstr(env, PPC32Instr_Call( cc,
(Addr32)toUInt(Ptr_to_ULong(cee->addr)=
),
- n_args + (passBBP ? 1 : 0) ));
+ argiregs ));
}
=20
=20
|