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
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;
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: {
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);
}
} 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);
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;
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;
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);
}
}
}
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));
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++;
}
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++;
}
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
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;
}
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