|
From: <sv...@va...> - 2013-01-21 18:12:42
|
carll 2013-01-21 18:12:31 +0000 (Mon, 21 Jan 2013)
New Revision: 2650
Log:
The 32-bit DFP value is stored in a 64-bit register in
ppc. The D32 to D64 and D64 to D32 definitions for the
Iop type was specified in VEX/priv/ir_defs.c, function
typeOfPrimop() as:
case Iop_D32toD64:
UNARY(Ity_64, Ity_D64);
case Iop_D64toD32:
BINARY(ity_RMode, Ity_D64, Ity_D64);
since the values resided in a 64-bit register. As part of the s390 DFP support
the definitions were changed to:
case Iop_D32toD64:
UNARY(Ity_32, Ity_D64);
case Iop_D64toD32:
BINARY(ity_RMode, Ity_D64, Ity_D32);
to reflect what they really should be. However, this broke the ppc
implementation. Valgrind would fail and report a mismatch on the types as the
ppc code was using a D64 instead of a D32.
This patch adds support for fetching and storing the Dfp32 operand as a 32-bit
value. The support includes adding the functions iselDfp32Expr() and
iselDfp32Expr_wrk() and additional code to support the DFP32 bit iops.
This patch is for Bugzilla 312620.
Modified files:
trunk/priv/guest_ppc_toIR.c
trunk/priv/host_ppc_isel.c
Modified: trunk/priv/host_ppc_isel.c (+95 -2)
===================================================================
--- trunk/priv/host_ppc_isel.c 2013-01-20 23:13:14 +00:00 (rev 2649)
+++ trunk/priv/host_ppc_isel.c 2013-01-21 18:12:31 +00:00 (rev 2650)
@@ -453,6 +453,8 @@
static HReg iselVecExpr ( ISelEnv* env, IRExpr* e );
/* 64-bit mode ONLY. */
+static HReg iselDfp32Expr_wrk ( ISelEnv* env, IRExpr* e );
+static HReg iselDfp32Expr ( ISelEnv* env, IRExpr* e );
static HReg iselDfp64Expr_wrk ( ISelEnv* env, IRExpr* e );
static HReg iselDfp64Expr ( ISelEnv* env, IRExpr* e );
@@ -3822,6 +3824,57 @@
vpanic("iselDblExpr_wrk(ppc)");
}
+static HReg iselDfp32Expr(ISelEnv* env, IRExpr* e)
+{
+ HReg r = iselDfp32Expr_wrk( env, e );
+ vassert(hregClass(r) == HRcFlt64);
+ vassert( hregIsVirtual(r) );
+ return r;
+}
+
+/* DO NOT CALL THIS DIRECTLY */
+static HReg iselDfp32Expr_wrk(ISelEnv* env, IRExpr* e)
+{
+ Bool mode64 = env->mode64;
+ IRType ty = typeOfIRExpr( env->type_env, e );
+
+ vassert( e );
+ vassert( ty == Ity_D32 );
+
+ /* --------- GET --------- */
+ if (e->tag == Iex_Get) {
+ HReg r_dst = newVRegF( env );
+ PPCAMode* am_addr = PPCAMode_IR( e->Iex.Get.offset,
+ GuestStatePtr(mode64) );
+ addInstr( env, PPCInstr_FpLdSt( True/*load*/, 8, r_dst, am_addr ) );
+ return r_dst;
+ }
+
+ /* --------- LOAD --------- */
+ if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
+ PPCAMode* am_addr;
+ HReg r_dst = newVRegF(env);
+ vassert(e->Iex.Load.ty == Ity_D32);
+ am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D32/*xfer*/);
+ addInstr(env, PPCInstr_FpLdSt(True/*load*/, 4, r_dst, am_addr));
+ return r_dst;
+ }
+
+ /* --------- OPS --------- */
+ if (e->tag == Iex_Binop) {
+ if (e->Iex.Binop.op == Iop_D64toD32) {
+ HReg fr_dst = newVRegF(env);
+ HReg fr_src = iselDfp64Expr(env, e->Iex.Binop.arg2);
+ set_FPU_DFP_rounding_mode( env, e->Iex.Binop.arg1 );
+ addInstr(env, PPCInstr_Dfp64Unary(Pfp_DRSP, fr_dst, fr_src));
+ return fr_dst;
+ }
+ }
+
+ ppIRExpr( e );
+ vpanic( "iselDfp32Expr_wrk(ppc)" );
+}
+
static HReg iselDfp64Expr(ISelEnv* env, IRExpr* e)
{
HReg r = iselDfp64Expr_wrk( env, e );
@@ -3853,6 +3906,15 @@
return r_dst;
}
+ if (e->tag == Iex_Load && e->Iex.Load.end == Iend_BE) {
+ PPCAMode* am_addr;
+ HReg r_dst = newVRegF(env);
+ vassert(e->Iex.Load.ty == Ity_D64);
+ am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, Ity_D64/*xfer*/);
+ addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, r_dst, am_addr));
+ return r_dst;
+ }
+
/* --------- OPS --------- */
if (e->tag == Iex_Qop) {
HReg r_dst = newVRegF( env );
@@ -3892,7 +3954,7 @@
return fr_dst;
}
case Iop_D32toD64: {
- HReg fr_src = iselDfp64Expr(env, e->Iex.Unop.arg);
+ HReg fr_src = iselDfp32Expr(env, e->Iex.Unop.arg);
addInstr(env, PPCInstr_Dfp64Unary(Pfp_DCTDP, fr_dst, fr_src));
return fr_dst;
}
@@ -3962,7 +4024,6 @@
HReg fr_dst = newVRegF(env);
switch (e->Iex.Binop.op) {
- case Iop_D64toD32: fpop = Pfp_DRSP; break;
case Iop_I64StoD64: fpop = Pfp_DCFFIX; break;
case Iop_D64toI64S: fpop = Pfp_DCTFIX; break;
default: break;
@@ -4732,6 +4793,22 @@
PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
return;
}
+ if (tyd == Ity_D64) {
+ PPCAMode* am_addr
+ = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
+ HReg fr_src = iselDfp64Expr(env, stmt->Ist.Store.data);
+ addInstr(env,
+ PPCInstr_FpLdSt(False/*store*/, 8, fr_src, am_addr));
+ return;
+ }
+ if (tyd == Ity_D32) {
+ PPCAMode* am_addr
+ = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
+ HReg fr_src = iselDfp32Expr(env, stmt->Ist.Store.data);
+ addInstr(env,
+ PPCInstr_FpLdSt(False/*store*/, 4, fr_src, am_addr));
+ return;
+ }
if (tyd == Ity_V128) {
PPCAMode* am_addr
= iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd/*of xfer*/);
@@ -4800,6 +4877,15 @@
fr_src, am_addr ));
return;
}
+ if (ty == Ity_D32) {
+ /* The 32-bit value is stored in a 64-bit register */
+ HReg fr_src = iselDfp32Expr( env, stmt->Ist.Put.data );
+ PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
+ GuestStatePtr(mode64) );
+ addInstr( env, PPCInstr_FpLdSt( False/*store*/, 8,
+ fr_src, am_addr ) );
+ return;
+ }
if (ty == Ity_D64) {
HReg fr_src = iselDfp64Expr( env, stmt->Ist.Put.data );
PPCAMode* am_addr = PPCAMode_IR( stmt->Ist.Put.offset,
@@ -4897,6 +4983,12 @@
addInstr(env, PPCInstr_FpUnary(Pfp_MOV, fr_dst, fr_src));
return;
}
+ if (ty == Ity_D32) {
+ HReg fr_dst = lookupIRTemp(env, tmp);
+ HReg fr_src = iselDfp32Expr(env, stmt->Ist.WrTmp.data);
+ addInstr(env, PPCInstr_Dfp64Unary(Pfp_MOV, fr_dst, fr_src));
+ return;
+ }
if (ty == Ity_V128) {
HReg v_dst = lookupIRTemp(env, tmp);
HReg v_src = iselVecExpr(env, stmt->Ist.WrTmp.data);
@@ -5350,6 +5442,7 @@
case Ity_F32:
case Ity_F64: hregLo = mkHReg(j++, HRcFlt64, True); break;
case Ity_V128: hregLo = mkHReg(j++, HRcVec128, True); break;
+ case Ity_D32:
case Ity_D64: hregLo = mkHReg(j++, HRcFlt64, True); break;
case Ity_D128: hregLo = mkHReg(j++, HRcFlt64, True);
hregMedLo = mkHReg(j++, HRcFlt64, True); break;
Modified: trunk/priv/guest_ppc_toIR.c (+16 -4)
===================================================================
--- trunk/priv/guest_ppc_toIR.c 2013-01-20 23:13:14 +00:00 (rev 2649)
+++ trunk/priv/guest_ppc_toIR.c 2013-01-21 18:12:31 +00:00 (rev 2650)
@@ -1128,6 +1128,12 @@
e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
return e;
}
+static IRExpr* getDReg32(UInt archreg) {
+ IRExpr *e;
+ vassert( archreg < 32 );
+ e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
+ return e;
+}
/* Read a floating point register pair and combine their contents into a
128-bit value */
@@ -1139,6 +1145,12 @@
}
/* Ditto, but write to a reg instead. */
+static void putDReg32(UInt archreg, IRExpr* e) {
+ vassert( archreg < 32 );
+ vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
+ stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
+}
+
static void putDReg(UInt archreg, IRExpr* e) {
vassert( archreg < 32 );
vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
@@ -9498,9 +9510,9 @@
DIP( "dctdp%s fr%u,fr%u\n",
flag_rC ? ".":"", frS_addr, frB_addr );
- frB = newTemp( Ity_D64 );
+ frB = newTemp( Ity_D32 );
frS = newTemp( Ity_D64 );
- assign( frB, getDReg( frB_addr ) );
+ assign( frB, getDReg32( frB_addr ) );
assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
putDReg( frS_addr, mkexpr( frS ) );
break;
@@ -9508,10 +9520,10 @@
DIP( "drsp%s fr%u,fr%u\n",
flag_rC ? ".":"", frS_addr, frB_addr );
frB = newTemp( Ity_D64 );
- frS = newTemp( Ity_D64 );
+ frS = newTemp( Ity_D32 );
assign( frB, getDReg( frB_addr ) );
assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
- putDReg( frS_addr, mkexpr( frS ) );
+ putDReg32( frS_addr, mkexpr( frS ) );
break;
case 0x122: // dctfix
DIP( "dctfix%s fr%u,fr%u\n",
|