valgrind/vg_bug270851_r2148.patch

212 lines
8.4 KiB
Diff

Index: VEX/priv/host_ppc_defs.c
===================================================================
--- VEX/priv/host_ppc_defs.c.orig
+++ VEX/priv/host_ppc_defs.c
@@ -962,17 +962,65 @@ PPCInstr* PPCInstr_FpRSP ( HReg dst, HRe
i->Pin.FpRSP.src = src;
return i;
}
+
+/*
+Valid combo | fromI | int32 | syned | flt64 |
+--------------------------------------------
+ | n n n n |
+--------------------------------------------
+ F64->I64U | n n n y |
+--------------------------------------------
+ | n n y n |
+--------------------------------------------
+ F64->I64S | n n y y |
+--------------------------------------------
+ | n y n n |
+--------------------------------------------
+ F64->I32U | n y n y |
+--------------------------------------------
+ | n y y n |
+--------------------------------------------
+ F64->I32S | n y y y |
+--------------------------------------------
+ I64U->F32 | y n n n |
+--------------------------------------------
+ I64U->F64 | y n n y |
+--------------------------------------------
+ | y n y n |
+--------------------------------------------
+ I64S->F64 | y n y y |
+--------------------------------------------
+ | y y n n |
+--------------------------------------------
+ | y y n y |
+--------------------------------------------
+ | y y y n |
+--------------------------------------------
+ | y y y y |
+--------------------------------------------
+*/
PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
- Bool dst64, HReg dst, HReg src ) {
+ Bool flt64, HReg dst, HReg src ) {
+ Bool tmp = fromI | int32 | syned | flt64;
+ vassert(tmp == True || tmp == False); // iow, no high bits set
+ UShort conversion = 0;
+ conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
+ switch (conversion) {
+ // Supported conversion operations
+ case 1: case 3: case 5: case 7:
+ case 8: case 9: case 11:
+ break;
+ default:
+ vpanic("PPCInstr_FpCftI(ppc_host)");
+ }
PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
i->tag = Pin_FpCftI;
i->Pin.FpCftI.fromI = fromI;
i->Pin.FpCftI.int32 = int32;
i->Pin.FpCftI.syned = syned;
- i->Pin.FpCftI.dst64 = dst64;
+ i->Pin.FpCftI.flt64 = flt64;
i->Pin.FpCftI.dst = dst;
i->Pin.FpCftI.src = src;
- vassert(!(int32 && fromI)); /* no such insn ("fcfiw"). */
return i;
}
PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
@@ -1445,7 +1493,7 @@ void ppPPCInstr ( PPCInstr* i, Bool mode
if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
if (i->Pin.FpCftI.syned == True)
str = "fcfid";
- else if (i->Pin.FpCftI.dst64 == True)
+ else if (i->Pin.FpCftI.flt64 == True)
str = "fcfidu";
else
str = "fcfidus";
@@ -3397,7 +3445,7 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf
// fcfid (conv i64 to f64), PPC64 p434
p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
goto done;
- } else if (i->Pin.FpCftI.dst64 == True) {
+ } else if (i->Pin.FpCftI.flt64 == True) {
// fcfidu (conv u64 to f64)
p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0);
goto done;
Index: VEX/priv/host_ppc_defs.h
===================================================================
--- VEX/priv/host_ppc_defs.h.orig
+++ VEX/priv/host_ppc_defs.h
@@ -461,7 +461,7 @@ typedef
Pin_FpLdSt, /* FP load/store */
Pin_FpSTFIW, /* stfiwx */
Pin_FpRSP, /* FP round IEEE754 double to IEEE754 single */
- Pin_FpCftI, /* fcfid/fctid/fctiw */
+ Pin_FpCftI, /* fcfid[u,s,us]/fctid[u]/fctiw[u] */
Pin_FpCMov, /* FP floating point conditional move */
Pin_FpLdFPSCR, /* mtfsf */
Pin_FpCmp, /* FP compare, generating value into int reg */
@@ -662,13 +662,15 @@ typedef
HReg src;
HReg dst;
} FpRSP;
- /* fcfid/fctid/fctiw. Note there's no fcfiw so fromI==True
- && int32==True is not allowed. */
+ /* fcfid[u,s,us]/fctid[u]/fctiw[u]. Only some combinations
+ of the various fields are allowed. This is asserted for
+ and documented in the code for the constructor,
+ PPCInstr_FpCftI, in host_ppc_defs.c. */
struct {
- Bool fromI; /* False==F->I, True==I->F */
- Bool int32; /* True== I is 32, False==I is 64 */
+ Bool fromI; /* True== I->F, False== F->I */
+ Bool int32; /* True== I is 32, False== I is 64 */
Bool syned;
- Bool dst64; /* True==dest is 64bit; False==dest is 32bit */
+ Bool flt64; /* True== F is 64, False== F is 32 */
HReg src;
HReg dst;
} FpCftI;
Index: VEX/priv/host_ppc_isel.c
===================================================================
--- VEX/priv/host_ppc_isel.c.orig
+++ VEX/priv/host_ppc_isel.c
@@ -1471,8 +1471,9 @@ static HReg iselWordExpr_R_wrk ( ISelEnv
set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
sub_from_sp( env, 16 );
- addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/, True,
- False, ftmp, fsrc));
+ addInstr(env, PPCInstr_FpCftI(False/*F->I*/, True/*int32*/,
+ True/*syned*/, True/*flt64*/,
+ ftmp, fsrc));
addInstr(env, PPCInstr_FpSTFIW(r1, ftmp));
addInstr(env, PPCInstr_Load(4, idst, zero_r1, mode64));
@@ -2959,6 +2960,8 @@ static HReg iselFltExpr ( ISelEnv* env,
/* DO NOT CALL THIS DIRECTLY */
static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
{
+ Bool mode64 = env->mode64;
+
IRType ty = typeOfIRExpr(env->type_env,e);
vassert(ty == Ity_F32);
@@ -3027,6 +3030,60 @@ static HReg iselFltExpr_wrk ( ISelEnv* e
return fdst;
}
+ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64UtoF32) {
+ if (mode64) {
+ HReg fdst = newVRegF(env);
+ HReg isrc = iselWordExpr_R(env, e->Iex.Binop.arg2);
+ HReg r1 = StackFramePtr(env->mode64);
+ PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
+
+ /* Set host rounding mode */
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+
+ sub_from_sp( env, 16 );
+
+ addInstr(env, PPCInstr_Store(8, zero_r1, isrc, True/*mode64*/));
+ addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
+ addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
+ False, False,
+ fdst, fdst));
+
+ add_to_sp( env, 16 );
+
+ ///* Restore default FPU rounding. */
+ //set_FPU_rounding_default( env );
+ return fdst;
+ } else {
+ /* 32-bit mode */
+ HReg fdst = newVRegF(env);
+ HReg isrcHi, isrcLo;
+ HReg r1 = StackFramePtr(env->mode64);
+ PPCAMode* zero_r1 = PPCAMode_IR( 0, r1 );
+ PPCAMode* four_r1 = PPCAMode_IR( 4, r1 );
+
+ iselInt64Expr(&isrcHi, &isrcLo, env, e->Iex.Binop.arg2);
+
+ /* Set host rounding mode */
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+
+ sub_from_sp( env, 16 );
+
+ addInstr(env, PPCInstr_Store(4, zero_r1, isrcHi, False/*mode32*/));
+ addInstr(env, PPCInstr_Store(4, four_r1, isrcLo, False/*mode32*/));
+ addInstr(env, PPCInstr_FpLdSt(True/*load*/, 8, fdst, zero_r1));
+ addInstr(env, PPCInstr_FpCftI(True/*I->F*/, False/*int64*/,
+ False, False,
+ fdst, fdst));
+
+ add_to_sp( env, 16 );
+
+ ///* Restore default FPU rounding. */
+ //set_FPU_rounding_default( env );
+ return fdst;
+ }
+
+ }
+
vex_printf("iselFltExpr(ppc): No such tag(%u)\n", e->tag);
ppIRExpr(e);
vpanic("iselFltExpr_wrk(ppc)");