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_mvuFlag = SpeedhackId_FIRST,
|
||||||
Speedhack_InstantVU1,
|
Speedhack_InstantVU1,
|
||||||
|
Speedhack_MTVU,
|
||||||
|
|
||||||
SpeedhackId_COUNT
|
SpeedhackId_COUNT
|
||||||
};
|
};
|
||||||
|
|
|
@ -146,7 +146,7 @@ void VU_Thread::ExecuteRingBuffer()
|
||||||
s32 addr = Read();
|
s32 addr = Read();
|
||||||
vifRegs.top = Read();
|
vifRegs.top = Read();
|
||||||
vifRegs.itop = Read();
|
vifRegs.itop = Read();
|
||||||
|
vuFBRST = Read();
|
||||||
if (addr != -1)
|
if (addr != -1)
|
||||||
vuRegs.VI[REG_TPC].UL = addr & 0x7FF;
|
vuRegs.VI[REG_TPC].UL = addr & 0x7FF;
|
||||||
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3);
|
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);
|
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);
|
//DevCon.Warning("E-Bit registered %x", VU0.VI[REG_VPU_STAT].UL);
|
||||||
}
|
}
|
||||||
if (interrupts & InterruptFlagVUTBit)
|
if (interrupts & InterruptFlagVUTBit)
|
||||||
{
|
{
|
||||||
mtvuInterrupts.fetch_and(~InterruptFlagVUTBit, std::memory_order_relaxed);
|
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;
|
VU0.VI[REG_VPU_STAT].UL |= 0x0400;
|
||||||
//DevCon.Warning("T-Bit registered %x", VU0.VI[REG_VPU_STAT].UL);
|
//DevCon.Warning("T-Bit registered %x", VU0.VI[REG_VPU_STAT].UL);
|
||||||
hwIntcIrq(7);
|
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!");
|
MTVU_LOG("MTVU - ExecuteVU!");
|
||||||
Get_MTVUChanges(); // Clear any pending interrupts
|
Get_MTVUChanges(); // Clear any pending interrupts
|
||||||
ReserveSpace(4);
|
ReserveSpace(5);
|
||||||
Write(MTVU_VU_EXECUTE);
|
Write(MTVU_VU_EXECUTE);
|
||||||
Write(vu_addr);
|
Write(vu_addr);
|
||||||
Write(vif_top);
|
Write(vif_top);
|
||||||
Write(vif_itop);
|
Write(vif_itop);
|
||||||
|
Write(fbrst);
|
||||||
CommitWritePos();
|
CommitWritePos();
|
||||||
gifUnit.TransferGSPacketData(GIF_TRANS_MTVU, NULL, 0);
|
gifUnit.TransferGSPacketData(GIF_TRANS_MTVU, NULL, 0);
|
||||||
KickStart();
|
KickStart();
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
Semaphore semaXGkick;
|
Semaphore semaXGkick;
|
||||||
std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
|
std::atomic<unsigned int> vuCycles[4]; // Used for VU cycle stealing hack
|
||||||
u32 vuCycleIdx; // Used for VU cycle stealing hack
|
u32 vuCycleIdx; // Used for VU cycle stealing hack
|
||||||
|
u32 vuFBRST;
|
||||||
|
|
||||||
enum InterruptFlag {
|
enum InterruptFlag {
|
||||||
InterruptFlagFinish = 1 << 0,
|
InterruptFlagFinish = 1 << 0,
|
||||||
|
@ -76,7 +77,7 @@ public:
|
||||||
|
|
||||||
void Get_MTVUChanges();
|
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);
|
void VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, u8* data, u32 size);
|
||||||
|
|
||||||
|
|
|
@ -65,9 +65,11 @@ void TraceLogFilters::LoadSave(SettingsWrapper& wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* const tbl_SpeedhackNames[] =
|
const char* const tbl_SpeedhackNames[] =
|
||||||
{
|
{
|
||||||
"mvuFlag",
|
"mvuFlag",
|
||||||
"InstantVU1"};
|
"InstantVU1",
|
||||||
|
"MTVU"
|
||||||
|
};
|
||||||
|
|
||||||
const char* EnumToString(SpeedhackId id)
|
const char* EnumToString(SpeedhackId id)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +87,9 @@ void Pcsx2Config::SpeedhackOptions::Set(SpeedhackId id, bool enabled)
|
||||||
case Speedhack_InstantVU1:
|
case Speedhack_InstantVU1:
|
||||||
vu1Instant = enabled;
|
vu1Instant = enabled;
|
||||||
break;
|
break;
|
||||||
|
case Speedhack_MTVU:
|
||||||
|
vuThread = enabled;
|
||||||
|
break;
|
||||||
jNO_DEFAULT;
|
jNO_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,12 @@ static void TestClearVUs(u32 madr, u32 qwc, bool isWrite)
|
||||||
//Catch up VU1 too
|
//Catch up VU1 too
|
||||||
CpuVU1->ExecuteBlock(0);
|
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;
|
cpuRegs.cycle = VU1.cycle;
|
||||||
//Catch up VU0 too
|
//Catch up VU0 too
|
||||||
CpuVU0->ExecuteBlock(0);
|
CpuVU0->ExecuteBlock(0);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "R5900OpcodeTables.h"
|
#include "R5900OpcodeTables.h"
|
||||||
#include "VUmicro.h"
|
#include "VUmicro.h"
|
||||||
#include "Vif_Dma.h"
|
#include "Vif_Dma.h"
|
||||||
|
#include "MTVU.h"
|
||||||
|
|
||||||
#define _Ft_ _Rt_
|
#define _Ft_ _Rt_
|
||||||
#define _Fs_ _Rd_
|
#define _Fs_ _Rd_
|
||||||
|
|
|
@ -61,15 +61,16 @@ void __fastcall vu1ExecMicro(u32 addr)
|
||||||
{
|
{
|
||||||
if (THREAD_VU1) {
|
if (THREAD_VU1) {
|
||||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||||
|
|
||||||
// Okay this is a little bit of a hack, but with good reason.
|
// 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
|
// 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"
|
// 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.
|
// 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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
|
|
|
@ -305,6 +305,7 @@ _vifT __fi u32 vifRead32(u32 mem)
|
||||||
{
|
{
|
||||||
vifStruct& vif = MTVU_VifX;
|
vifStruct& vif = MTVU_VifX;
|
||||||
bool wait = idx && THREAD_VU1;
|
bool wait = idx && THREAD_VU1;
|
||||||
|
|
||||||
switch (mem)
|
switch (mem)
|
||||||
{
|
{
|
||||||
case caseVif(ROW0):
|
case caseVif(ROW0):
|
||||||
|
@ -380,44 +381,36 @@ _vifT __fi bool vifWrite32(u32 mem, u32 value)
|
||||||
|
|
||||||
case caseVif(ROW0):
|
case caseVif(ROW0):
|
||||||
vif.MaskRow._u32[0] = value;
|
vif.MaskRow._u32[0] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteRow(vif);
|
||||||
vu1Thread.WriteRow(vif);
|
|
||||||
return false;
|
return false;
|
||||||
case caseVif(ROW1):
|
case caseVif(ROW1):
|
||||||
vif.MaskRow._u32[1] = value;
|
vif.MaskRow._u32[1] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteRow(vif);
|
||||||
vu1Thread.WriteRow(vif);
|
|
||||||
return false;
|
return false;
|
||||||
case caseVif(ROW2):
|
case caseVif(ROW2):
|
||||||
vif.MaskRow._u32[2] = value;
|
vif.MaskRow._u32[2] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteRow(vif);
|
||||||
vu1Thread.WriteRow(vif);
|
|
||||||
return false;
|
return false;
|
||||||
case caseVif(ROW3):
|
case caseVif(ROW3):
|
||||||
vif.MaskRow._u32[3] = value;
|
vif.MaskRow._u32[3] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteRow(vif);
|
||||||
vu1Thread.WriteRow(vif);
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case caseVif(COL0):
|
case caseVif(COL0):
|
||||||
vif.MaskCol._u32[0] = value;
|
vif.MaskCol._u32[0] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteCol(vif);
|
||||||
vu1Thread.WriteCol(vif);
|
|
||||||
return false;
|
return false;
|
||||||
case caseVif(COL1):
|
case caseVif(COL1):
|
||||||
vif.MaskCol._u32[1] = value;
|
vif.MaskCol._u32[1] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteCol(vif);
|
||||||
vu1Thread.WriteCol(vif);
|
|
||||||
return false;
|
return false;
|
||||||
case caseVif(COL2):
|
case caseVif(COL2):
|
||||||
vif.MaskCol._u32[2] = value;
|
vif.MaskCol._u32[2] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteCol(vif);
|
||||||
vu1Thread.WriteCol(vif);
|
|
||||||
return false;
|
return false;
|
||||||
case caseVif(COL3):
|
case caseVif(COL3):
|
||||||
vif.MaskCol._u32[3] = value;
|
vif.MaskCol._u32[3] = value;
|
||||||
if (idx && THREAD_VU1)
|
vu1Thread.WriteCol(vif);
|
||||||
vu1Thread.WriteCol(vif);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,9 +173,6 @@ __fi void vif1SetupTransfer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (vif1ch.chcr.TTE)
|
if (vif1ch.chcr.TTE)
|
||||||
{
|
{
|
||||||
// Transfer dma tag if tte is set
|
// Transfer dma tag if tte is set
|
||||||
|
@ -233,8 +230,7 @@ __fi void vif1VUFinish()
|
||||||
{
|
{
|
||||||
if (VU0.VI[REG_VPU_STAT].UL & 0x500)
|
if (VU0.VI[REG_VPU_STAT].UL & 0x500)
|
||||||
{
|
{
|
||||||
if(THREAD_VU1)
|
vu1Thread.Get_MTVUChanges();
|
||||||
vu1Thread.Get_MTVUChanges();
|
|
||||||
|
|
||||||
CPU_INT(VIF_VU1_FINISH, 128);
|
CPU_INT(VIF_VU1_FINISH, 128);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -327,19 +327,28 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
|
||||||
{
|
{
|
||||||
if ((psHu32(mem & ~0xff) & 0x100) && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER + 2))
|
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)
|
while (psHu32(mem & ~0xff) & 0x100)
|
||||||
{
|
{
|
||||||
switch ((mem >> 8) & 0xFF)
|
switch ((mem >> 8) & 0xFF)
|
||||||
{
|
{
|
||||||
case 0x80: // VIF0
|
case 0x80: // VIF0
|
||||||
vif0Interrupt();
|
vif0Interrupt();
|
||||||
|
cpuRegs.interrupt &= ~(1 << DMAC_VIF0);
|
||||||
break;
|
break;
|
||||||
case 0x90: // VIF1
|
case 0x90: // VIF1
|
||||||
vif1Interrupt();
|
if (vif1Regs.stat.VEW)
|
||||||
|
{
|
||||||
|
vu1Finish(false);
|
||||||
|
vif1VUFinish();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vif1Interrupt();
|
||||||
|
cpuRegs.interrupt &= ~(1 << DMAC_VIF1);
|
||||||
break;
|
break;
|
||||||
case 0xA0: // GIF
|
case 0xA0: // GIF
|
||||||
gifInterrupt();
|
gifInterrupt();
|
||||||
|
cpuRegs.interrupt &= ~(1 << DMAC_GIF);
|
||||||
break;
|
break;
|
||||||
case 0xB0: // IPUFROM
|
case 0xB0: // IPUFROM
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
@ -351,9 +360,11 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
|
||||||
break;
|
break;
|
||||||
case 0xD0: // SPRFROM
|
case 0xD0: // SPRFROM
|
||||||
SPRFROMinterrupt();
|
SPRFROMinterrupt();
|
||||||
|
cpuRegs.interrupt &= ~(1 << DMAC_FROM_SPR);
|
||||||
break;
|
break;
|
||||||
case 0xD4: // SPRTO
|
case 0xD4: // SPRTO
|
||||||
SPRTOinterrupt();
|
SPRTOinterrupt();
|
||||||
|
cpuRegs.interrupt &= ~(1 << DMAC_TO_SPR);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -127,21 +127,24 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit)
|
||||||
|
|
||||||
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
|
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
|
||||||
|
|
||||||
|
|
||||||
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
|
||||||
if (isEbit) // Clear 'is busy' Flags
|
if (isEbit) // Clear 'is busy' Flags
|
||||||
{
|
{
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
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
|
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);
|
xJMP(mVU.exitFunct);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&mVUregs, &stateBackup, sizeof(mVUregs)); //Restore the state for the rest of the recompile
|
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);
|
xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
|
||||||
if ((isEbit && isEbit != 3)) // Clear 'is busy' Flags
|
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
|
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
||||||
}
|
}
|
||||||
else
|
|
||||||
xFastCall((void*)mVUEBit);
|
|
||||||
}
|
}
|
||||||
else if(isEbit)
|
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
|
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);
|
xJMP(mVU.exitFunct);
|
||||||
}
|
}
|
||||||
memcpy(&mVUregs, &stateBackup, sizeof(mVUregs)); //Restore the state for the rest of the recompile
|
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.
|
//So if it is taken, you need to end the program, else you get infinite loops.
|
||||||
mVUendProgram(mVU, &mFC, 2);
|
mVUendProgram(mVU, &mFC, 2);
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], arg1regd);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], arg1regd);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +345,10 @@ void normBranch(mV, microFlagCycles& mFC)
|
||||||
if (mVUup.dBit && doDBitHandling)
|
if (mVUup.dBit && doDBitHandling)
|
||||||
{
|
{
|
||||||
u32 tempPC = iPC;
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -355,7 +363,10 @@ void normBranch(mV, microFlagCycles& mFC)
|
||||||
if (mVUup.tBit)
|
if (mVUup.tBit)
|
||||||
{
|
{
|
||||||
u32 tempPC = iPC;
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -381,6 +392,8 @@ void normBranch(mV, microFlagCycles& mFC)
|
||||||
mVUendProgram(mVU, &mFC, 3);
|
mVUendProgram(mVU, &mFC, 3);
|
||||||
iPC = branchAddr(mVU) / 4;
|
iPC = branchAddr(mVU) / 4;
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
iPC = tempPC;
|
iPC = tempPC;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +420,10 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
{
|
{
|
||||||
DevCon.Warning("T-Bit on branch, please report if broken");
|
DevCon.Warning("T-Bit on branch, please report if broken");
|
||||||
u32 tempPC = iPC;
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -419,11 +435,15 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
xForwardJump32 tJMP(xInvertCond((JccComparisonType)JMPcc));
|
xForwardJump32 tJMP(xInvertCond((JccComparisonType)JMPcc));
|
||||||
incPC(4); // Set PC to First instruction of Non-Taken Side
|
incPC(4); // Set PC to First instruction of Non-Taken Side
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUTBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
tJMP.SetTarget();
|
tJMP.SetTarget();
|
||||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||||
iPC = branchAddr(mVU) / 4;
|
iPC = branchAddr(mVU) / 4;
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUTBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
eJMP.SetTarget();
|
eJMP.SetTarget();
|
||||||
iPC = tempPC;
|
iPC = tempPC;
|
||||||
|
@ -431,7 +451,10 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
if (mVUup.dBit && doDBitHandling)
|
if (mVUup.dBit && doDBitHandling)
|
||||||
{
|
{
|
||||||
u32 tempPC = iPC;
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -466,11 +489,15 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
xForwardJump32 dJMP((JccComparisonType)JMPcc);
|
xForwardJump32 dJMP((JccComparisonType)JMPcc);
|
||||||
incPC(4); // Set PC to First instruction of Non-Taken Side
|
incPC(4); // Set PC to First instruction of Non-Taken Side
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
dJMP.SetTarget();
|
dJMP.SetTarget();
|
||||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||||
iPC = branchAddr(mVU) / 4;
|
iPC = branchAddr(mVU) / 4;
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
iPC = tempPC;
|
iPC = tempPC;
|
||||||
}
|
}
|
||||||
|
@ -486,12 +513,16 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
xForwardJump32 eJMP(((JccComparisonType)JMPcc));
|
xForwardJump32 eJMP(((JccComparisonType)JMPcc));
|
||||||
incPC(1); // Set PC to First instruction of Non-Taken Side
|
incPC(1); // Set PC to First instruction of Non-Taken Side
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
eJMP.SetTarget();
|
eJMP.SetTarget();
|
||||||
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
incPC(-4); // Go Back to Branch Opcode to get branchAddr
|
||||||
|
|
||||||
iPC = branchAddr(mVU) / 4;
|
iPC = branchAddr(mVU) / 4;
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -550,7 +581,10 @@ void normJump(mV, microFlagCycles& mFC)
|
||||||
}
|
}
|
||||||
if (mVUup.dBit && doDBitHandling)
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -565,7 +599,10 @@ void normJump(mV, microFlagCycles& mFC)
|
||||||
}
|
}
|
||||||
if (mVUup.tBit)
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!mVU.index || !THREAD_VU1)
|
if (!mVU.index || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -575,6 +612,8 @@ void normJump(mV, microFlagCycles& mFC)
|
||||||
mVUDTendProgram(mVU, &mFC, 2);
|
mVUDTendProgram(mVU, &mFC, 2);
|
||||||
xMOV(gprT1, ptr32[&mVU.branch]);
|
xMOV(gprT1, ptr32[&mVU.branch]);
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUTBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
eJMP.SetTarget();
|
eJMP.SetTarget();
|
||||||
}
|
}
|
||||||
|
@ -583,6 +622,8 @@ void normJump(mV, microFlagCycles& mFC)
|
||||||
mVUendProgram(mVU, &mFC, 2);
|
mVUendProgram(mVU, &mFC, 2);
|
||||||
xMOV(gprT1, ptr32[&mVU.branch]);
|
xMOV(gprT1, ptr32[&mVU.branch]);
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
|
||||||
|
if (mVU.index && THREAD_VU1)
|
||||||
|
xFastCall((void*)mVUEBit);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -549,7 +549,10 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr)
|
||||||
|
|
||||||
void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
|
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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!isVU1 || !THREAD_VU1)
|
if (!isVU1 || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
@ -564,7 +567,10 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
|
||||||
|
|
||||||
void mVUDoTBit(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);
|
xForwardJump32 eJMP(Jcc_Zero);
|
||||||
if (!isVU1 || !THREAD_VU1)
|
if (!isVU1 || !THREAD_VU1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
extern void _vu0WaitMicro();
|
extern void _vu0WaitMicro();
|
||||||
extern void _vu0FinishMicro();
|
extern void _vu0FinishMicro();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue