Added comments for my previous VU0 sync fix, along with some other code cleanups.

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@444 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2008-12-16 19:18:41 +00:00 committed by Gregory Hainaut
parent 1b8cd7c055
commit 8ebcc4c442
5 changed files with 54 additions and 56 deletions

View File

@ -549,6 +549,11 @@ void cpuBranchTest()
// We're in a BranchTest. All dynarec registers are flushed // We're in a BranchTest. All dynarec registers are flushed
// so there is no need to freeze registers here. // so there is no need to freeze registers here.
Cpu->ExecuteVU0Block(); Cpu->ExecuteVU0Block();
// This might be needed to keep the EE and VU0 in sync.
// A better fix will require hefty changes to the VU recs. -_-
if(VU0.VI[REG_VPU_STAT].UL & 0x1)
cpuSetNextBranchDelta( 768 );
} }
assert( !g_globalXMMSaved X86_32CODE(&& !g_globalMMXSaved) ); assert( !g_globalXMMSaved X86_32CODE(&& !g_globalMMXSaved) );

View File

@ -206,13 +206,16 @@ void vu0ExecMicro(u32 addr) {
VU0.VI[REG_VPU_STAT].UL|= 0x1; VU0.VI[REG_VPU_STAT].UL|= 0x1;
VU0.VI[REG_VPU_STAT].UL&= ~0xAE; VU0.VI[REG_VPU_STAT].UL&= ~0xAE;
cpuSetNextBranchDelta( 64 );
if (addr != -1) VU0.VI[REG_TPC].UL = addr; if (addr != -1) VU0.VI[REG_TPC].UL = addr;
_vuExecMicroDebug(VU0); _vuExecMicroDebug(VU0);
FreezeXMMRegs(1); FreezeXMMRegs(1);
Cpu->ExecuteVU0Block(); Cpu->ExecuteVU0Block();
FreezeXMMRegs(0); FreezeXMMRegs(0);
// If the VU0 program didn't finish then we'll want to finish it up
// pretty soon. This fixes vmhacks in some games (Naruto Ultimate Ninja 2)
if(VU0.VI[REG_VPU_STAT].UL & 0x1)
cpuSetNextBranchDelta( 128 );
} }
void _vu0ExecUpper(VURegs* VU, u32 *ptr) { void _vu0ExecUpper(VURegs* VU, u32 *ptr) {

View File

@ -146,11 +146,9 @@ void vu1ExecMicro(u32 addr)
if(VU0.VI[REG_VPU_STAT].UL & 0x100) { if(VU0.VI[REG_VPU_STAT].UL & 0x100) {
SysPrintf("Previous Microprogram still running on VU1\n"); SysPrintf("Previous Microprogram still running on VU1\n");
if( VU0.VI[REG_VPU_STAT].UL & 0x100 ) { do {
do { Cpu->ExecuteVU1Block();
Cpu->ExecuteVU1Block(); } while(VU0.VI[REG_VPU_STAT].UL & 0x100);
} while(VU0.VI[REG_VPU_STAT].UL & 0x100);
}
} }
VUM_LOG("vu1ExecMicro %x\n", addr); VUM_LOG("vu1ExecMicro %x\n", addr);
VUM_LOG("vu1ExecMicro %x (count=%d)\n", addr, count++); VUM_LOG("vu1ExecMicro %x (count=%d)\n", addr, count++);
@ -161,7 +159,6 @@ void vu1ExecMicro(u32 addr)
if (addr != -1) VU1.VI[REG_TPC].UL = addr; if (addr != -1) VU1.VI[REG_TPC].UL = addr;
_vuExecMicroDebug(VU1); _vuExecMicroDebug(VU1);
//do { //do {
FreezeXMMRegs(1); FreezeXMMRegs(1);
Cpu->ExecuteVU1Block(); Cpu->ExecuteVU1Block();
@ -169,6 +166,12 @@ void vu1ExecMicro(u32 addr)
//} while(VU0.VI[REG_VPU_STAT].UL & 0x100); //} while(VU0.VI[REG_VPU_STAT].UL & 0x100);
// rec can call vu1ExecMicro // rec can call vu1ExecMicro
// VU1 isn't handled by branch tests right now, so this isn't needed.
// although maybe it should be? VU1 is updated in the intBranchTest, but not the
// recompiler one. Why? No clue. (air)
//if( VU1.VI[REG_VPU_STAT].UL & 0x1 )
// cpuSetNextBranchDelta( 256 );
} }
void _vu1ExecUpper(VURegs* VU, u32 *ptr) { void _vu1ExecUpper(VURegs* VU, u32 *ptr) {

View File

@ -55,19 +55,21 @@ _vuopinfo g_cop2info = {0, 0, 1, 1, 1, 0, 0};
#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) #define _Ftf_ ((cpuRegs.code >> 23) & 0x03)
#define _Cc_ (cpuRegs.code & 0x03) #define _Cc_ (cpuRegs.code & 0x03)
#define REC_COP2_FUNC(f, delreg) \ void recCop2BranchCall( void (*func)() )
void f(); \ {
void rec##f() { \ X86_32CODE(SetFPUstate());
SysPrintf("cop2 "#f" called\n"); \ recBranchCall( func );
X86_32CODE(SetFPUstate()); \ _freeX86regs();
MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \
MOV32ItoM((uptr)&cpuRegs.pc, pc); \
iFlushCall(FLUSH_NOCONST); \
CALLFunc((uptr)f); \
_freeX86regs(); \
branch = 2; \
} }
#define REC_COP2_FUNC( f ) \
void f(); \
void rec##f() \
{ \
SysPrintf("Warning > cop2 "#f" called\n"); \
recCop2BranchCall( f ); \
}
#define INTERPRETATE_COP2_FUNC(f) \ #define INTERPRETATE_COP2_FUNC(f) \
void recV##f() { \ void recV##f() { \
MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \ MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \
@ -250,9 +252,6 @@ static void recCFC2()
static void recCTC2() static void recCTC2()
{ {
#ifdef __x86_64__
int mmreg;
#endif
if (cpuRegs.code & 1) { if (cpuRegs.code & 1) {
#ifdef __x86_64__ #ifdef __x86_64__
iFlushCall(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86); iFlushCall(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86);
@ -289,49 +288,37 @@ static void recCTC2()
assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 && assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 &&
_checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 ); _checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 );
// Execute VU1 Micro SubRoutine
_callFunctionArg1((uptr)FreezeXMMRegs_, MEM_CONSTTAG, 1);
_callFunctionArg1((uptr)vu1ExecMicro, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]&0xffff);
_callFunctionArg1((uptr)FreezeXMMRegs_, MEM_CONSTTAG, 0);
#else #else
iFlushCall(FLUSH_NOCONST);// since CALLFunc iFlushCall(FLUSH_NOCONST);// since CALLFunc
assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 && assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 &&
_checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 ); _checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 );
#endif
// Execute VU1 Micro SubRoutine // Execute VU1 Micro SubRoutine
_callFunctionArg1((uptr)vu1ExecMicro, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]&0xffff); _callFunctionArg1((uptr)vu1ExecMicro, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]&0xffff);
#endif
break; break;
default: default:
{
if( _Fs_ < 16 ) if( _Fs_ < 16 )
assert( (g_cpuConstRegs[_Rt_].UL[0]&0xffff0000)==0); assert( (g_cpuConstRegs[_Rt_].UL[0]&0xffff0000)==0);
#ifdef __x86_64__
mmreg = _checkX86reg(X86TYPE_VI, _Fs_, MODE_WRITE);
if( mmreg >= 0 ) MOV32ItoR(mmreg, g_cpuConstRegs[_Rt_].UL[0]);
// a lot of games have vu0 spinning on some integer // a lot of games have vu0 spinning on some integer
// then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck) // then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck)
iFlushCall(FLUSH_FREE_TEMPX86|FLUSH_FREE_VU0);
_callFunctionArg1((uptr)FreezeXMMRegs_, MEM_CONSTTAG, 1); #ifdef __x86_64__
CALLFunc((uptr)Cpu->ExecuteVU0Block); int mmreg = _checkX86reg(X86TYPE_VI, _Fs_, MODE_WRITE);
_callFunctionArg1((uptr)FreezeXMMRegs_, MEM_CONSTTAG, 0); if( mmreg >= 0 ) MOV32ItoR(mmreg, g_cpuConstRegs[_Rt_].UL[0]);
iFlushCall(FLUSH_FREE_TEMPX86|FLUSH_FREE_VU0);
#else #else
MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]); MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]);
// fixme: this code should issue a BranchTest instead of calling the VU0Block directly.
// It would be a lot safter and would get rid of the 64 bit mess above too.
// a lot of games have vu0 spinning on some integer
// then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck)
iFlushCall(FLUSH_NOCONST); iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)Cpu->ExecuteVU0Block);
//SysPrintf( "Recompiler Warning > Unstable VU0 opcode used." );
#endif #endif
CALLFunc((uptr)Cpu->ExecuteVU0Block);
// fixme: if the VU0 stat&1 is still enabled, then we should probably set a cpuBranchTest
// for 128 cycles from now. It would be the safest thing to do to make sure the VU0
// responds in a timely matter to the game's register write.
break; break;
}
} }
} }
else else
@ -613,10 +600,10 @@ void _cop2AnalyzeOp(EEINST* pinst, int dostalls)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// BC2: Instructions // BC2: Instructions
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
REC_COP2_FUNC(BC2F, 0); REC_COP2_FUNC(BC2F);
REC_COP2_FUNC(BC2T, 0); REC_COP2_FUNC(BC2T);
REC_COP2_FUNC(BC2FL, 0); REC_COP2_FUNC(BC2FL);
REC_COP2_FUNC(BC2TL, 0); REC_COP2_FUNC(BC2TL);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Special1 instructions // Special1 instructions