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); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1); 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); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1); xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1);
} }
@ -198,7 +198,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
xSHUF.PS(xmmT1, xmmT1, 0); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1); 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); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1); xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1);
} }

View File

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

View File

@ -80,7 +80,10 @@ mVUop(mVU_DIV) {
writeQreg(Fs, mVUinfo.writeQ); writeQreg(Fs, mVUinfo.writeQ);
if (mVU.cop2) if (mVU.cop2)
{
xAND(gprF0, ~0xc0000);
xOR(gprF0, ptr32[&mVU.divFlag]); xOR(gprF0, ptr32[&mVU.divFlag]);
}
mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
@ -103,7 +106,10 @@ mVUop(mVU_SQRT) {
writeQreg(Ft, mVUinfo.writeQ); writeQreg(Ft, mVUinfo.writeQ);
if (mVU.cop2) if (mVU.cop2)
{
xAND(gprF0, ~0xc0000);
xOR(gprF0, ptr32[&mVU.divFlag]); xOR(gprF0, ptr32[&mVU.divFlag]);
}
mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU.profiler.EmitOp(opSQRT); mVU.profiler.EmitOp(opSQRT);
@ -145,7 +151,10 @@ mVUop(mVU_RSQRT) {
writeQreg(Fs, mVUinfo.writeQ); writeQreg(Fs, mVUinfo.writeQ);
if (mVU.cop2) if (mVU.cop2)
{
xAND(gprF0, ~0xc0000);
xOR(gprF0, ptr32[&mVU.divFlag]); xOR(gprF0, ptr32[&mVU.divFlag]);
}
mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft); 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].sFlag.lastWrite = 0;
microVU0.prog.IRinfo.info[0].mFlag.doFlag = true; microVU0.prog.IRinfo.info[0].mFlag.doFlag = true;
microVU0.prog.IRinfo.info[0].mFlag.write = 0xff; microVU0.prog.IRinfo.info[0].mFlag.write = 0xff;
//Denormalize
xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); 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); xMOVSS(ptr32[&vu0Regs.VI[REG_Q].UL], xmmPQ);
} }
if (mode & 0x10) { // Status/Mac Flags were Updated 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(); microVU0.regAlloc->flushAll();
if (mode & 0x10) { // Update VU0 Status/Mac instances after flush to avoid corrupting anything 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); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&microVU0.regs().micro_statusflags], xmmT1); xMOVAPS(ptr128[&microVU0.regs().micro_statusflags], xmmT1);
@ -295,8 +300,7 @@ static void recCFC2() {
iFlushCall(FLUSH_EVERYTHING); iFlushCall(FLUSH_EVERYTHING);
if (_Rd_ == REG_STATUS_FLAG) { // Normalize Status Flag if (_Rd_ == REG_STATUS_FLAG) { // Normalize Status Flag
xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); xMOV(eax, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]);
mVUallocSFLAGc(eax, gprF0, 0);
} }
else xMOV(eax, ptr32[&vu0Regs.VI[_Rd_].UL]); else xMOV(eax, ptr32[&vu0Regs.VI[_Rd_].UL]);
@ -375,21 +379,20 @@ static void recCTC2() {
break; break;
case REG_STATUS_FLAG: case REG_STATUS_FLAG:
{ {
if (_Rt_) { // Denormalizes flag into eax (gprT1) if (_Rt_) {
mVUallocSFLAGd(&cpuRegs.GPR.r[_Rt_].UL[0]); xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]);
xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], eax); 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); else xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F);
__aligned16 static const u32 sticky_flags[4] = { 0xFC0,0xFC0,0xFC0,0xFC0 };
__aligned16 static const u32 status_flags[4] = { 0x3F,0x3F,0x3F,0x3F };
//Need to update the sticky flags for microVU //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); xSHUF.PS(xmmT1, xmmT1, 0);
xAND.PS(xmmT1, ptr128[&sticky_flags]); // Make sure the values are everywhere the need to be
xMOVAPS(xmmT2, ptr128[&vu0Regs.micro_statusflags]);
xAND.PS(xmmT1, ptr128[&status_flags]);
xOR.PS(xmmT1, xmmT2);
xMOVAPS(ptr128[&vu0Regs.micro_statusflags], xmmT1); xMOVAPS(ptr128[&vu0Regs.micro_statusflags], xmmT1);
break; break;
} }