microVU: Sort out when the Status flag is de/normalized

Properly clear non-stick invalid/zero flags on DIV/SQRT/RSQRT COP2 instructions
This commit is contained in:
refractionpcsx2 2020-10-26 16:50:48 +00:00
parent 4b0dc9c0df
commit 9ebcb3b141
4 changed files with 39 additions and 28 deletions

View File

@ -97,7 +97,7 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) {
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1);
xMOVDZX(xmmT1, ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL]);
xMOVDZX(xmmT1, getFlagReg(fStatus));
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1);
}
@ -198,7 +198,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1);
xMOVDZX(xmmT1, ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL]);
xMOVDZX(xmmT1, getFlagReg(fStatus));
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1);
}

View File

@ -95,11 +95,10 @@ void mVUdispatcherCD(mV) {
xLDMXCSR(g_sseVUMXCSR);
mVUrestoreRegs(mVU);
xMOV(gprF0, ptr32[&mVU.statFlag[0]]);
xMOV(gprF1, ptr32[&mVU.statFlag[1]]);
xMOV(gprF2, ptr32[&mVU.statFlag[2]]);
xMOV(gprF3, ptr32[&mVU.statFlag[3]]);
xMOV(gprF0, ptr32[&mVU.regs().micro_statusflags[0]]);
xMOV(gprF1, ptr32[&mVU.regs().micro_statusflags[1]]);
xMOV(gprF2, ptr32[&mVU.regs().micro_statusflags[2]]);
xMOV(gprF3, ptr32[&mVU.regs().micro_statusflags[3]]);
// Jump to Recompiled Code Block
xJMP(ptrNative[&mVU.resumePtrXG]);
@ -110,10 +109,10 @@ void mVUdispatcherCD(mV) {
//xMOV(ptr32[&mVU.resumePtrXG], gprT1);
// Backup Status Flag (other regs were backed up on xgkick)
xMOV(ptr32[&mVU.statFlag[0]], gprF0);
xMOV(ptr32[&mVU.statFlag[1]], gprF1);
xMOV(ptr32[&mVU.statFlag[2]], gprF2);
xMOV(ptr32[&mVU.statFlag[3]], gprF3);
xMOV(ptr32[&mVU.regs().micro_statusflags[0]], gprF0);
xMOV(ptr32[&mVU.regs().micro_statusflags[1]], gprF1);
xMOV(ptr32[&mVU.regs().micro_statusflags[2]], gprF2);
xMOV(ptr32[&mVU.regs().micro_statusflags[3]], gprF3);
// Load EE's MXCSR state
xLDMXCSR(g_sseMXCSR);

View File

@ -80,7 +80,10 @@ mVUop(mVU_DIV) {
writeQreg(Fs, mVUinfo.writeQ);
if (mVU.cop2)
{
xAND(gprF0, ~0xc0000);
xOR(gprF0, ptr32[&mVU.divFlag]);
}
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
@ -103,7 +106,10 @@ mVUop(mVU_SQRT) {
writeQreg(Ft, mVUinfo.writeQ);
if (mVU.cop2)
{
xAND(gprF0, ~0xc0000);
xOR(gprF0, ptr32[&mVU.divFlag]);
}
mVU.regAlloc->clearNeeded(Ft);
mVU.profiler.EmitOp(opSQRT);
@ -145,7 +151,10 @@ mVUop(mVU_RSQRT) {
writeQreg(Fs, mVUinfo.writeQ);
if (mVU.cop2)
{
xAND(gprF0, ~0xc0000);
xOR(gprF0, ptr32[&mVU.divFlag]);
}
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);

View File

@ -51,8 +51,10 @@ void setupMacroOp(int mode, const char* opName) {
microVU0.prog.IRinfo.info[0].sFlag.lastWrite = 0;
microVU0.prog.IRinfo.info[0].mFlag.doFlag = true;
microVU0.prog.IRinfo.info[0].mFlag.write = 0xff;
xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]);
//Denormalize
mVUallocSFLAGd(&vu0Regs.VI[REG_STATUS_FLAG].UL);
xMOV(gprF0, eax);
}
}
@ -61,12 +63,15 @@ void endMacroOp(int mode) {
xMOVSS(ptr32[&vu0Regs.VI[REG_Q].UL], xmmPQ);
}
if (mode & 0x10) { // Status/Mac Flags were Updated
xMOV(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], gprF0);
// Normalize
mVUallocSFLAGc(eax, gprF0, 0);
xMOV(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], eax);
}
microVU0.regAlloc->flushAll();
if (mode & 0x10) { // Update VU0 Status/Mac instances after flush to avoid corrupting anything
xMOVDZX(xmmT1, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]);
mVUallocSFLAGd(&vu0Regs.VI[REG_STATUS_FLAG].UL);
xMOVDZX(xmmT1, eax);
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&microVU0.regs().micro_statusflags], xmmT1);
@ -295,8 +300,7 @@ static void recCFC2() {
iFlushCall(FLUSH_EVERYTHING);
if (_Rd_ == REG_STATUS_FLAG) { // Normalize Status Flag
xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]);
mVUallocSFLAGc(eax, gprF0, 0);
xMOV(eax, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]);
}
else xMOV(eax, ptr32[&vu0Regs.VI[_Rd_].UL]);
@ -375,21 +379,20 @@ static void recCTC2() {
break;
case REG_STATUS_FLAG:
{
if (_Rt_) { // Denormalizes flag into eax (gprT1)
mVUallocSFLAGd(&cpuRegs.GPR.r[_Rt_].UL[0]);
xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], eax);
if (_Rt_) {
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]);
xAND(eax, 0xFC0);
xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F);
xOR(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], eax);
}
else xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], 0);
__aligned16 static const u32 sticky_flags[4] = { 0xFC0,0xFC0,0xFC0,0xFC0 };
__aligned16 static const u32 status_flags[4] = { 0x3F,0x3F,0x3F,0x3F };
else xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F);
//Need to update the sticky flags for microVU
xMOVDZX(xmmT1, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]);
mVUallocSFLAGd(&vu0Regs.VI[REG_STATUS_FLAG].UL);
xMOVDZX(xmmT1, eax);
xSHUF.PS(xmmT1, xmmT1, 0);
xAND.PS(xmmT1, ptr128[&sticky_flags]);
xMOVAPS(xmmT2, ptr128[&vu0Regs.micro_statusflags]);
xAND.PS(xmmT1, ptr128[&status_flags]);
xOR.PS(xmmT1, xmmT2);
// Make sure the values are everywhere the need to be
xMOVAPS(ptr128[&vu0Regs.micro_statusflags], xmmT1);
break;
}