From: Carl Love Date: Mon, 21 Jan 2013 18:12:31 +0000 (+0000) Subject: The 32-bit DFP value is stored in a 64-bit register in X-Git-Tag: svn/VALGRIND_3_9_0^2~144 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72c66826b167591588add1f804d74e1e5beae75b;p=thirdparty%2Fvalgrind.git 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. git-svn-id: svn://svn.valgrind.org/vex/trunk@2650 --- diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c index 165aaafcbc..cab2a43788 100644 --- a/VEX/priv/guest_ppc_toIR.c +++ b/VEX/priv/guest_ppc_toIR.c @@ -1128,6 +1128,12 @@ static IRExpr* getDReg(UInt archreg) { 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 @@ static IRExpr *getDReg_pair(UInt archreg) { } /* 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 @@ static Bool dis_dfp_fmt_conv(UInt theInstr) { 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 @@ static Bool dis_dfp_fmt_conv(UInt theInstr) { 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", diff --git a/VEX/priv/host_ppc_isel.c b/VEX/priv/host_ppc_isel.c index 6a281bb3dc..50dd9b8639 100644 --- a/VEX/priv/host_ppc_isel.c +++ b/VEX/priv/host_ppc_isel.c @@ -453,6 +453,8 @@ static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ); 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 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) 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 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) 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 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) 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 @@ static HReg iselDfp64Expr_wrk(ISelEnv* env, IRExpr* e) 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 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) 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 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) 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 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) 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 @@ HInstrArray* iselSB_PPC ( IRSB* bb, 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;