- Working on getting some old code working again which allows comparison between mVU and sVU program results.

- Have the compiler explicitly pack the VU reg structs since we rely on this.
- Various minor changes.


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3407 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-07-07 05:59:25 +00:00
parent b53a92e019
commit 3649a9e226
18 changed files with 372 additions and 103 deletions

View File

@ -383,6 +383,15 @@ void SysCoreAllocations::SelectCpuProviders() const
CpuVU1 = EmuConfig.Cpu.Recompiler.UseMicroVU1 ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->superVU1; CpuVU1 = EmuConfig.Cpu.Recompiler.UseMicroVU1 ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->superVU1;
} }
// This is a semi-hacky function for convenience
BaseVUmicroCPU* SysCoreAllocations::getVUprovider(int whichProvider, int vuIndex) const {
switch (whichProvider) {
case 0: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->interpVU1 : (BaseVUmicroCPU*)CpuProviders->interpVU0;
case 1: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->superVU1 : (BaseVUmicroCPU*)CpuProviders->superVU0;
case 2: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->microVU1 : (BaseVUmicroCPU*)CpuProviders->microVU0;
}
return NULL;
}
// Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition. // Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
// This can be called at any time outside the context of a Cpu->Execute() block without // This can be called at any time outside the context of a Cpu->Execute() block without

View File

@ -22,6 +22,7 @@
#include "CDVD/CDVDaccess.h" #include "CDVD/CDVDaccess.h"
typedef SafeArray<u8> VmStateBuffer; typedef SafeArray<u8> VmStateBuffer;
class BaseVUmicroCPU;
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// SysCoreAllocations class // SysCoreAllocations class
@ -39,6 +40,7 @@ public:
virtual ~SysCoreAllocations() throw(); virtual ~SysCoreAllocations() throw();
void SelectCpuProviders() const; void SelectCpuProviders() const;
BaseVUmicroCPU* getVUprovider(int whichProvider, int vuIndex) const;
bool HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const; bool HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const;

View File

@ -16,6 +16,10 @@
#pragma once #pragma once
#include "Vif.h" #include "Vif.h"
#ifdef _MSC_VER // Most of the structs here should be packed
# pragma pack(1)
#endif
enum VURegFlags enum VURegFlags
{ {
REG_STATUS_FLAG = 16, REG_STATUS_FLAG = 16,
@ -62,7 +66,7 @@ union VECTOR {
s16 SS[8]; s16 SS[8];
u8 UC[16]; u8 UC[16];
s8 SC[16]; s8 SC[16];
}; } __packed;
struct REG_VI { struct REG_VI {
union { union {
@ -76,7 +80,7 @@ struct REG_VI {
}; };
u32 padding[3]; // needs padding to make them 128bit; VU0 maps VU1's VI regs as 128bits to addr 0x4xx0 in u32 padding[3]; // needs padding to make them 128bit; VU0 maps VU1's VI regs as 128bits to addr 0x4xx0 in
// VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes) // VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes)
}; } __packed;
//#define VUFLAG_BREAKONMFLAG 0x00000001 //#define VUFLAG_BREAKONMFLAG 0x00000001
#define VUFLAG_MFLAGSET 0x00000002 #define VUFLAG_MFLAGSET 0x00000002
@ -152,7 +156,8 @@ struct VURegs {
, Micro( NULL ) , Micro( NULL )
{ {
} }
}; } __packed;
enum VUPipeState enum VUPipeState
{ {
VUPIPE_NONE = 0, VUPIPE_NONE = 0,
@ -177,6 +182,10 @@ struct _VURegsNum {
int cycles; int cycles;
}; };
#ifdef _MSC_VER // Restore to default pack alignment
# pragma pack()
#endif
extern VURegs* g_pVU1; extern VURegs* g_pVU1;
extern __aligned16 VURegs VU0; extern __aligned16 VURegs VU0;

View File

@ -671,6 +671,10 @@
<Filter <Filter
Name="Super VU" Name="Super VU"
> >
<File
RelativePath="..\..\x86\sVU_Compare.h"
>
</File>
<File <File
RelativePath="..\..\x86\sVU_Debug.h" RelativePath="..\..\x86\sVU_Debug.h"
> >

View File

@ -15,7 +15,7 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#if 0
#include "Common.h" #include "Common.h"
#include "iR5900.h" #include "iR5900.h"
#include "VUmicro.h" #include "VUmicro.h"
@ -24,8 +24,6 @@
#define useMVU1 CHECK_MICROVU1 #define useMVU1 CHECK_MICROVU1
int mVUdebugNow = 0;
//#define DEBUG_COMPARE // Run sVU or mVU and print results //#define DEBUG_COMPARE // Run sVU or mVU and print results
//#define DEBUG_COMPARE2 // Runs both VU recs and breaks when results differ //#define DEBUG_COMPARE2 // Runs both VU recs and breaks when results differ
@ -285,3 +283,5 @@ namespace VU1micro
} }
}*/ }*/
#endif #endif
#endif

View File

