From 7c373cf291f19307cbe8f6b935ec3e6cf5c60339 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sun, 21 Apr 2024 08:24:40 +0100 Subject: [PATCH] VU: Expand IBit hack to work for immediates on several instructions --- pcsx2/x86/microVU_Analyze.inl | 2 +- pcsx2/x86/microVU_Compile.inl | 17 +++- pcsx2/x86/microVU_Lower.inl | 152 ++++++++++++++++++++++++++++------ 3 files changed, 145 insertions(+), 26 deletions(-) diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index 27b57457d2..64f866f66d 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -228,7 +228,7 @@ __fi void mVUanalyzeIALU2(mV, int Is, int It) __fi void mVUanalyzeIADDI(mV, int Is, int It, s16 imm) { mVUanalyzeIALU2(mVU, Is, It); - if (!Is) + if (!Is && !EmuConfig.Gamefixes.IbitHack) { setConstReg(It, imm); } diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index a345fe5ad4..ca418d27cd 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -744,12 +744,27 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) { mVUsetupRange(mVU, xPC, false); if (branch < 2) - mVUsetupRange(mVU, xPC + 8, true); // Ideally we'd do +4 but the mmx compare only works in 64bits, this should be fine + mVUsetupRange(mVU, xPC + 4, true); } } else { incPC(-1); + if (EmuConfig.Gamefixes.IbitHack) + { + // Ignore IADDI, IADDIU and ISUBU, ILW, ISW, LQ, SQ. + // Be warned, this is a little risky as we could be ignoring subtle differences in the operations. + // 2 is too much, 1 is too little, so it gets 2. It's a hack anyways... + const u32 upper = (mVU.code >> 25); + if (upper == 0x1 || upper == 0x0 || upper == 0x4 || upper == 0x5 || upper == 0x8 || upper == 0x9 || (upper == 0x40 && (mVU.code & 0x3F) == 0x32)) + { + incPC(1); + mVUsetupRange(mVU, xPC, false); + if (branch < 2) + mVUsetupRange(mVU, xPC + 2, true); + incPC(-1); + } + } mVUopL(mVU, 0); incPC(1); } diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index da4405e0a0..4eee43a132 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -858,17 +858,37 @@ mVUop(mVU_IADDI) if (_Is_ == 0) { const xRegister32& regT = mVU.regAlloc->allocGPR(-1, _It_, mVUlow.backupVI); - if (_Imm5_ != 0) - xMOV(regT, _Imm5_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm5_ != 0) + xMOV(regT, _Imm5_); + else + xXOR(regT, regT); + } else - xXOR(regT, regT); + { + xMOV(regT, ptr32[&curI]); + xSHL(regT, 21); + xSAR(regT, 27); + } mVU.regAlloc->clearNeeded(regT); } else { const xRegister32& regS = mVU.regAlloc->allocGPR(_Is_, _It_, mVUlow.backupVI); - if (_Imm5_ != 0) - xADD(regS, _Imm5_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm5_ != 0) + xADD(regS, _Imm5_); + } + else + { + xMOV(gprT1, ptr32[&curI]); + xSHL(gprT1, 21); + xSAR(gprT1, 27); + + xADD(regS, gprT1); + } mVU.regAlloc->clearNeeded(regS); } mVU.profiler.EmitOp(opIADDI); @@ -884,17 +904,43 @@ mVUop(mVU_IADDIU) if (_Is_ == 0) { const xRegister32& regT = mVU.regAlloc->allocGPR(-1, _It_, mVUlow.backupVI); - if (_Imm15_ != 0) - xMOV(regT, _Imm15_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm15_ != 0) + xMOV(regT, _Imm15_); + else + xXOR(regT, regT); + } else - xXOR(regT, regT); + { + xMOV(regT, ptr32[&curI]); + xMOV(gprT1, regT); + xSHR(gprT1, 10); + xAND(gprT1, 0x7800); + xAND(regT, 0x7FF); + xOR(regT, gprT1); + } mVU.regAlloc->clearNeeded(regT); } else { const xRegister32& regS = mVU.regAlloc->allocGPR(_Is_, _It_, mVUlow.backupVI); - if (_Imm15_ != 0) - xADD(regS, _Imm15_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm15_ != 0) + xADD(regS, _Imm15_); + } + else + { + xMOV(gprT1, ptr32[&curI]); + xMOV(gprT2, gprT1); + xSHR(gprT2, 10); + xAND(gprT2, 0x7800); + xAND(gprT1, 0x7FF); + xOR(gprT1, gprT2); + + xADD(regS, gprT1); + } mVU.regAlloc->clearNeeded(regS); } mVU.profiler.EmitOp(opIADDIU); @@ -964,8 +1010,22 @@ mVUop(mVU_ISUBIU) pass2 { const xRegister32& regS = mVU.regAlloc->allocGPR(_Is_, _It_, mVUlow.backupVI); - if (_Imm15_ != 0) - xSUB(regS, _Imm15_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm15_ != 0) + xSUB(regS, _Imm15_); + } + else + { + xMOV(gprT1, ptr32[&curI]); + xMOV(gprT2, gprT1); + xSHR(gprT2, 10); + xAND(gprT2, 0x7800); + xAND(gprT1, 0x7FF); + xOR(gprT1, gprT2); + + xSUB(regS, gprT1); + } mVU.regAlloc->clearNeeded(regS); mVU.profiler.EmitOp(opISUBIU); } @@ -1100,12 +1160,23 @@ mVUop(mVU_ILW) pass2 { void* ptr = mVU.regs().Mem + offsetSS; - std::optional optaddr(mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, offsetSS)); + std::optional optaddr(EmuConfig.Gamefixes.IbitHack ? std::nullopt : mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, offsetSS)); if (!optaddr.has_value()) { mVU.regAlloc->moveVIToGPR(gprT1, _Is_); - if (_Imm11_ != 0) - xADD(gprT1, _Imm11_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm11_ != 0) + xADD(gprT1, _Imm11_); + } + else + { + xMOV(gprT2, ptr32[&curI]); + xSHL(gprT2, 21); + xSAR(gprT2, 21); + + xADD(gprT1, gprT2); + } mVUaddrFix(mVU, gprT1q); } @@ -1164,12 +1235,23 @@ mVUop(mVU_ISW) } pass2 { - std::optional optaddr(mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, 0)); + std::optional optaddr(EmuConfig.Gamefixes.IbitHack ? std::nullopt : mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, 0)); if (!optaddr.has_value()) { mVU.regAlloc->moveVIToGPR(gprT1, _Is_); - if (_Imm11_ != 0) - xADD(gprT1, _Imm11_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm11_ != 0) + xADD(gprT1, _Imm11_); + } + else + { + xMOV(gprT2, ptr32[&curI]); + xSHL(gprT2, 21); + xSAR(gprT2, 21); + + xADD(gprT1, gprT2); + } mVUaddrFix(mVU, gprT1q); } @@ -1251,12 +1333,23 @@ mVUop(mVU_LQ) pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, false); } pass2 { - const std::optional optaddr(mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, 0)); + const std::optional optaddr(EmuConfig.Gamefixes.IbitHack ? std::nullopt : mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, 0)); if (!optaddr.has_value()) { mVU.regAlloc->moveVIToGPR(gprT1, _Is_); - if (_Imm11_ != 0) - xADD(gprT1, _Imm11_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm11_ != 0) + xADD(gprT1, _Imm11_); + } + else + { + xMOV(gprT2, ptr32[&curI]); + xSHL(gprT2, 21); + xSAR(gprT2, 21); + + xADD(gprT1, gprT2); + } mVUaddrFix(mVU, gprT1q); } @@ -1345,12 +1438,23 @@ mVUop(mVU_SQ) pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, false); } pass2 { - const std::optional optptr(mVUoptimizeConstantAddr(mVU, _It_, _Imm11_, 0)); + const std::optional optptr(EmuConfig.Gamefixes.IbitHack ? std::nullopt : mVUoptimizeConstantAddr(mVU, _It_, _Imm11_, 0)); if (!optptr.has_value()) { mVU.regAlloc->moveVIToGPR(gprT1, _It_); - if (_Imm11_ != 0) - xADD(gprT1, _Imm11_); + if (!EmuConfig.Gamefixes.IbitHack) + { + if (_Imm11_ != 0) + xADD(gprT1, _Imm11_); + } + else + { + xMOV(gprT2, ptr32[&curI]); + xSHL(gprT2, 21); + xSAR(gprT2, 21); + + xADD(gprT1, gprT2); + } mVUaddrFix(mVU, gprT1q); }