mirror of https://github.com/PCSX2/pcsx2.git
MTVU: Try to make T-Bit more reliable.
Add MTVUSpeedHack option to GameDB so it can be forcefully disabled
This commit is contained in:
parent
05a7a61257
commit
fd4a5acc40
|
@ -58,6 +58,7 @@ enum SpeedhackId
|
|||
|
||||
Speedhack_mvuFlag = SpeedhackId_FIRST,
|
||||
Speedhack_InstantVU1,
|
||||
Speedhack_MTVU,
|
||||
|
||||
SpeedhackId_COUNT
|
||||
};
|
||||
|
|
|
@ -146,7 +146,7 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
s32 addr = Read();
|
||||
vifRegs.top = Read();
|
||||
vifRegs.itop = Read();
|
||||
|
||||
vuFBRST = Read();
|
||||
if (addr != -1)
|
||||
vuRegs.VI[REG_TPC].UL = addr & 0x7FF;
|
||||
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3);
|
||||
|
@ -406,13 +406,13 @@ void VU_Thread::Get_MTVUChanges()
|
|||
{
|
||||
mtvuInterrupts.fetch_and(~InterruptFlagVUEBit, std::memory_order_relaxed);
|
||||
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0x0100;
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||
//DevCon.Warning("E-Bit registered %x", VU0.VI[REG_VPU_STAT].UL);
|
||||
}
|
||||
if (interrupts & InterruptFlagVUTBit)
|
||||
{
|
||||
mtvuInterrupts.fetch_and(~InterruptFlagVUTBit, std::memory_order_relaxed);
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0x0100;
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||
VU0.VI[REG_VPU_STAT].UL |= 0x0400;
|
||||
//DevCon.Warning("T-Bit registered %x", VU0.VI[REG_VPU_STAT].UL);
|
||||
hwIntcIrq(7);
|
||||
|
@ -445,15 +445,16 @@ void VU_Thread::WaitVU()
|
|||
}
|
||||
}
|
||||
|
||||
void VU_Thread::ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop)
|
||||
void VU_Thread::ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop, u32 fbrst)
|
||||
{
|
||||
MTVU_LOG("MTVU - ExecuteVU!");
|
||||
Get_MTVUChanges(); // Clear any pending interrupts
|
||||
ReserveSpace(4);
|
||||
ReserveSpace(5);
|
||||
Write(MTVU_VU_EXECUTE);
|
||||
Write(vu_addr);
|
||||
Write(vif_top);
|
||||
Write(vif_itop);
|
||||
Write(fbrst);
|
||||
CommitWritePos();
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_MTVU, NULL, 0);
|
||||
KickStart();
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
Semaphore semaXGkick;
|
||||
std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
|
||||
u32 vuCycleIdx; // Used for VU cycle stealing hack
|
||||
u32 vuFBRST;
|
||||
|
||||
enum InterruptFlag {
|
||||
InterruptFlagFinish = 1 << 0,
|
||||
|
@ -76,7 +77,7 @@ public:
|
|||
|
||||
void Get_MTVUChanges();
|
||||
|
||||
void ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop);
|
||||
void ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop, u32 fbrst);
|
||||
|
||||
void VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size);
|
||||
|
||||
|
|
|
@ -65,9 +65,11 @@ void TraceLogFilters::LoadSave(SettingsWrapper& wrap)
|
|||
}
|
||||
|
||||
const char* const tbl_SpeedhackNames[] =
|
||||
{
|
||||
"mvuFlag",
|
||||
"InstantVU1"};
|
||||
{
|
||||
"mvuFlag",
|
||||
"InstantVU1",
|
||||
"MTVU"
|
||||
};
|
||||
|
||||
const char* EnumToString(SpeedhackId id)
|
||||
{
|
||||
|
@ -85,6 +87,9 @@ void Pcsx2Config::SpeedhackOptions::Set(SpeedhackId id, bool enabled)
|
|||
case Speedhack_InstantVU1:
|
||||
vu1Instant = enabled;
|
||||
break;
|
||||
case Speedhack_MTVU:
|
||||
vuThread = enabled;
|
||||
break;
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,12 @@ static void TestClearVUs(u32 madr, u32 qwc, bool isWrite)
|
|||
//Catch up VU1 too
|
||||
CpuVU1->ExecuteBlock(0);
|
||||
}
|
||||
if ((madr >= 0x11008000) && (VU0.VI[REG_VPU_STAT].UL & 0x100) && !THREAD_VU1)
|
||||
if ((madr >= 0x11008000) && (VU0.VI[REG_VPU_STAT].UL & 0x100) && (!THREAD_VU1 || !isWrite))
|
||||
{
|
||||
CpuVU1->Execute(vu1RunCycles);
|
||||
if (THREAD_VU1)
|
||||
vu1Thread.WaitVU();
|
||||
else
|
||||
CpuVU1->Execute(vu1RunCycles);
|
||||
cpuRegs.cycle = VU1.cycle;
|
||||
//Catch up VU0 too
|
||||
CpuVU0->ExecuteBlock(0);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "R5900OpcodeTables.h"
|
||||
#include "VUmicro.h"
|
||||
#include "Vif_Dma.h"
|
||||
#include "MTVU.h"
|
||||
|
||||
#define _Ft_ _Rt_
|
||||
#define _Fs_ _Rd_
|
||||
|
|
|
@ -61,15 +61,16 @@ void __fastcall vu1ExecMicro(u32 addr)
|
|||
{
|
||||
if (THREAD_VU1) {
|
||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||
|
||||
// Okay this is a little bit of a hack, but with good reason.
|
||||
// Most of the time with MTVU we want to pretend the VU has finished quickly as to gain the benefit from running another thread
|
||||
// however with T-Bit games when the T-Bit is enabled, it needs to wait in case a T-Bit happens, so we need to set "Busy"
|
||||
// We shouldn't do this all the time as it negates the extra thread and causes games like Ratchet & Clank to be no faster.
|
||||
if(VU0.VI[REG_FBRST].UL & 0x800)
|
||||
if (VU0.VI[REG_FBRST].UL & 0x800)
|
||||
{
|
||||
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
||||
}
|
||||
|
||||
vu1Thread.ExecuteVU(addr, vif1Regs.top, vif1Regs.itop);
|
||||
vu1Thread.ExecuteVU(addr, vif1Regs.top, vif1Regs.itop, VU0.VI[REG_FBRST].UL);
|
||||
return;
|
||||
}
|
||||
static int count = 0;
|
||||
|
|
|
@ -305,6 +305,7 @@ _vifT __fi u32 vifRead32(u32 mem)
|
|||
{
|
||||
vifStruct& vif = MTVU_VifX;
|
||||
bool wait = idx && THREAD_VU1;
|
||||
|
||||
switch (mem)
|
||||
{
|
||||
case caseVif(ROW0):
|
||||
|
@ -380,44 +381,36 @@ _vifT __fi bool vifWrite32(u32 mem, u32 value)
|
|||
|
||||
case caseVif(ROW0):
|
||||
vif.MaskRow._u32[0] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
case caseVif(ROW1):
|
||||
vif.MaskRow._u32[1] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
case caseVif(ROW2):
|
||||
vif.MaskRow._u32[2] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
case caseVif(ROW3):
|
||||
vif.MaskRow._u32[3] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteRow(vif);
|
||||
vu1Thread.WriteRow(vif);
|
||||
return false;
|
||||
|
||||
case caseVif(COL0):
|
||||
vif.MaskCol._u32[0] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
case caseVif(COL1):
|
||||
vif.MaskCol._u32[1] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
case caseVif(COL2):
|
||||
vif.MaskCol._u32[2] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
case caseVif(COL3):
|
||||
vif.MaskCol._u32[3] = value;
|
||||
if (idx && THREAD_VU1)
|
||||
vu1Thread.WriteCol(vif);
|
||||
vu1Thread.WriteCol(vif);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -173,9 +173,6 @@ __fi void vif1SetupTransfer()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (vif1ch.chcr.TTE)
|
||||
{
|
||||
// Transfer dma tag if tte is set
|
||||
|
@ -203,7 +200,7 @@ __fi void vif1SetupTransfer()
|
|||
ret = VIF1transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
|
||||
//ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
|
||||
}
|
||||
|
||||
|
||||
if (!ret && vif1.irqoffset.enabled)
|
||||
{
|
||||
vif1.inprogress &= ~1; // Better clear this so it has to do it again (Jak 1)
|
||||
|
@ -233,8 +230,7 @@ __fi void vif1VUFinish()
|
|||
{
|
||||
if (VU0.VI[REG_VPU_STAT].UL & 0x500)
|
||||
{
|
||||
if(THREAD_VU1)
|
||||
vu1Thread.Get_MTVUChanges();
|
||||
vu1Thread.Get_MTVUChanges();
|
||||
|
||||
CPU_INT(VIF_VU1_FINISH, 128);
|
||||
return;
|
||||
|
@ -355,11 +351,11 @@ __fi void vif1Interrupt()
|
|||
vif1.vifstalled.enabled = false;
|
||||
|
||||
//Mirroring change to VIF0
|
||||
if (vif1.cmd)
|
||||
if (vif1.cmd)
|
||||
{
|
||||
if (vif1.done && (vif1ch.qwc == 0)) vif1Regs.stat.VPS = VPS_WAITING;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
vif1Regs.stat.VPS = VPS_IDLE;
|
||||
}
|
||||
|
|
|
@ -327,19 +327,28 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
|
|||
{
|
||||
if ((psHu32(mem & ~0xff) & 0x100) && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER + 2))
|
||||
{
|
||||
DevCon.Warning("Gamefix: Write to DMA addr %x while STR is busy!", mem);
|
||||
//DevCon.Warning("Gamefix: Write to DMA addr %x while STR is busy!", mem);
|
||||
while (psHu32(mem & ~0xff) & 0x100)
|
||||
{
|
||||
switch ((mem >> 8) & 0xFF)
|
||||
{
|
||||
case 0x80: // VIF0
|
||||
vif0Interrupt();
|
||||
cpuRegs.interrupt &= ~(1 << DMAC_VIF0);
|
||||
break;
|
||||
case 0x90: // VIF1
|
||||
vif1Interrupt();
|
||||
if (vif1Regs.stat.VEW)
|
||||
{
|
||||
vu1Finish(false);
|
||||
vif1VUFinish();
|
||||
}
|
||||
else
|
||||
vif1Interrupt();
|
||||
cpuRegs.interrupt &= ~(1 << DMAC_VIF1);
|
||||
break;
|
||||
case 0xA0: // GIF
|
||||
gifInterrupt();
|
||||
cpuRegs.interrupt &= ~(1 << DMAC_GIF);
|
||||
break;
|
||||
case 0xB0: // IPUFROM
|
||||
[[fallthrough]];
|
||||
|
@ -351,9 +360,11 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
|
|||
break;
|
||||
case 0xD0: // SPRFROM
|
||||
SPRFROMinterrupt();
|
||||
cpuRegs.interrupt &= ~(1 << DMAC_FROM_SPR);
|
||||
break;
|
||||
case 0xD4: // SPRTO
|
||||
SPRTOinterrupt();
|
||||
cpuRegs.interrupt &= ~(1 << DMAC_TO_SPR);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -127,21 +127,24 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit)
|
|||
|
||||
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
|
||||
|
||||
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
|
||||
if (isEbit) // Clear 'is busy' Flags
|
||||
{
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
||||
}
|
||||
else
|
||||
xFastCall((void*)mVUTBit);
|
||||
}
|
||||
|
||||
if (isEbit != 2) // Save PC, and Jump to Exit Point
|
||||
{
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUTBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
}
|
||||
|
||||
memcpy(&mVUregs, &stateBackup, sizeof(mVUregs)); //Restore the state for the rest of the recompile
|
||||
}
|
||||
|
||||
|
@ -244,6 +247,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit)
|
|||
xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1);
|
||||
}
|
||||
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
|
||||
if ((isEbit && isEbit != 3)) // Clear 'is busy' Flags
|
||||
{
|
||||
|
@ -252,8 +256,6 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit)
|
|||
{
|
||||
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
||||
}
|
||||
else
|
||||
xFastCall((void*)mVUEBit);
|
||||
}
|
||||
else if(isEbit)
|
||||
{
|
||||
|
@ -262,7 +264,8 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit)
|
|||
|
||||
if (isEbit != 2 && isEbit != 3) // Save PC, and Jump to Exit Point
|
||||
{
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
}
|
||||
memcpy(&mVUregs, &stateBackup, sizeof(mVUregs)); //Restore the state for the rest of the recompile
|
||||
|
@ -321,6 +324,8 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump)
|
|||
//So if it is taken, you need to end the program, else you get infinite loops.
|
||||
mVUendProgram(mVU, &mFC, 2);
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], arg1regd);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
}
|
||||
|
||||
|
@ -340,7 +345,10 @@ void normBranch(mV, microFlagCycles& mFC)
|
|||
if (mVUup.dBit && doDBitHandling)
|
||||
{
|
||||
u32 tempPC = iPC;
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
|
@ -355,7 +363,10 @@ void normBranch(mV, microFlagCycles& mFC)
|
|||
if (mVUup.tBit)
|
||||
{
|
||||
u32 tempPC = iPC;
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
|
@ -381,6 +392,8 @@ void normBranch(mV, microFlagCycles& mFC)
|
|||
mVUendProgram(mVU, &mFC, 3);
|
||||
iPC = branchAddr(mVU) / 4;
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
iPC = tempPC;
|
||||
}
|
||||
|
@ -407,7 +420,10 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
|||
{
|
||||
DevCon.Warning("T-Bit on branch, please report if broken");
|
||||
u32 tempPC = iPC;
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
|
@ -419,11 +435,15 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
|||
xForwardJump32 tJMP(xInvertCond((JccComparisonType)JMPcc));
|
||||
incPC(4); // Set PC to First instruction of Non-Taken Side
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUTBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
tJMP.SetTarget();
|
||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||
iPC = branchAddr(mVU) / 4;
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUTBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
eJMP.SetTarget();
|
||||
iPC = tempPC;
|
||||
|
@ -431,7 +451,10 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
|||
if (mVUup.dBit && doDBitHandling)
|
||||
{
|
||||
u32 tempPC = iPC;
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
|
@ -466,11 +489,15 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
|||
xForwardJump32 dJMP((JccComparisonType)JMPcc);
|
||||
incPC(4); // Set PC to First instruction of Non-Taken Side
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
dJMP.SetTarget();
|
||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||
iPC = branchAddr(mVU) / 4;
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
iPC = tempPC;
|
||||
}
|
||||
|
@ -486,12 +513,16 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
|||
xForwardJump32 eJMP(((JccComparisonType)JMPcc));
|
||||
incPC(1); // Set PC to First instruction of Non-Taken Side
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
eJMP.SetTarget();
|
||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||
|
||||
iPC = branchAddr(mVU) / 4;
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
return;
|
||||
}
|
||||
|
@ -550,7 +581,10 @@ void normJump(mV, microFlagCycles& mFC)
|
|||
}
|
||||
if (mVUup.dBit && doDBitHandling)
|
||||
{
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
if (THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
|
@ -565,7 +599,10 @@ void normJump(mV, microFlagCycles& mFC)
|
|||
}
|
||||
if (mVUup.tBit)
|
||||
{
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!mVU.index || !THREAD_VU1)
|
||||
{
|
||||
|
@ -575,6 +612,8 @@ void normJump(mV, microFlagCycles& mFC)
|
|||
mVUDTendProgram(mVU, &mFC, 2);
|
||||
xMOV(gprT1, ptr32[&mVU.branch]);
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUTBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
eJMP.SetTarget();
|
||||
}
|
||||
|
@ -583,6 +622,8 @@ void normJump(mV, microFlagCycles& mFC)
|
|||
mVUendProgram(mVU, &mFC, 2);
|
||||
xMOV(gprT1, ptr32[&mVU.branch]);
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xFastCall((void*)mVUEBit);
|
||||
xJMP(mVU.exitFunct);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -549,7 +549,10 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr)
|
|||
|
||||
void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
|
||||
{
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x400 : 0x4));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!isVU1 || !THREAD_VU1)
|
||||
{
|
||||
|
@ -564,7 +567,10 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
|
|||
|
||||
void mVUDoTBit(microVU& mVU, microFlagCycles* mFC)
|
||||
{
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
if (mVU.index && THREAD_VU1)
|
||||
xTEST(ptr32[&vu1Thread.vuFBRST], (isVU1 ? 0x800 : 0x8));
|
||||
else
|
||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
|
||||
xForwardJump32 eJMP(Jcc_Zero);
|
||||
if (!isVU1 || !THREAD_VU1)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern void _vu0WaitMicro();
|
||||
extern void _vu0FinishMicro();
|
||||
|
||||
|
|
Loading…
Reference in New Issue