@ -115,6 +115,10 @@ _f void mVUreset(mV) {
//memset(&mVU->prog, 0, sizeof(mVU->prog)); //memset(&mVU->prog, 0, sizeof(mVU->prog));
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState));
if (IsDevBuild) { // Release builds shouldn't need this
memset(mVU->cache, 0xcc, mVU->cacheSize);
}
// Program Variables // Program Variables
mVU->prog.cleared = 1; mVU->prog.cleared = 1;
mVU->prog.isSame = -1; mVU->prog.isSame = -1;
@ -163,12 +167,9 @@ void mVUresizeCache(mV, u32 size) {
if (size >= (u32)mVUcacheMaxSize) { if (size >= (u32)mVUcacheMaxSize) {
if (mVU->cacheSize==mVUcacheMaxSize) { if (mVU->cacheSize==mVUcacheMaxSize) {
// We can't grow the rec any larger, so just reset it and start over.
// Crap! We can't grow the rec any larger, so just reset it and start over.
//(if we don't reset, the rec will eventually crash) //(if we don't reset, the rec will eventually crash)
Console.WriteLn(Color_Magenta, "microVU%d: Cannot grow cache, size limit reached! [%dmb]. Resetting rec.", mVU->index, mVU->cacheSize/_1mb); Console.WriteLn(Color_Magenta, "microVU%d: Cannot grow cache, size limit reached! [%dmb]. Resetting rec.", mVU->index, mVU->cacheSize/_1mb);
memset(mVU->cache, 0xcc, mVU->cacheSize);
mVUreset(mVU); mVUreset(mVU);
return; return;
} }
@ -179,7 +180,7 @@ void mVUresizeCache(mV, u32 size) {
u8* cache = SysMmapEx(NULL, size, 0, (mVU->index ? "Micro VU1 RecCache" : "Micro VU0 RecCache")); u8* cache = SysMmapEx(NULL, size, 0, (mVU->index ? "Micro VU1 RecCache" : "Micro VU0 RecCache"));
if(!cache && !mVU->cache) throw Exception::OutOfMemory( wxsFormat( L"Micro VU%d recompiled code cache", mVU->index) ); if(!cache && !mVU->cache) throw Exception::OutOfMemory( wxsFormat( L"Micro VU%d recompiled code cache", mVU->index) );
if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); return; } if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); mVUreset(mVU); return; }
if (mVU->cache) { if (mVU->cache) {
HostSys::Munmap(mVU->cache, mVU->cacheSize); HostSys::Munmap(mVU->cache, mVU->cacheSize);
ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec"); ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec");
@ -187,7 +188,6 @@ void mVUresizeCache(mV, u32 size) {
mVU->cache = cache; mVU->cache = cache;
mVU->cacheSize = size; mVU->cacheSize = size;
memset(mVU->cache, 0xcc, mVU->cacheSize);
ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize); ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize);
mVUreset(mVU); mVUreset(mVU);
} }

View File

@ -203,7 +203,7 @@ extern __aligned16 microVU microVU0;
extern __aligned16 microVU microVU1; extern __aligned16 microVU microVU1;
// Debug Helper // Debug Helper
extern int mVUdebugNow; int mVUdebugNow = 0;
// Main Functions // Main Functions
_f void mVUinit(VURegs*, int); _f void mVUinit(VURegs*, int);

View File

@ -149,8 +149,8 @@ _f void mVUallocVIa(mV, x32 GPRreg, int _reg_, bool signext = false)
_f void mVUallocVIb(mV, x32 GPRreg, int _reg_) _f void mVUallocVIb(mV, x32 GPRreg, int _reg_)
{ {
if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch) if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch)
xMOVZX(edx, ptr16[&mVU->regs->VI[_reg_].UL]); xMOVZX(gprT3, ptr16[&mVU->regs->VI[_reg_].UL]);
xMOV(ptr32[&mVU->VIbackup], edx); xMOV (ptr32[&mVU->VIbackup], gprT3);
} }
if (_reg_ == 0) { return; } if (_reg_ == 0) { return; }
else if (_reg_ < 16) { xMOV(ptr16[&mVU->regs->VI[_reg_].UL], xRegister16(GPRreg.Id)); } else if (_reg_ < 16) { xMOV(ptr16[&mVU->regs->VI[_reg_].UL], xRegister16(GPRreg.Id)); }

View File

@ -66,7 +66,7 @@ _f void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
#if 1 // CHECK_MACROVU0 - Always on now #if 1 // CHECK_MACROVU0 - Always on now
xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus)); xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus));
#else #else
mVUallocSFLAGc(gprT1, fStatus); mVUallocSFLAGc(gprT1, gprT2, fStatus);
xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], gprT1); xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], gprT1);
#endif #endif
mVUallocMFLAGa(mVU, gprT1, fMac); mVUallocMFLAGa(mVU, gprT1, fMac);

View File

@ -134,27 +134,25 @@ void doIbit(mV) {
void doSwapOp(mV) { void doSwapOp(mV) {
if (mVUinfo.backupVF && !mVUlow.noWriteVF) { if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC); DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC);
xmm t2 = mVU->regAlloc->allocReg();
{
xmm t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg); xmm t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
xmm t2 = mVU->regAlloc->allocReg();
xMOVAPS(t2, t1); xMOVAPS(t2, t1);
mVU->regAlloc->clearNeeded(t1); mVU->regAlloc->clearNeeded(t1);
}
mVUopL(mVU, 1); mVUopL(mVU, 1);
{
xmm t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0); t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
xXOR.PS(t2, t1); xXOR.PS(t2, t1);
xXOR.PS(t1, t2); xXOR.PS(t1, t2);
xXOR.PS(t2, t1); xXOR.PS(t2, t1);
mVU->regAlloc->clearNeeded(t1); mVU->regAlloc->clearNeeded(t1);
}
incPC(1); incPC(1);
doUpperOp(); doUpperOp();
{
xmm t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf); t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
xMOVAPS(t1, t2); xMOVAPS(t1, t2);
mVU->regAlloc->clearNeeded(t1); mVU->regAlloc->clearNeeded(t1);
}
mVU->regAlloc->clearNeeded(t2); mVU->regAlloc->clearNeeded(t2);
} }
else { mVUopL(mVU, 1); incPC(1); doUpperOp(); } else { mVUopL(mVU, 1); incPC(1); doUpperOp(); }
@ -171,7 +169,7 @@ _f void mVUcheckBadOp(mV) {
// Prints msg when exiting block early if 1st op was a bad opcode (Dawn of Mana Level 2) // Prints msg when exiting block early if 1st op was a bad opcode (Dawn of Mana Level 2)
_f void handleBadOp(mV, int count) { _f void handleBadOp(mV, int count) {
if (mVUinfo.isBadOp && count == 0) { if (mVUinfo.isBadOp && count == 0) {
xMOV(ecx, (uptr)mVU); xMOV(gprT2, (uptr)mVU);
if (!isVU1) xCALL(mVUbadOp0); if (!isVU1) xCALL(mVUbadOp0);
else xCALL(mVUbadOp1); else xCALL(mVUbadOp1);
} }
@ -312,21 +310,36 @@ _f void mVUsavePipelineState(microVU* mVU) {
} }
} }
// Prints Start/End PC of blocks executed, for debugging...
void mVUdebugPrintBlocks(microVU* mVU, bool isEndPC) {
if (mVUdebugNow) {
xMOV(gprT2, xPC);
if (isEndPC) xCALL(mVUprintPC2);
else xCALL(mVUprintPC1);
}
}
// Test cycles to see if we need to exit-early...
void mVUtestCycles(microVU* mVU) { void mVUtestCycles(microVU* mVU) {
//u32* vu0jmp;
iPC = mVUstartPC; iPC = mVUstartPC;
mVUdebugNOW(0);
if (doEarlyExit(mVU)) { if (doEarlyExit(mVU)) {
xCMP(ptr32[&mVU->cycles], 0); xCMP(ptr32[&mVU->cycles], 0);
xForwardJG32 skip; xForwardJG32 skip;
// FIXME: uh... actually kind of a pain with xForwardJump if (isVU0) {
//if (!isVU1) { TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); vu0jmp = JZ32(0); } // TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET);
xMOV(ecx, (uptr)mVU); // xFowardJZ32 vu0jmp;
if (isVU1) xCALL(mVUwarning1); // xMOV(gprT2, (uptr)mVU);
//else xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation // xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
mVUsavePipelineState(mVU); mVUsavePipelineState(mVU);
mVUendProgram(mVU, NULL, 0); mVUendProgram(mVU, NULL, 0);
//if (!isVU1) vu0jmp.SetTarget(); // vu0jmp.SetTarget();
}
else {
xMOV(gprT2, (uptr)mVU);
xCALL(mVUwarning1);
mVUsavePipelineState(mVU);
mVUendProgram(mVU, NULL, 0);
}
skip.SetTarget(); skip.SetTarget();
} }
xSUB(ptr32[&mVU->cycles], mVUcycles); xSUB(ptr32[&mVU->cycles], mVUcycles);
@ -408,6 +421,7 @@ _r void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
mVUsetFlags(mVU, mFC); // Sets Up Flag instances mVUsetFlags(mVU, mFC); // Sets Up Flag instances
mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking
mVUdebugPrintBlocks(mVU,0);// Prints Start/End PC of blocks executed, for debugging...
mVUtestCycles(mVU); // Update VU Cycles and Exit Early if Necessary mVUtestCycles(mVU); // Update VU Cycles and Exit Early if Necessary
// Second Pass // Second Pass
@ -427,7 +441,7 @@ _r void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
else if (!mVUinfo.isBdelay) { incPC(1); } else if (!mVUinfo.isBdelay) { incPC(1); }
else { else {
mVUsetupRange(mVU, xPC, 0); mVUsetupRange(mVU, xPC, 0);
mVUdebugNOW(1); mVUdebugPrintBlocks(mVU,1);
incPC(-3); // Go back to branch opcode incPC(-3); // Go back to branch opcode
switch (mVUlow.branch) { switch (mVUlow.branch) {
case 1: case 2: normBranch(mVU, mFC); return thisPtr; // B/BAL case 1: case 2: normBranch(mVU, mFC); return thisPtr; // B/BAL

View File

@ -53,11 +53,11 @@ void mVUdispatcherA(mV) {
xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_MAC_FLAG].UL]); xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_MAC_FLAG].UL]);
xSHUF.PS(xmmT1, xmmT1, 0); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU->macFlag[0]], xmmT1); xMOVAPS(ptr128[mVU->macFlag], xmmT1);
xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_CLIP_FLAG].UL]); xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_CLIP_FLAG].UL]);
xSHUF.PS(xmmT1, xmmT1, 0); xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS(ptr128[&mVU->clipFlag[0]], xmmT1); xMOVAPS(ptr128[mVU->clipFlag], xmmT1);
xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_P].UL]); xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_P].UL]);
xMOVAPS(xmmPQ, ptr128[&mVU->regs->VI[REG_Q].UL]); xMOVAPS(xmmPQ, ptr128[&mVU->regs->VI[REG_Q].UL]);

View File

@ -87,6 +87,7 @@ typedef xRegister32 x32;
#define isCOP2 (mVU->cop2 != 0) #define isCOP2 (mVU->cop2 != 0)
#define isVU1 (mVU->index != 0) #define isVU1 (mVU->index != 0)
#define isVU0 (mVU->index == 0)
#define getIndex (isVU1 ? 1 : 0) #define getIndex (isVU1 ? 1 : 0)
#define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16) #define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16)
#define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12))) #define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12)))
@ -296,14 +297,6 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
} \ } \
} }
#define mVUdebugNOW(isEndPC) { \
if (mVUdebugNow) { \
xMOV(gprT2, xPC); \
if (isEndPC) { xCALL(mVUprintPC2); } \
else { xCALL(mVUprintPC1); } \
} \
}
void mVUmergeRegs(xmm dest, xmm src, int xyzw, bool modXYZW=false); void mVUmergeRegs(xmm dest, xmm src, int xyzw, bool modXYZW=false);
void mVUsaveReg(xmm reg, xAddressVoid ptr, int xyzw, bool modXYZW); void mVUsaveReg(xmm reg, xAddressVoid ptr, int xyzw, bool modXYZW);
void mVUloadReg(xmm reg, xAddressVoid ptr, int xyzw); void mVUloadReg(xmm reg, xAddressVoid ptr, int xyzw);

View File

