mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
1b8cd7c055
commit
8ebcc4c442
|
@ -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) );
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue