From b62992e5d82210f8059b11bdd7cc30b8fae431bc Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Tue, 4 Sep 2012 13:45:42 +0000 Subject: [PATCH] Load/store doubles on MIPS are modeled through Ity_F64 rather than two Ity_F32. This patch changes how the load/store doublewords are modeled on MIPS. Previously, this was modeled through two Ity_F32s which caused test reports to be different to expected. This fixes memcheck/tests/fprw. git-svn-id: svn://svn.valgrind.org/vex/trunk@2511 --- VEX/priv/guest_mips_toIR.c | 28 ++-------------- VEX/priv/host_mips_defs.c | 67 +++++++------------------------------- VEX/priv/host_mips_isel.c | 50 +++++++++++++++++++++------- 3 files changed, 53 insertions(+), 92 deletions(-) diff --git a/VEX/priv/guest_mips_toIR.c b/VEX/priv/guest_mips_toIR.c index 3c72619cdf..2e60ed7c30 100644 --- a/VEX/priv/guest_mips_toIR.c +++ b/VEX/priv/guest_mips_toIR.c @@ -2173,36 +2173,14 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, case 0x35: /* Load Doubleword to Floating Point - LDC1 (MIPS32) */ LOAD_STORE_PATTERN; - - t2 = newTemp(Ity_I32); - assign(t2, binop(Iop_Add32, getIReg(rs), - mkU32(extend_s_16to32(imm + 4)))); - -#if defined (_MIPSEL) - putFReg(ft, load(Ity_F32, mkexpr(t1))); - putFReg(ft + 1, load(Ity_F32, mkexpr(t2))); -#elif defined (_MIPSEB) - putFReg(ft + 1, load(Ity_F32, mkexpr(t1))); - putFReg(ft, load(Ity_F32, mkexpr(t2))); -#endif + putDReg(ft, load(Ity_F64, mkexpr(t1))); DIP("ldc1 f%d, %d(%d) \n", rt, imm, rs); break; case 0x3D: /* Store Doubleword from Floating Point - SDC1 */ LOAD_STORE_PATTERN; - - t2 = newTemp(Ity_I32); - assign(t2, binop(Iop_Add32, getIReg(rs), - mkU32(extend_s_16to32(imm + 4)))); - -#if defined (_MIPSEL) - store(mkexpr(t1), getFReg(ft)); - store(mkexpr(t2), getFReg(ft + 1)); -#elif defined (_MIPSEB) - store(mkexpr(t1), getFReg(ft + 1)); - store(mkexpr(t2), getFReg(ft)); -#endif + store(mkexpr(t1), getDReg(ft)); DIP("sdc1 f%d, %d(%d)", ft, imm, rs); break; @@ -2310,7 +2288,7 @@ static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, store(mkexpr(t1), getFReg(fs)); #endif - DIP("sdc1 f%d, %d(%d)", ft, imm, rs); + DIP("sdxc1 f%d, %d(%d)", ft, imm, rs); break; } case 0x0F: { diff --git a/VEX/priv/host_mips_defs.c b/VEX/priv/host_mips_defs.c index f2a1e82934..86e8ee8f74 100644 --- a/VEX/priv/host_mips_defs.c +++ b/VEX/priv/host_mips_defs.c @@ -860,7 +860,7 @@ MIPSAMode *nextMIPSAModeFloat(MIPSAMode * am) MIPSAMode* ret; switch (am->tag) { case Mam_IR: - ret = MIPSAMode_IR(am->Mam.IR.index + 8, am->Mam.IR.base); + ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base); break; case Mam_RR: ret = MIPSAMode_RR(am->Mam.RR.index + 1, am->Mam.RR.base); @@ -1736,18 +1736,12 @@ void ppMIPSInstr(MIPSInstr * i, Bool mode64) } } else if (i->Min.FpLdSt.sz == 8) { if (i->Min.FpLdSt.isLoad) { - if (mode64) - vex_printf("ldc1 "); - else - vex_printf("lwc1 "); + vex_printf("ldc1 "); ppHRegMIPS(i->Min.FpLdSt.reg, mode64); vex_printf(","); ppMIPSAMode(i->Min.FpLdSt.addr, mode64); } else { - if (mode64) - vex_printf("sdc1 "); - else - vex_printf("swc1 "); + vex_printf("sdc1 "); ppHRegMIPS(i->Min.FpLdSt.reg, mode64); vex_printf(","); ppMIPSAMode(i->Min.FpLdSt.addr, mode64); @@ -1952,16 +1946,9 @@ void getRegUsage_MIPSInstr(HRegUsage * u, MIPSInstr * i, Bool mode64) addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); return; } else if (i->Min.FpLdSt.sz == 8) { - if (mode64) { - addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead), - i->Min.FpLdSt.reg); - addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); - } else { - addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead), - i->Min.FpLdSt.reg); - addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); - addRegUsage_MIPSAMode(u, nextMIPSAModeFloat(i->Min.FpLdSt.addr)); - } + addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead), + i->Min.FpLdSt.reg); + addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); return; } break; @@ -2107,14 +2094,8 @@ void mapRegs_MIPSInstr(HRegRemap * m, MIPSInstr * i, Bool mode64) mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); return; } else if (i->Min.FpLdSt.sz == 8) { - if (mode64) { - mapReg(m, &i->Min.FpLdSt.reg); - mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); - } else { - mapReg(m, &i->Min.FpLdSt.reg); - mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); - mapRegs_MIPSAMode(m, nextMIPSAModeFloat(i->Min.FpLdSt.addr)); - } + mapReg(m, &i->Min.FpLdSt.reg); + mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); return; } break; @@ -3515,39 +3496,15 @@ Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc, UInt f_reg = dregNo(i->Min.FpLdSt.reg); if (i->Min.FpLdSt.isLoad) { if (am_addr->tag == Mam_IR) { - if (mode64) { - p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64); - } else { - p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64); - p = doAMode_IR(p, 0x31, f_reg + 1, - nextMIPSAModeFloat(am_addr), mode64); - } + p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64); } else if (am_addr->tag == Mam_RR) { - if (mode64) { - p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64); - } else { - p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64); - p = doAMode_RR(p, 0x31, f_reg + 1, - nextMIPSAModeFloat(am_addr), mode64); - } + p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64); } } else { if (am_addr->tag == Mam_IR) { - if (mode64) { - p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64); - } else { - p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64); - p = doAMode_IR(p, 0x39, f_reg + 1, - nextMIPSAModeFloat(am_addr), mode64); - } + p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64); } else if (am_addr->tag == Mam_RR) { - if (mode64) { - p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64); - } else { - p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64); - p = doAMode_RR(p, 0x39, f_reg + 1, - nextMIPSAModeFloat(am_addr), mode64); - } + p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64); } } } diff --git a/VEX/priv/host_mips_isel.c b/VEX/priv/host_mips_isel.c index 347a682fdf..c0fa0280e3 100644 --- a/VEX/priv/host_mips_isel.c +++ b/VEX/priv/host_mips_isel.c @@ -344,7 +344,7 @@ static HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo) sub_from_sp(env, 16); // Move SP down 16 bytes am_addr0 = MIPSAMode_IR(0, StackPointer(mode64)); - am_addr1 = MIPSAMode_IR(8, StackPointer(mode64)); + am_addr1 = MIPSAMode_IR(4, StackPointer(mode64)); // store hi,lo as Ity_I32's addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64)); @@ -445,15 +445,21 @@ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard, vassert(argreg < MIPS_N_REGPARMS); vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 || typeOfIRExpr(env->type_env, args[i]) == Ity_I64); - if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) { + if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32 || mode64) { argiregs |= (1 << (argreg + 4)); addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env, args[i]))); } else { // Ity_I64 - vassert(mode64); + if (argreg & 1) { + argreg++; + argiregs |= (1 << (argreg + 4)); + } + HReg rHi, rLo; + iselInt64Expr(&rHi, &rLo, env, args[i]); argiregs |= (1 << (argreg + 4)); - addInstr(env, mk_iMOVds_RR(argregs[argreg], iselWordExpr_R(env, - args[i]))); + addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi )); + argiregs |= (1 << (argreg + 4)); + addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo)); } argreg++; } @@ -474,11 +480,18 @@ static void doHelperCall(ISelEnv * env, Bool passBBP, IRExpr * guard, vassert(argreg < MIPS_N_REGPARMS); vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32 || typeOfIRExpr(env->type_env, args[i]) == Ity_I64); - if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32) { + if (typeOfIRExpr(env->type_env, args[i]) == Ity_I32 || mode64) { tmpregs[argreg] = iselWordExpr_R(env, args[i]); } else { // Ity_I64 - vassert(mode64); - tmpregs[argreg] = iselWordExpr_R(env, args[i]); + if (argreg & 1) + argreg++; + if (argreg + 1 >= MIPS_N_REGPARMS) + vassert(0); /* out of argregs */ + HReg raHi, raLo; + iselInt64Expr(&raHi, &raLo, env, args[i]); + tmpregs[argreg] = raLo; + argreg++; + tmpregs[argreg] = raHi; } argreg++; } @@ -2249,10 +2262,10 @@ static HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e) sub_from_sp(env, 16); // Move SP down 16 bytes am_addr = MIPSAMode_IR(0, StackPointer(mode64)); - // store as I32 + // store as I64 addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64)); - // load as Ity_F32 + // load as Ity_F64 addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr)); add_to_sp(env, 16); // Reset SP @@ -2783,6 +2796,13 @@ static void iselStmt(ISelEnv * env, IRStmt * stmt) return; } + if (!mode64 && (tyd == Ity_F64)) { + HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data); + addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src, + am_addr)); + return; + } + break; } @@ -2893,8 +2913,14 @@ static void iselStmt(ISelEnv * env, IRStmt * stmt) retty = typeOfIRTemp(env->type_env, d->tmp); if (retty == Ity_I64 && !mode64) { - vex_printf - ("Dirty! Return 64 bits. Not implemented (yet!)\n"); + HReg rHi = newVRegI(env); + HReg rLo = newVRegI(env); + HReg dstHi, dstLo; + addInstr(env, mk_iMOVds_RR(rLo, hregMIPS_GPR2(mode64))); + addInstr(env, mk_iMOVds_RR(rHi, hregMIPS_GPR3(mode64))); + lookupIRTemp64(&dstHi, &dstLo, env, d->tmp); + addInstr(env, mk_iMOVds_RR(dstHi, rHi)); + addInstr(env, mk_iMOVds_RR(dstLo, rLo)); return; } if (retty == Ity_I8 || retty == Ity_I16 || retty == Ity_I32 -- 2.47.2