@ -22,10 +22,10 @@
void mVUunpack_xyzw(xmm dstreg, xmm srcreg, int xyzw) void mVUunpack_xyzw(xmm dstreg, xmm srcreg, int xyzw)
{ {
switch ( xyzw ) { switch ( xyzw ) {
case 0: xPSHUF.D(dstreg, srcreg, 0x00); break; case 0: xPSHUF.D(dstreg, srcreg, 0x00); break; // XXXX
case 1: xPSHUF.D(dstreg, srcreg, 0x55); break; case 1: xPSHUF.D(dstreg, srcreg, 0x55); break; // YYYY
case 2: xPSHUF.D(dstreg, srcreg, 0xaa); break; case 2: xPSHUF.D(dstreg, srcreg, 0xaa); break; // ZZZZ
case 3: xPSHUF.D(dstreg, srcreg, 0xff); break; case 3: xPSHUF.D(dstreg, srcreg, 0xff); break; // WWWW
} }
} }
@ -236,13 +236,13 @@ _f void mVUaddrFix(mV, x32 gprReg)
_f void mVUbackupRegs(microVU* mVU) _f void mVUbackupRegs(microVU* mVU)
{ {
mVU->regAlloc->flushAll(); mVU->regAlloc->flushAll();
xMOVAPS(ptr128[&mVU->xmmPQb[0]], xmmPQ); xMOVAPS(ptr128[mVU->xmmPQb], xmmPQ);
} }
// Restore Volatile Regs // Restore Volatile Regs
_f void mVUrestoreRegs(microVU* mVU) _f void mVUrestoreRegs(microVU* mVU)
{ {
xMOVAPS(xmmPQ, ptr128[&mVU->xmmPQb[0]]); xMOVAPS(xmmPQ, ptr128[mVU->xmmPQb]);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------

View File

@ -24,29 +24,31 @@
#define SHIFT_XYZW(gprReg) { if (_XYZW_SS && modXYZW && !_W) { xSHL(gprReg, ADD_XYZW); } } #define SHIFT_XYZW(gprReg) { if (_XYZW_SS && modXYZW && !_W) { xSHL(gprReg, ADD_XYZW); } }
// Note: If modXYZW is true, then it adjusts XYZW for Single Scalar operations // Note: If modXYZW is true, then it adjusts XYZW for Single Scalar operations
static void mVUupdateFlags(mV, xmm reg, xmm regT1in = xEmptyReg, xmm regT2 = xEmptyReg, bool modXYZW = 1) { static void mVUupdateFlags(mV, xmm reg, xmm regT1 = xEmptyReg, xmm regT2 = xEmptyReg, bool modXYZW = 1) {
x32 mReg = gprT1; x32 mReg = gprT1, sReg = getFlagReg(sFLAG.write);
bool regT2b = false; bool regT1b = false, regT2b = false;
static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}; static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag); //SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; } if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
xmm regT1 = regT1in.IsEmpty() ? mVU->regAlloc->allocReg() : regT1in; if (regT1.IsEmpty()) {
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) regT1 = mVU->regAlloc->allocReg();
{ regT1b = true;
if (regT2.IsEmpty()) }
{
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) {
if (regT2.IsEmpty()) {
regT2 = mVU->regAlloc->allocReg(); regT2 = mVU->regAlloc->allocReg();
regT2b = true; regT2b = true;
} }
xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw
} }
else else regT2 = reg;
regT2 = reg;
if (sFLAG.doFlag) { if (sFLAG.doFlag) {
mVUallocSFLAGa(getFlagReg(sFLAG.write), sFLAG.lastWrite); // Get Prev Status Flag mVUallocSFLAGa(sReg, sFLAG.lastWrite); // Get Prev Status Flag
if (sFLAG.doNonSticky) xAND(getFlagReg(sFLAG.write), 0xfffc00ff); // Clear O,U,S,Z flags if (sFLAG.doNonSticky) xAND(sReg, 0xfffc00ff); // Clear O,U,S,Z flags
} }
//-------------------------Check for Signed flags------------------------------ //-------------------------Check for Signed flags------------------------------
@ -69,13 +71,13 @@ static void mVUupdateFlags(mV, xmm reg, xmm regT1in = xEmptyReg, xmm regT2 = xEm
if (mFLAG.doFlag) mVUallocMFLAGb(mVU, mReg, mFLAG.write); // Set Mac Flag if (mFLAG.doFlag) mVUallocMFLAGb(mVU, mReg, mFLAG.write); // Set Mac Flag
if (sFLAG.doFlag) { if (sFLAG.doFlag) {
xOR(getFlagReg(sFLAG.write), mReg); xOR(sReg, mReg);
if (sFLAG.doNonSticky) { if (sFLAG.doNonSticky) {
xSHL(mReg, 8); xSHL(mReg, 8);
xOR(getFlagReg(sFLAG.write), mReg); xOR (sReg, mReg);
} }
} }
if (regT1 != regT1in) mVU->regAlloc->clearNeeded(regT1); if (regT1b) mVU->regAlloc->clearNeeded(regT1);
if (regT2b) mVU->regAlloc->clearNeeded(regT2); if (regT2b) mVU->regAlloc->clearNeeded(regT2);
} }
@ -350,7 +352,7 @@ mVUop(mVU_OPMSUB) {
} }
// FTOI0/FTIO4/FTIO12/FTIO15 Opcodes // FTOI0/FTIO4/FTIO12/FTIO15 Opcodes
static void mVU_FTOIx(mP, const float (*addr)[4], const char* opName) { static void mVU_FTOIx(mP, const float* addr, const char* opName) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
if (!_Ft_) return; if (!_Ft_) return;
@ -377,7 +379,7 @@ static void mVU_FTOIx(mP, const float (*addr)[4], const char* opName) {
} }
// ITOF0/ITOF4/ITOF12/ITOF15 Opcodes // ITOF0/ITOF4/ITOF12/ITOF15 Opcodes
static void mVU_ITOFx(mP, const float (*addr)[4], const char* opName) { static void mVU_ITOFx(mP, const float* addr, const char* opName) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
if (!_Ft_) return; if (!_Ft_) return;
@ -404,9 +406,9 @@ mVUop(mVU_CLIP) {
mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite); mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite);
xSHL(gprT1, 6); xSHL(gprT1, 6);
xAND.PS(Ft, ptr128[&mVUglob.absclip[0]]); xAND.PS(Ft, ptr128[mVUglob.absclip]);
xMOVAPS(t1, Ft); xMOVAPS(t1, Ft);
xPOR(t1, ptr128[&mVUglob.signbit[0]]); xPOR(t1, ptr128[mVUglob.signbit]);
xCMPNLE.PS(t1, Fs); // -w, -z, -y, -x xCMPNLE.PS(t1, Fs); // -w, -z, -y, -x
xCMPLT.PS(Ft, Fs); // +w, +z, +y, +x xCMPLT.PS(Ft, Fs); // +w, +z, +y, +x
@ -520,11 +522,11 @@ mVUop(mVU_MINIy) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIy", 0); }
mVUop(mVU_MINIz) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIz", 0); } mVUop(mVU_MINIz) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIz", 0); }
mVUop(mVU_MINIw) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIw", 0); } mVUop(mVU_MINIw) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIw", 0); }
mVUop(mVU_FTOI0) { mVU_FTOIx(mX, NULL, "FTOI0"); } mVUop(mVU_FTOI0) { mVU_FTOIx(mX, NULL, "FTOI0"); }
mVUop(mVU_FTOI4) { mVU_FTOIx(mX, &mVUglob.FTOI_4, "FTOI4"); } mVUop(mVU_FTOI4) { mVU_FTOIx(mX, mVUglob.FTOI_4, "FTOI4"); }
mVUop(mVU_FTOI12) { mVU_FTOIx(mX, &mVUglob.FTOI_12, "FTOI12"); } mVUop(mVU_FTOI12) { mVU_FTOIx(mX, mVUglob.FTOI_12, "FTOI12"); }
mVUop(mVU_FTOI15) { mVU_FTOIx(mX, &mVUglob.FTOI_15, "FTOI15"); } mVUop(mVU_FTOI15) { mVU_FTOIx(mX, mVUglob.FTOI_15, "FTOI15"); }
mVUop(mVU_ITOF0) { mVU_ITOFx(mX, NULL, "ITOF0"); } mVUop(mVU_ITOF0) { mVU_ITOFx(mX, NULL, "ITOF0"); }
mVUop(mVU_ITOF4) { mVU_ITOFx(mX, &mVUglob.ITOF_4, "ITOF4"); } mVUop(mVU_ITOF4) { mVU_ITOFx(mX, mVUglob.ITOF_4, "ITOF4"); }
mVUop(mVU_ITOF12) { mVU_ITOFx(mX, &mVUglob.ITOF_12, "ITOF12"); } mVUop(mVU_ITOF12) { mVU_ITOFx(mX, mVUglob.ITOF_12, "ITOF12"); }
mVUop(mVU_ITOF15) { mVU_ITOFx(mX, &mVUglob.ITOF_15, "ITOF15"); } mVUop(mVU_ITOF15) { mVU_ITOFx(mX, mVUglob.ITOF_15, "ITOF15"); }
mVUop(mVU_NOP) { pass3 { mVUlog("NOP"); } } mVUop(mVU_NOP) { pass3 { mVUlog("NOP"); } }

