Skip to content

Commit

Permalink
VU: Expand IBit hack to work for immediates on several instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Apr 21, 2024
1 parent 7e1900a commit 3e07dd5
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 30 deletions.
2 changes: 1 addition & 1 deletion pcsx2/x86/microVU_Analyze.inl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
17 changes: 16 additions & 1 deletion pcsx2/x86/microVU_Compile.inl
Original file line number Diff line number Diff line change
Expand Up @@ -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 wared, 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);
}
Expand Down
189 changes: 161 additions & 28 deletions pcsx2/x86/microVU_Lower.inl
Original file line number Diff line number Diff line change
Expand Up @@ -858,17 +858,50 @@ 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(gprT1, ptr32[&curI]);
xSHR(gprT1, 6);
xAND(gprT1, 0x1F);
xTEST(gprT1, 0x10);

xForwardJZ32 skipExtend;
xOR(gprT1, 0xFFF0);
skipExtend.SetTarget();

xMOVSX(regT, xRegister16(gprT1));
}
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]);
xSHR(gprT1, 6);
xAND(gprT1, 0x1F);
xTEST(gprT1, 0x10);

xForwardJZ32 skipExtend;
xOR(gprT1, 0xFFF0);
xMOVSX(gprT1, xRegister16(gprT1));
skipExtend.SetTarget();

xADD(regS, gprT1);
}
mVU.regAlloc->clearNeeded(regS);
}
mVU.profiler.EmitOp(opIADDI);
Expand All @@ -884,17 +917,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);
Expand Down Expand Up @@ -964,8 +1023,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);
}
Expand Down Expand Up @@ -1101,16 +1174,31 @@ mVUop(mVU_ILW)
{
void* ptr = mVU.regs().Mem + offsetSS;
std::optional<xAddressVoid> optaddr(mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, offsetSS));
if (!optaddr.has_value())
if (EmuConfig.Gamefixes.IbitHack || !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]);
xAND(gprT2, 0x7FF);
xTEST(gprT2, 0x400);

xForwardJZ32 skipExtend;
xOR(gprT2, 0xFFFFF800);
skipExtend.SetTarget();

xADD(gprT1, gprT2);
}
mVUaddrFix(mVU, gprT1q);
}

const xRegister32& regT = mVU.regAlloc->allocGPR(-1, _It_, mVUlow.backupVI);
xMOVZX(regT, ptr16[optaddr.has_value() ? optaddr.value() : xComplexAddress(gprT2q, ptr, gprT1q)]);
xMOVZX(regT, ptr16[(optaddr.has_value() && !EmuConfig.Gamefixes.IbitHack) ? optaddr.value() : xComplexAddress(gprT2q, ptr, gprT1q)]);
mVU.regAlloc->clearNeeded(regT);
mVU.profiler.EmitOp(opILW);
}
Expand Down Expand Up @@ -1165,17 +1253,32 @@ mVUop(mVU_ISW)
pass2
{
std::optional<xAddressVoid> optaddr(mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, 0));
if (!optaddr.has_value())
if (EmuConfig.Gamefixes.IbitHack || !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]);
xAND(gprT2, 0x7FF);
xTEST(gprT2, 0x400);

xForwardJZ32 skipExtend;
xOR(gprT2, 0xFFFFF800);
skipExtend.SetTarget();

xADD(gprT1, gprT2);
}
mVUaddrFix(mVU, gprT1q);
}

// If regT is dirty, the high bits might not be zero.
const xRegister32& regT = mVU.regAlloc->allocGPR(_It_, -1, false, true);
const xAddressVoid ptr(optaddr.has_value() ? optaddr.value() : xComplexAddress(gprT2q, mVU.regs().Mem, gprT1q));
const xAddressVoid ptr((optaddr.has_value() && !EmuConfig.Gamefixes.IbitHack) ? optaddr.value() : xComplexAddress(gprT2q, mVU.regs().Mem, gprT1q));
if (_X) xMOV(ptr32[ptr], regT);
if (_Y) xMOV(ptr32[ptr + 4], regT);
if (_Z) xMOV(ptr32[ptr + 8], regT);
Expand Down Expand Up @@ -1252,16 +1355,31 @@ mVUop(mVU_LQ)
pass2
{
const std::optional<xAddressVoid> optaddr(mVUoptimizeConstantAddr(mVU, _Is_, _Imm11_, 0));
if (!optaddr.has_value())
if (EmuConfig.Gamefixes.IbitHack || !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]);
xAND(gprT2, 0x7FF);
xTEST(gprT2, 0x400);

xForwardJZ32 skipExtend;
xOR(gprT2, 0xFFFFF800);
skipExtend.SetTarget();

xADD(gprT1, gprT2);
}
mVUaddrFix(mVU, gprT1q);
}

const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
mVUloadReg(Ft, optaddr.has_value() ? optaddr.value() : xComplexAddress(gprT2q, mVU.regs().Mem, gprT1q), _X_Y_Z_W);
mVUloadReg(Ft, (optaddr.has_value() && !EmuConfig.Gamefixes.IbitHack) ? optaddr.value() : xComplexAddress(gprT2q, mVU.regs().Mem, gprT1q), _X_Y_Z_W);
mVU.regAlloc->clearNeeded(Ft);
mVU.profiler.EmitOp(opLQ);
}
Expand Down Expand Up @@ -1346,16 +1464,31 @@ mVUop(mVU_SQ)
pass2
{
const std::optional<xAddressVoid> optptr(mVUoptimizeConstantAddr(mVU, _It_, _Imm11_, 0));
if (!optptr.has_value())
if (EmuConfig.Gamefixes.IbitHack || !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]);
xAND(gprT2, 0x7FF);
xTEST(gprT2, 0x400);

xForwardJZ32 skipExtend;
xOR(gprT2, 0xFFFFF800);
skipExtend.SetTarget();

xADD(gprT1, gprT2);
}
mVUaddrFix(mVU, gprT1q);
}

const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _XYZW_PS ? -1 : 0, _X_Y_Z_W);
mVUsaveReg(Fs, optptr.has_value() ? optptr.value() : xComplexAddress(gprT2q, mVU.regs().Mem, gprT1q), _X_Y_Z_W, 1);
mVUsaveReg(Fs, (optptr.has_value() && !EmuConfig.Gamefixes.IbitHack) ? optptr.value() : xComplexAddress(gprT2q, mVU.regs().Mem, gprT1q), _X_Y_Z_W, 1);
mVU.regAlloc->clearNeeded(Fs);
mVU.profiler.EmitOp(opSQ);
}
Expand Down

0 comments on commit 3e07dd5

Please sign in to comment.