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();
|
vifRegs.itop = Read();
|
||||||
|
|
||||||
if (addr != -1) vuRegs.VI[REG_TPC].UL = addr;
|
if (addr != -1) vuRegs.VI[REG_TPC].UL = addr;
|
||||||
|
vuCPU->SetStartPC(vuRegs.VI[REG_TPC].UL << 3);
|
||||||
vuCPU->Execute(vu1RunCycles);
|
vuCPU->Execute(vu1RunCycles);
|
||||||
gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU();
|
gifUnit.gifPath[GIF_PATH_1].FinishGSPacketMTVU();
|
||||||
semaXGkick.Post(); // Tell MTGS a path1 packet is complete
|
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
|
// 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.
|
// 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
|
// 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. :)
|
// 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
|
// 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)
|
// but not microVU. Would like to have it local to their respective classes... someday)
|
||||||
u32 code;
|
u32 code;
|
||||||
|
u32 start_pc;
|
||||||
|
|
||||||
// branch/branchpc are used by interpreter only, but making them local to the interpreter
|
// branch/branchpc are used by interpreter only, but making them local to the interpreter
|
||||||
// classes requires considerable code refactoring. Maybe later. >_<
|
// classes requires considerable code refactoring. Maybe later. >_<
|
||||||
|
|
|
@ -48,6 +48,8 @@ void __fastcall vu0ExecMicro(u32 addr) {
|
||||||
VU0.VI[REG_VPU_STAT].UL |= 0x01;
|
VU0.VI[REG_VPU_STAT].UL |= 0x01;
|
||||||
VU0.cycle = cpuRegs.cycle;
|
VU0.cycle = cpuRegs.cycle;
|
||||||
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
|
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
|
||||||
|
|
||||||
|
CpuVU0->SetStartPC(VU0.VI[REG_TPC].UL << 3);
|
||||||
_vuExecMicroDebug(VU0);
|
_vuExecMicroDebug(VU0);
|
||||||
CpuVU0->ExecuteBlock(1);
|
CpuVU0->ExecuteBlock(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,11 @@ InterpVU0::InterpVU0()
|
||||||
IsInterpreter = true;
|
IsInterpreter = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpVU0::SetStartPC(u32 startPC)
|
||||||
|
{
|
||||||
|
VU0.start_pc = startPC;
|
||||||
|
}
|
||||||
|
|
||||||
void InterpVU0::Step()
|
void InterpVU0::Step()
|
||||||
{
|
{
|
||||||
vu0Exec( &VU0 );
|
vu0Exec( &VU0 );
|
||||||
|
|
|
@ -61,7 +61,8 @@ void __fastcall vu1ExecMicro(u32 addr)
|
||||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||||
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
||||||
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
|
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);
|
CpuVU1->Execute(vu1RunCycles);
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,11 @@ void InterpVU1::Shutdown() noexcept {
|
||||||
vu1Thread.WaitVU();
|
vu1Thread.WaitVU();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpVU1::SetStartPC(u32 startPC)
|
||||||
|
{
|
||||||
|
VU1.start_pc = startPC;
|
||||||
|
}
|
||||||
|
|
||||||
void InterpVU1::Step()
|
void InterpVU1::Step()
|
||||||
{
|
{
|
||||||
VU1.VI[REG_TPC].UL &= VU1_PROGMASK;
|
VU1.VI[REG_TPC].UL &= VU1_PROGMASK;
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
virtual void Reserve()=0;
|
virtual void Reserve()=0;
|
||||||
virtual void Shutdown()=0;
|
virtual void Shutdown()=0;
|
||||||
virtual void Reset()=0;
|
virtual void Reset()=0;
|
||||||
|
virtual void SetStartPC(u32 startPC)=0;
|
||||||
virtual void Execute(u32 cycles)=0;
|
virtual void Execute(u32 cycles)=0;
|
||||||
virtual void ExecuteBlock(bool startUp)=0;
|
virtual void ExecuteBlock(bool startUp)=0;
|
||||||
|
|
||||||
|
@ -172,6 +173,7 @@ public:
|
||||||
void Reset() { }
|
void Reset() { }
|
||||||
|
|
||||||
void Step();
|
void Step();
|
||||||
|
void SetStartPC(u32 startPC);
|
||||||
void Execute(u32 cycles);
|
void Execute(u32 cycles);
|
||||||
void Clear(u32 addr, u32 size) {}
|
void Clear(u32 addr, u32 size) {}
|
||||||
|
|
||||||
|
@ -192,6 +194,7 @@ public:
|
||||||
void Shutdown() noexcept;
|
void Shutdown() noexcept;
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
void SetStartPC(u32 startPC);
|
||||||
void Step();
|
void Step();
|
||||||
void Execute(u32 cycles);
|
void Execute(u32 cycles);
|
||||||
void Clear(u32 addr, u32 size) {}
|
void Clear(u32 addr, u32 size) {}
|
||||||
|
@ -217,6 +220,7 @@ public:
|
||||||
void Shutdown() noexcept;
|
void Shutdown() noexcept;
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
void SetStartPC(u32 startPC);
|
||||||
void Execute(u32 cycles);
|
void Execute(u32 cycles);
|
||||||
void Clear(u32 addr, u32 size);
|
void Clear(u32 addr, u32 size);
|
||||||
void Vsync() noexcept;
|
void Vsync() noexcept;
|
||||||
|
@ -237,6 +241,7 @@ public:
|
||||||
void Reserve();
|
void Reserve();
|
||||||
void Shutdown() noexcept;
|
void Shutdown() noexcept;
|
||||||
void Reset();
|
void Reset();
|
||||||
|
void SetStartPC(u32 startPC);
|
||||||
void Execute(u32 cycles);
|
void Execute(u32 cycles);
|
||||||
void Clear(u32 addr, u32 size);
|
void Clear(u32 addr, u32 size);
|
||||||
void Vsync() noexcept;
|
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)
|
// Searches for Cached Micro Program and sets prog.cur to it (returns entry-point to program)
|
||||||
_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||||
microVU& mVU = mVUx;
|
microVU& mVU = mVUx;
|
||||||
microProgramQuick& quick = mVU.prog.quick[startPC/8];
|
microProgramQuick& quick = mVU.prog.quick[mVU.regs().start_pc/8];
|
||||||
microProgramList* list = mVU.prog.prog [startPC/8];
|
microProgramList* list = mVU.prog.prog [mVU.regs().start_pc/8];
|
||||||
|
|
||||||
if(!quick.prog) { // If null, we need to search for new program
|
if(!quick.prog) { // If null, we need to search for new program
|
||||||
std::deque<microProgram*>::iterator it(list->begin());
|
std::deque<microProgram*>::iterator it(list->begin());
|
||||||
for ( ; it != list->end(); ++it) {
|
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
|
// If cleared and program not found, make a new program instance
|
||||||
mVU.prog.cleared = 0;
|
mVU.prog.cleared = 0;
|
||||||
mVU.prog.isSame = 1;
|
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);
|
void* entryPoint = mVUblockFetch(mVU, startPC, pState);
|
||||||
quick.block = mVU.prog.cur->block[startPC/8];
|
quick.block = mVU.prog.cur->block[startPC/8];
|
||||||
quick.prog = mVU.prog.cur;
|
quick.prog = mVU.prog.cur;
|
||||||
|
@ -301,9 +302,13 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||||
//mVUprintUniqueRatio(mVU);
|
//mVUprintUniqueRatio(mVU);
|
||||||
return entryPoint;
|
return entryPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If list.quick, then we've already found and recompiled the program ;)
|
// If list.quick, then we've already found and recompiled the program ;)
|
||||||
mVU.prog.isSame = -1;
|
mVU.prog.isSame = -1;
|
||||||
mVU.prog.cur = quick.prog;
|
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);
|
return mVUentryGet(mVU, quick.block, startPC, pState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,6 +352,11 @@ void recMicroVU1::Reset() {
|
||||||
mVUreset(microVU1, true);
|
mVUreset(microVU1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void recMicroVU0::SetStartPC(u32 startPC)
|
||||||
|
{
|
||||||
|
VU0.start_pc = startPC;
|
||||||
|
}
|
||||||
|
|
||||||
void recMicroVU0::Execute(u32 cycles) {
|
void recMicroVU0::Execute(u32 cycles) {
|
||||||
pxAssert(m_Reserved); // please allocate me first! :|
|
pxAssert(m_Reserved); // please allocate me first! :|
|
||||||
|
|
||||||
|
@ -366,6 +376,12 @@ void recMicroVU0::Execute(u32 cycles) {
|
||||||
hwIntcIrq(6);
|
hwIntcIrq(6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void recMicroVU1::SetStartPC(u32 startPC)
|
||||||
|
{
|
||||||
|
VU1.start_pc = startPC;
|
||||||
|
}
|
||||||
|
|
||||||
void recMicroVU1::Execute(u32 cycles) {
|
void recMicroVU1::Execute(u32 cycles) {
|
||||||
pxAssert(m_Reserved); // please allocate me first! :|
|
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) {
|
void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
||||||
|
|
||||||
int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit);
|
int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit && isEbit != 3);
|
||||||
int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit);
|
int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit && isEbit != 3);
|
||||||
int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit);
|
int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit && isEbit != 3);
|
||||||
int qInst = 0;
|
int qInst = 0;
|
||||||
int pInst = 0;
|
int pInst = 0;
|
||||||
microBlock stateBackup;
|
microBlock stateBackup;
|
||||||
memcpy(&stateBackup, &mVUregs, sizeof(mVUregs)); //backup the state, it's about to get screwed with.
|
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
|
mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P
|
||||||
else
|
else
|
||||||
mVU.regAlloc->flushAll();
|
mVU.regAlloc->flushAll();
|
||||||
|
|
||||||
if (isEbit) {
|
if (isEbit && isEbit != 3) {
|
||||||
memzero(mVUinfo);
|
memzero(mVUinfo);
|
||||||
memzero(mVUregsTemp);
|
memzero(mVUregsTemp);
|
||||||
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
|
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_MAC_FLAG].UL], gprT1);
|
||||||
xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2);
|
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(xmmT1, ptr128[mVU.macFlag]);
|
||||||
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1);
|
xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1);
|
||||||
xMOVAPS(xmmT1, ptr128[mVU.clipFlag]);
|
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) {
|
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
|
||||||
//xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
|
//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);
|
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
|
||||||
xJMP(mVU.exitFunct);
|
xJMP(mVU.exitFunct);
|
||||||
}
|
}
|
||||||
|
@ -293,6 +293,21 @@ void normBranch(mV, microFlagCycles& mFC) {
|
||||||
eJMP.SetTarget();
|
eJMP.SetTarget();
|
||||||
iPC = tempPC;
|
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 (mVUup.eBit) {
|
||||||
if(mVUlow.badBranch)
|
if(mVUlow.badBranch)
|
||||||
DevCon.Warning("End on evil Unconditional branch! - Not implemented! - If game broken report to PCSX2 Team");
|
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();
|
eJMP.SetTarget();
|
||||||
iPC = tempPC;
|
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 (mVUup.eBit) { // Conditional Branch With E-Bit Set
|
||||||
if(mVUlow.evilBranch)
|
if(mVUlow.evilBranch)
|
||||||
DevCon.Warning("End on evil branch! - Not implemented! - If game broken report to PCSX2 Team");
|
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) {
|
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 (mVUlow.constJump.isValid) { // Jump Address is Constant
|
||||||
if (mVUup.eBit) { // E-bit Jump
|
if (mVUup.eBit) { // E-bit Jump
|
||||||
iPC = (mVUlow.constJump.regValue*2) & (mVU.progMemMask);
|
iPC = (mVUlow.constJump.regValue*2) & (mVU.progMemMask);
|
||||||
|
|
|
@ -567,13 +567,18 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((curI & _Mbit_) && isVU0) {
|
if ((curI & _Mbit_) && isVU0) {
|
||||||
incPC(-2);
|
if (xPC > 0)
|
||||||
if (!(curI & _Mbit_)) { //If the last instruction was also M-Bit we don't need to sync again
|
{
|
||||||
incPC(2);
|
incPC(-2);
|
||||||
mVUup.mBit = true;
|
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
|
else
|
||||||
incPC(2);
|
mVUup.mBit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curI & _Ibit_) {
|
if (curI & _Ibit_) {
|
||||||
|
@ -677,6 +682,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
|
||||||
mVUsetupRange(mVU, xPC, false);
|
mVUsetupRange(mVU, xPC, false);
|
||||||
incPC(2);
|
incPC(2);
|
||||||
mVUendProgram(mVU, &mFC, 0);
|
mVUendProgram(mVU, &mFC, 0);
|
||||||
|
normBranchCompile(mVU, xPC);
|
||||||
incPC(-2);
|
incPC(-2);
|
||||||
goto perf_and_return;
|
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
|
if (doJumpAsSameProgram) { // Treat jump as part of same microProgram
|
||||||
return mVUblockFetch(mVUx, startPC, ptr);
|
return mVUblockFetch(mVUx, startPC, ptr);
|
||||||
}
|
}
|
||||||
|
mVUx.regs().start_pc = startPC;
|
||||||
if (doJumpCaching) { // When doJumpCaching, ptr is a microBlock pointer
|
if (doJumpCaching) { // When doJumpCaching, ptr is a microBlock pointer
|
||||||
microVU& mVU = mVUx;
|
microVU& mVU = mVUx;
|
||||||
microBlock* pBlock = (microBlock*)ptr;
|
microBlock* pBlock = (microBlock*)ptr;
|
||||||
|
|
Loading…
Reference in New Issue