232
pcsx2/x86/sVU_Compare.h Normal file
View File

@ -0,0 +1,232 @@
#pragma once
extern BaseVUmicroCPU* getVUprovider(int whichProvider, int vuIndex);
SysCoreAllocations& GetSysCoreAlloc();
void runSVU1(u32 cycles) {
do { // while loop needed since not always will return finished
SuperVUExecuteProgram(VU1.VI[REG_TPC].UL & 0x3ff8, 1);
} while( VU0.VI[REG_VPU_STAT].UL&0x100 );
}
void runMVU1(u32 cycles) {
GetSysCoreAlloc().getVUprovider(2, 1)->Execute(cycles);
}
void clearSVU1(u32 Addr, u32 Size) {
SuperVUClear(Addr, Size, 1);
}
void clearMVU1(u32 Addr, u32 Size) {
GetSysCoreAlloc().getVUprovider(2, 1)->Clear(Addr, Size);
}
void recSuperVU1::Clear(u32 Addr, u32 Size) {
clearSVU1(Addr, Size);
clearMVU1(Addr, Size);
}
void resetSVU1() {
GetSysCoreAlloc().getVUprovider(1, 1)->Reset();
}
void resetMVU1() {
GetSysCoreAlloc().getVUprovider(2, 1)->Reset();
}
extern int mVUdebugNow;
static u32 runCount = 0;
__aligned16 u8 backVUregs[sizeof(VURegs)];
__aligned16 u8 cmpVUregs [sizeof(VURegs)];
__aligned16 u8 backVUmem [0x4000];
__aligned16 u8 cmpVUmem [0x4000];
#define VU3 (*(VURegs*)cmpVUregs)
#define fABS(aInt) (aInt & 0x7fffffff)
//#define cmpU(uA, uB) (fABS(uA) != fABS(uB))
#define cmpU(uA, uB) (uA != uB)
#define cmpA Console.Error
#define cmpB Console.WriteLn
#define cmpPrint(cond) { \
if (cond) { \
cmpA("%s", str1); \
cmpA("%s", str2); \
/*mVUdebugNow = 1;*/\
} \
else { \
cmpB("%s", str1); \
cmpB("%s", str2); \
} \
}
//#define DEBUG_COMPARE // Run sVU or mVU and print results
//#define DEBUG_COMPARE2 // Runs both VU recs and breaks when results differ
#ifdef DEBUG_COMPARE
static int runAmount = 0;
void VUtestPause() {
runAmount++;
if (runAmount < 654) return;
if (useMVU1) SysPrintf("Micro VU - Pass %d\n", runAmount);
else SysPrintf("Super VU - Pass %d\n", runAmount);
for (int i = 0; i < 32; i++) {
SysPrintf("VF%02d = {%f, %f, %f, %f}\n", i, VU1.VF[i].F[0], VU1.VF[i].F[1], VU1.VF[i].F[2], VU1.VF[i].F[3]);
}
SysPrintf("ACC = {%f, %f, %f, %f}\n", VU1.ACC.F[0], VU1.ACC.F[1], VU1.ACC.F[2], VU1.ACC.F[3]);
for (int i = 0; i < 16; i++) {
SysPrintf("VI%02d = % 8d ($%08x)\n", i, (s16)VU1.VI[i].UL, (s16)VU1.VI[i].UL);
}
SysPrintf("Stat = % 8d ($%08x)\n", (s16)VU1.VI[REG_STATUS_FLAG].UL, (s16)VU1.VI[REG_STATUS_FLAG].UL);
SysPrintf("MAC = % 8d ($%08x)\n", (s16)VU1.VI[REG_MAC_FLAG].UL, (s16)VU1.VI[REG_MAC_FLAG].UL);
SysPrintf("CLIP = % 8d ($%08x)\n", (s16)VU1.VI[REG_CLIP_FLAG].UL, (s16)VU1.VI[REG_CLIP_FLAG].UL);
SysPrintf("Q-reg = %f ($%08x)\n", VU1.VI[REG_Q].F, (s32)VU1.VI[REG_Q].UL);
SysPrintf("P-reg = %f ($%08x)\n", VU1.VI[REG_P].F, (s32)VU1.VI[REG_P].UL);
SysPrintf("I-reg = %f ($%08x)\n", VU1.VI[REG_I].F, (s32)VU1.VI[REG_I].UL);
SysPrintf("_Stat = % 8d ($%08x)\n", (s16)VU1.statusflag, (s16)VU1.statusflag);
SysPrintf("_MAC = % 8d ($%08x)\n", (s16)VU1.macflag, (s16)VU1.macflag);
SysPrintf("_CLIP = % 8d ($%08x)\n", (s16)VU1.clipflag, (s16)VU1.clipflag);
u32 j = 0;
for (int i = 0; i < (0x4000 / 4); i++) {
j ^= ((u32*)(VU1.Mem))[i];
}
SysPrintf("VU Mem CRC = 0x%08x\n", j);
SysPrintf("EndPC = 0x%04x\n", VU1.VI[REG_TPC].UL);
// ... wtf?? --air
for (int i = 0; i < 10000000; i++) {
Threading::Sleep(1000);
}
}
#else
void VUtestPause() {}
#endif
void recSuperVU1::Execute(u32 cycles) {
cycles = 0x7fffffff;
if((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { Console.Error("VU1 memory overflow!!: %x", VU1.VI[REG_TPC].UL); }
#ifdef DEBUG_COMPARE
SysPrintf("(%08d) StartPC = 0x%04x\n", runAmount, VU1.VI[REG_TPC].UL);
#endif
runCount++;
memcpy_const((u8*)backVUregs, (u8*)&VU1, sizeof(VURegs));
memcpy_const((u8*)backVUmem, (u8*) VU1.Mem, 0x4000);
runMVU1(cycles);
memcpy_const((u8*)cmpVUregs,(u8*)&VU1, sizeof(VURegs));
memcpy_const((u8*)cmpVUmem, (u8*)VU1.Mem, 0x4000);
memcpy_const((u8*)&VU1, (u8*)backVUregs, sizeof(VURegs));
memcpy_const((u8*)VU1.Mem, (u8*)backVUmem, 0x4000);
runSVU1(cycles);
if ((memcmp((u8*)cmpVUregs, (u8*)&VU1, (16*32) + (16*16))) || (memcmp((u8*)cmpVUmem, (u8*)VU1.Mem, 0x4000))) {
static char str1[1000];
static char str2[1000];
Console.WriteLn("\n\n");
Console.WriteLn("-----------------------------------------------\n");
Console.Warning("Problem Occurred!");
Console.WriteLn("-----------------------------------------------\n");
Console.WriteLn("runCount = %d\n", runCount);
Console.WriteLn("StartPC [%04x]\n", ((VURegs*)backVUregs)->VI[REG_TPC].UL);
Console.WriteLn("-----------------------------------------------\n\n");
Console.WriteLn("-----------------------------------------------\n");
Console.Warning("Micro VU / Super VU");
Console.WriteLn("-----------------------------------------------\n");
for (int i = 0; i < 32; i++) {
sprintf(str1, "VF%02d = {%f, %f, %f, %f}", i, VU3.VF[i].F[0], VU3.VF[i].F[1], VU3.VF[i].F[2], VU3.VF[i].F[3]);
sprintf(str2, "VF%02d = {%f, %f, %f, %f}", i, VU1.VF[i].F[0], VU1.VF[i].F[1], VU1.VF[i].F[2], VU1.VF[i].F[3]);
cmpPrint((cmpU(VU1.VF[i].UL[0], VU3.VF[i].UL[0]) || cmpU(VU1.VF[i].UL[1], VU3.VF[i].UL[1]) || cmpU(VU1.VF[i].UL[2], VU3.VF[i].UL[2]) || cmpU(VU1.VF[i].UL[3], VU3.VF[i].UL[3])));
}
sprintf(str1, "ACC = {%f, %f, %f, %f}", VU3.ACC.F[0], VU3.ACC.F[1], VU3.ACC.F[2], VU3.ACC.F[3]);
sprintf(str2, "ACC = {%f, %f, %f, %f}", VU1.ACC.F[0], VU1.ACC.F[1], VU1.ACC.F[2], VU1.ACC.F[3]);
cmpPrint((cmpU(VU1.ACC.UL[0], VU3.ACC.UL[0]) || cmpU(VU1.ACC.UL[1], VU3.ACC.UL[1]) || cmpU(VU1.ACC.UL[2], VU3.ACC.UL[2]) || cmpU(VU1.ACC.UL[3], VU3.ACC.UL[3])));
for (int i = 0; i < 16; i++) {
sprintf(str1, "VI%02d = % 8d ($%08x)", i, (s16)VU3.VI[i].UL, VU3.VI[i].UL);
sprintf(str2, "VI%02d = % 8d ($%08x)", i, (s16)VU1.VI[i].UL, VU1.VI[i].UL);
cmpPrint((VU1.VI[i].UL != VU3.VI[i].UL));
}
sprintf(str1, "Stat = % 8d ($%08x)", (s16)VU3.VI[REG_STATUS_FLAG].UL, VU3.VI[REG_STATUS_FLAG].UL);
sprintf(str2, "Stat = % 8d ($%08x)", (s16)VU1.VI[REG_STATUS_FLAG].UL, VU1.VI[REG_STATUS_FLAG].UL);
cmpPrint((VU1.VI[REG_STATUS_FLAG].UL != VU3.VI[REG_STATUS_FLAG].UL));
sprintf(str1, "MAC = % 8d ($%08x)", (s16)VU3.VI[REG_MAC_FLAG].UL, VU3.VI[REG_MAC_FLAG].UL);
sprintf(str2, "MAC = % 8d ($%08x)", (s16)VU1.VI[REG_MAC_FLAG].UL, VU1.VI[REG_MAC_FLAG].UL);
cmpPrint((VU1.VI[REG_MAC_FLAG].UL != VU3.VI[REG_MAC_FLAG].UL));
sprintf(str1, "CLIP = % 8d ($%08x)", (s16)VU3.VI[REG_CLIP_FLAG].UL, VU3.VI[REG_CLIP_FLAG].UL);
sprintf(str2, "CLIP = % 8d ($%08x)", (s16)VU1.VI[REG_CLIP_FLAG].UL, VU1.VI[REG_CLIP_FLAG].UL);
cmpPrint((VU1.VI[REG_CLIP_FLAG].UL != VU3.VI[REG_CLIP_FLAG].UL));
sprintf(str1, "Q-reg = %f ($%08x)", VU3.VI[REG_Q].F, VU3.VI[REG_Q].UL);
sprintf(str2, "Q-reg = %f ($%08x)", VU1.VI[REG_Q].F, VU1.VI[REG_Q].UL);
cmpPrint((VU1.VI[REG_Q].UL != VU3.VI[REG_Q].UL));
sprintf(str1, "P-reg = %f ($%08x)", VU3.VI[REG_P].F, VU3.VI[REG_P].UL);
sprintf(str2, "P-reg = %f ($%08x)", VU1.VI[REG_P].F, VU1.VI[REG_P].UL);
cmpPrint((VU1.VI[REG_P].UL != VU3.VI[REG_P].UL));
sprintf(str1, "I-reg = %f ($%08x)", VU3.VI[REG_I].F, VU3.VI[REG_I].UL);
sprintf(str2, "I-reg = %f ($%08x)", VU1.VI[REG_I].F, VU1.VI[REG_I].UL);
cmpPrint((VU1.VI[REG_I].UL != VU3.VI[REG_I].UL));
sprintf(str1, "_Stat = % 8d ($%08x)", (s16)VU3.statusflag, VU3.statusflag);
sprintf(str2, "_Stat = % 8d ($%08x)", (s16)VU1.statusflag, VU1.statusflag);
cmpPrint((VU1.statusflag != VU3.statusflag));
sprintf(str1, "_MAC = % 8d ($%08x)", (s16)VU3.macflag, VU3.macflag);
sprintf(str2, "_MAC = % 8d ($%08x)", (s16)VU1.macflag, VU1.macflag);
cmpPrint((VU1.macflag != VU3.macflag));
sprintf(str1, "_CLIP = % 8d ($%08x)", (s16)VU3.clipflag, VU3.clipflag);
sprintf(str2, "_CLIP = % 8d ($%08x)", (s16)VU1.clipflag, VU1.clipflag);
cmpPrint((VU1.clipflag != VU3.clipflag));
u32 j = 0;
u32 z = 0;
for (int i = 0; i < (0x4000 / 4); i++) {
j ^= ((u32*)(cmpVUmem))[i];
z ^= ((u32*)(VU1.Mem)) [i];
}
sprintf(str1, "VU Mem CRC = 0x%08x", j);
sprintf(str2, "VU Mem CRC = 0x%08x", z);
cmpPrint((j != z));
sprintf(str1, "EndPC = 0x%04x", VU3.VI[REG_TPC].UL);
sprintf(str2, "EndPC = 0x%04x", VU1.VI[REG_TPC].UL);
cmpPrint((VU1.VI[REG_TPC].UL != VU3.VI[REG_TPC].UL));
Console.WriteLn("-----------------------------------------------\n\n");
/*
if (mVUdebugNow) {
resetMVU1();
memcpy_const((u8*)&VU1, (u8*)backVUregs, sizeof(VURegs));
memcpy_const((u8*)VU1.Mem, (u8*)backVUmem, 0x4000);
runMVU1(cycles);
for (int i = 0; i < 10000000; i++) {
Sleep(1000);
}
}*/
}
//VUtestPause();
}

View File

@ -4670,6 +4670,9 @@ void recSuperVU1::Reset()
SuperVUReset( 1 ); SuperVUReset( 1 );
} }
#if 0
#include "sVU_Compare.h"
#else
void recSuperVU1::Execute(u32 cycles) void recSuperVU1::Execute(u32 cycles)
{ {
if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return; if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
@ -4690,3 +4693,4 @@ void recSuperVU1::Clear(u32 Addr, u32 Size)
{ {
SuperVUClear(Addr, Size, 1); SuperVUClear(Addr, Size, 1);
} }
#endif