mirror of https://github.com/PCSX2/pcsx2.git
mVU: Keep start PC, modify prog search to avoid recompilation
Also fix some M-Bit stuff
This commit is contained in:
parent
378eccc6ea
commit
4595aae0de
|
@ -113,6 +113,7 @@ void VU_Thread::ExecuteRingBuffer()
|
|||
vifRegs.itop = Read();
|
||||
|
||||
if (addr != -1) vuRegs.VI[REG_TPC].UL = addr;
|
||||
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3);
|
||||
vuCPU->Execute(vu1RunCycles);
|
||||
gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU();
|
||||
semaXGkick.Post(); // Tell MTGS a path1 packet is complete
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// the lower 16 bit value. IF the change is breaking of all compatibility with old
|
||||
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A11 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A12 << 16) | 0x0000;
|
||||
|
||||
// this function is meant to be used in the place of GSfreeze, and provides a safe layer
|
||||
// between the GS saving function and the MTGS's needs. :)
|
||||
|
|
|
@ -134,6 +134,7 @@ struct __aligned16 VURegs {
|
|||
// Current opcode being interpreted or recompiled (this var is used by Interps
|
||||
// but not microVU. Would like to have it local to their respective classes... someday)
|
||||
u32 code;
|
||||
u32 start_pc;
|
||||
|
||||
// branch/branchpc are used by interpreter only, but making them local to the interpreter
|
||||
// classes requires considerable code refactoring. Maybe later. >_<
|
||||
|
|
|
@ -48,6 +48,8 @@ void __fastcall vu0ExecMicro(u32 addr) {
|
|||
VU0.VI[REG_VPU_STAT].UL |= 0x01;
|
||||
VU0.cycle = cpuRegs.cycle;
|
||||
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
|
||||
|
||||
CpuVU0->SetStartPC(VU0.VI[REG_TPC].UL << 3);
|
||||
_vuExecMicroDebug(VU0);
|
||||
CpuVU0->ExecuteBlock(1);
|
||||
}
|
||||
|
|
|
@ -198,6 +198,11 @@ InterpVU0::InterpVU0()
|
|||
IsInterpreter = true;
|
||||
}
|
||||
|
||||
void InterpVU0::SetStartPC(u32 startPC)
|
||||
{
|
||||
VU0.start_pc = startPC;
|
||||
}
|
||||
|
||||
void InterpVU0::Step()
|
||||
{
|
||||
vu0Exec( &VU0 );
|
||||
|
|
|
@ -61,7 +61,8 @@ void __fastcall vu1ExecMicro(u32 addr)
|
|||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
||||
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
|
||||
_vuExecMicroDebug(VU1);
|
||||
|
||||
CpuVU1->SetStartPC(VU1.VI[REG_TPC].UL << 3);
|
||||
_vuExecMicroDebug(VU1);
|
||||
CpuVU1->Execute(vu1RunCycles);
|
||||
}
|
||||
|
|
|
@ -202,6 +202,11 @@ void InterpVU1::Shutdown() noexcept {
|
|||
vu1Thread.WaitVU();
|
||||
}
|
||||
|
||||
void InterpVU1::SetStartPC(u32 startPC)
|
||||
{
|
||||
VU1.start_pc = startPC;
|
||||
}
|
||||
|
||||
void InterpVU1::Step()
|
||||
{
|
||||
VU1.VI[REG_TPC].UL &= VU1_PROGMASK;
|
||||
|
|
|
@ -85,6 +85,7 @@ public:
|
|||
virtual void Reserve()=0;
|
||||
virtual void Shutdown()=0;
|
||||
virtual void Reset()=0;
|
||||
virtual void SetStartPC(u32 startPC)=0;
|
||||
virtual void Execute(u32 cycles)=0;
|
||||
virtual void ExecuteBlock(bool startUp)=0;
|
||||
|
||||
|
@ -172,6 +173,7 @@ public:
|
|||
void Reset() { }
|
||||
|
||||
void Step();
|
||||
void SetStartPC(u32 startPC);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size) {}
|
||||
|
||||
|
@ -192,6 +194,7 @@ public:
|
|||
void Shutdown() noexcept;
|
||||
void Reset();
|
||||
|
||||
void SetStartPC(u32 startPC);
|
||||
void Step();
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size) {}
|
||||
|
@ -217,6 +220,7 @@ public:
|
|||
void Shutdown() noexcept;
|
||||
|
||||
void Reset();
|
||||
void SetStartPC(u32 startPC);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size);
|
||||
void Vsync() noexcept;
|
||||
|
@ -237,6 +241,7 @@ public:
|
|||
void Reserve();
|
||||
void Shutdown() noexcept;
|
||||
void Reset();
|
||||
void SetStartPC(u32 startPC);
|
||||
void Execute(u32 cycles);
|
||||
void Clear(u32 addr, u32 size);
|
||||
void Vsync() noexcept;
|
||||
|
|
|
@ -256,8 +256,9 @@ __fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg)
|
|||
// Searches for Cached Micro Program and sets prog.cur to it (returns entry-point to program)
|
||||
_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||
microVU& mVU = mVUx;
|
||||
microProgramQuick& quick = mVU.prog.quick[startPC/8];
|
||||
microProgramList* list = mVU.prog.prog [startPC/8];
|
||||
microProgramQuick& quick = mVU.prog.quick[mVU.regs().start_pc/8];
|
||||
microProgramList* list = mVU.prog.prog [mVU.regs().start_pc/8];
|
||||
|
||||
if(!quick.prog) { // If null, we need to search for new program
|
||||
std::deque<microProgram*>::iterator it(list->begin());
|
||||
for ( ; it != list->end(); ++it) {
|
||||
|
@ -293,7 +294,7 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
|||
// If cleared and program not found, make a new program instance
|
||||
mVU.prog.cleared = 0;
|
||||
mVU.prog.isSame = 1;
|
||||
mVU.prog.cur = mVUcreateProg(mVU, startPC/8);
|
||||
mVU.prog.cur = mVUcreateProg(mVU, mVU.regs().start_pc/8);
|
||||
void* entryPoint = mVUblockFetch(mVU, startPC, pState);
|
||||
quick.block = mVU.prog.cur->block[startPC/8];
|
||||
quick.prog = mVU.prog.cur;
|
||||
|
@ -301,9 +302,13 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
|||
//mVUprintUniqueRatio(mVU);
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
// If list.quick, then we've already found and recompiled the program ;)
|
||||
mVU.prog.isSame = -1;
|
||||
mVU.prog.cur = quick.prog;
|
||||
mVU.prog.isSame = -1;
|
||||
mVU.prog.cur = quick.prog;
|
||||
// Because the VU's can now run in sections and not whole programs at once
|
||||
// we need to set the current block so it gets the right program back
|
||||
quick.block = mVU.prog.cur->block[startPC / 8];
|
||||
return mVUentryGet(mVU, quick.block, startPC, pState);
|
||||
}
|
||||
|
||||
|
@ -347,6 +352,11 @@ void recMicroVU1::Reset() {
|
|||
mVUreset(microVU1, true);
|
||||
}
|
||||
|
||||
void recMicroVU0::SetStartPC(u32 startPC)
|
||||
{
|
||||
VU0.start_pc = startPC;
|
||||
}
|
||||
|
||||
void recMicroVU0::Execute(u32 cycles) {
|
||||
pxAssert(m_Reserved); // please allocate me first! :|
|
||||
|
||||
|
@ -366,6 +376,12 @@ void recMicroVU0::Execute(u32 cycles) {
|
|||
hwIntcIrq(6);
|
||||
}
|
||||
}
|
||||
|
||||
void recMicroVU1::SetStartPC(u32 startPC)
|
||||
{
|
||||
VU1.start_pc = startPC;
|
||||
}
|
||||
|
||||
void recMicroVU1::Execute(u32 cycles) {
|
||||
pxAssert(m_Reserved); // please allocate me first! :|
|
||||
|
||||
|
|
|
@ -118,19 +118,19 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
|||
|
||||
void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
||||
|
||||
int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit);
|
||||
int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit);
|
||||
int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit);
|
||||
int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit && isEbit != 3);
|
||||
int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit && isEbit != 3);
|
||||
int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit && isEbit != 3);
|
||||
int qInst = 0;
|
||||
int pInst = 0;
|
||||
microBlock stateBackup;
|
||||
memcpy(&stateBackup, &mVUregs, sizeof(mVUregs)); //backup the state, it's about to get screwed with.
|
||||
if(!isEbit)
|
||||
if(!isEbit || isEbit == 3)
|
||||
mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P
|
||||
else
|
||||
mVU.regAlloc->flushAll();
|
||||
|
||||
if (isEbit) {
|
||||
if (isEbit && isEbit != 3) {
|
||||
memzero(mVUinfo);
|
||||
memzero(mVUregsTemp);
|
||||
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
|
||||
|
@ -178,7 +178,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
|||
xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1);
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2);
|
||||
|
||||
if (!isEbit) { // Backup flag instances
|
||||
if (!isEbit || isEbit == 3) { // Backup flag instances
|
||||
xMOVAPS(xmmT1, ptr128[mVU.macFlag]);
|
||||
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1);
|
||||
xMOVAPS(xmmT1, ptr128[mVU.clipFlag]);
|
||||
|
@ -204,14 +204,14 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
|||
}
|
||||
|
||||
|
||||
if (isEbit || isVU1) { // Clear 'is busy' Flags
|
||||
if ((isEbit && isEbit != 3) || isVU1) { // Clear 'is busy' Flags
|
||||
if (!mVU.index || !THREAD_VU1) {
|
||||
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
||||
//xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
|
||||
}
|
||||
}
|
||||
|
||||
if (isEbit != 2) { // 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);
|
||||
xJMP(mVU.exitFunct);
|
||||
}
|
||||
|
@ -293,6 +293,21 @@ void normBranch(mV, microFlagCycles& mFC) {
|
|||
eJMP.SetTarget();
|
||||
iPC = tempPC;
|
||||
}
|
||||
if (mVUup.mBit)
|
||||
{
|
||||
DevCon.Warning("M-Bit on normal branch, report if broken");
|
||||
u32 tempPC = iPC;
|
||||
u32* cpS = (u32*)&mVUregs;
|
||||
u32* lpS = (u32*)&mVU.prog.lpState;
|
||||
for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) {
|
||||
xMOV(ptr32[lpS], cpS[0]);
|
||||
}
|
||||
mVUendProgram(mVU, &mFC, 3);
|
||||
iPC = branchAddr(mVU) / 4;
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
xJMP(mVU.exitFunct);
|
||||
iPC = tempPC;
|
||||
}
|
||||
if (mVUup.eBit) {
|
||||
if(mVUlow.badBranch)
|
||||
DevCon.Warning("End on evil Unconditional branch! - Not implemented! - If game broken report to PCSX2 Team");
|
||||
|
@ -408,7 +423,27 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
|
|||
eJMP.SetTarget();
|
||||
iPC = tempPC;
|
||||
}
|
||||
|
||||
if (mVUup.mBit)
|
||||
{
|
||||
u32 tempPC = iPC;
|
||||
u32* cpS = (u32*)&mVUregs;
|
||||
u32* lpS = (u32*)&mVU.prog.lpState;
|
||||
for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) {
|
||||
xMOV(ptr32[lpS], cpS[0]);
|
||||
}
|
||||
mVUendProgram(mVU, &mFC, 3);
|
||||
xCMP(ptr16[&mVU.branch], 0);
|
||||
xForwardJump32 dJMP((JccComparisonType)JMPcc);
|
||||
incPC(4); // Set PC to First instruction of Non-Taken Side
|
||||
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||
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);
|
||||
xJMP(mVU.exitFunct);
|
||||
iPC = tempPC;
|
||||
}
|
||||
if (mVUup.eBit) { // Conditional Branch With E-Bit Set
|
||||
if(mVUlow.evilBranch)
|
||||
DevCon.Warning("End on evil branch! - Not implemented! - If game broken report to PCSX2 Team");
|
||||
|
@ -471,6 +506,10 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
|
|||
}
|
||||
|
||||
void normJump(mV, microFlagCycles& mFC) {
|
||||
if (mVUup.mBit)
|
||||
{
|
||||
DevCon.Warning("M-Bit on Jump! Please report if broken");
|
||||
}
|
||||
if (mVUlow.constJump.isValid) { // Jump Address is Constant
|
||||
if (mVUup.eBit) { // E-bit Jump
|
||||
iPC = (mVUlow.constJump.regValue*2) & (mVU.progMemMask);
|
||||
|
|
|
@ -567,13 +567,18 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
|
|||
}
|
||||
|
||||
if ((curI & _Mbit_) && isVU0) {
|
||||
incPC(-2);
|
||||
if (!(curI & _Mbit_)) { //If the last instruction was also M-Bit we don't need to sync again
|
||||
incPC(2);
|
||||
mVUup.mBit = true;
|
||||
if (xPC > 0)
|
||||
{
|
||||
incPC(-2);
|
||||
if (!(curI & _Mbit_)) { //If the last instruction was also M-Bit we don't need to sync again
|
||||
incPC(2);
|
||||
mVUup.mBit = true;
|
||||
}
|
||||
else
|
||||
incPC(2);
|
||||
}
|
||||
else
|
||||
incPC(2);
|
||||
mVUup.mBit = true;
|
||||
}
|
||||
|
||||
if (curI & _Ibit_) {
|
||||
|
@ -677,6 +682,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
|
|||
mVUsetupRange(mVU, xPC, false);
|
||||
incPC(2);
|
||||
mVUendProgram(mVU, &mFC, 0);
|
||||
normBranchCompile(mVU, xPC);
|
||||
incPC(-2);
|
||||
goto perf_and_return;
|
||||
}
|
||||
|
@ -773,6 +779,7 @@ _mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr) {
|
|||
if (doJumpAsSameProgram) { // Treat jump as part of same microProgram
|
||||
return mVUblockFetch(mVUx, startPC, ptr);
|
||||
}
|
||||
mVUx.regs().start_pc = startPC;
|
||||
if (doJumpCaching) { // When doJumpCaching, ptr is a microBlock pointer
|
||||
microVU& mVU = mVUx;
|
||||
microBlock* pBlock = (microBlock*)ptr;
|
||||
|
|
Loading…
Reference in New Issue