- 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;
}
// 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.
// 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"
typedef SafeArray<u8> VmStateBuffer;
class BaseVUmicroCPU;
// --------------------------------------------------------------------------------------
// SysCoreAllocations class
@ -39,6 +40,7 @@ public:
virtual ~SysCoreAllocations() throw();
void SelectCpuProviders() const;
BaseVUmicroCPU* getVUprovider(int whichProvider, int vuIndex) const;
bool HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const;

View File

@ -16,6 +16,10 @@
#pragma once
#include "Vif.h"
#ifdef _MSC_VER // Most of the structs here should be packed
# pragma pack(1)
#endif
enum VURegFlags
{
REG_STATUS_FLAG = 16,
@ -62,7 +66,7 @@ union VECTOR {
s16 SS[8];
u8 UC[16];
s8 SC[16];
};
} __packed;
struct REG_VI {
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
// VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes)
};
} __packed;
//#define VUFLAG_BREAKONMFLAG 0x00000001
#define VUFLAG_MFLAGSET 0x00000002
@ -152,7 +156,8 @@ struct VURegs {
, Micro( NULL )
{
}
};
} __packed;
enum VUPipeState
{
VUPIPE_NONE = 0,
@ -177,6 +182,10 @@ struct _VURegsNum {
int cycles;
};
#ifdef _MSC_VER // Restore to default pack alignment
# pragma pack()
#endif
extern VURegs* g_pVU1;
extern __aligned16 VURegs VU0;

View File

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

View File

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

View File

@ -114,6 +114,10 @@ _f void mVUreset(mV) {
// Clear All Program Data
//memset(&mVU->prog, 0, sizeof(mVU->prog));
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
mVU->prog.cleared = 1;
@ -163,12 +167,9 @@ void mVUresizeCache(mV, u32 size) {
if (size >= (u32)mVUcacheMaxSize) {
if (mVU->cacheSize==mVUcacheMaxSize) {
// 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)
// 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)
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);
return;
}
@ -179,7 +180,7 @@ void mVUresizeCache(mV, u32 size) {
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) { 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) {
HostSys::Munmap(mVU->cache, mVU->cacheSize);
ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec");
@ -187,7 +188,6 @@ void mVUresizeCache(mV, u32 size) {
mVU->cache = cache;
mVU->cacheSize = size;
memset(mVU->cache, 0xcc, mVU->cacheSize);
ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize);
mVUreset(mVU);
}

View File

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

View File

@ -73,7 +73,7 @@ _f void mVUallocSFLAGc(x32 reg, x32 regT, int fInstance)
setBitSFLAG(reg, regT, 0x00f0, 0x0080); // SS Bit
xAND(regT, 0xffff0000); // DS/DI/OS/US/D/I/O/U Bits
xSHR(regT, 14);
xOR(reg, regT);
xOR (reg, regT);
}
// Denormalizes Status Flag
@ -149,8 +149,8 @@ _f void mVUallocVIa(mV, x32 GPRreg, int _reg_, bool signext = false)
_f void mVUallocVIb(mV, x32 GPRreg, int _reg_)
{
if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch)
xMOVZX(edx, ptr16[&mVU->regs->VI[_reg_].UL]);
xMOV(ptr32[&mVU->VIbackup], edx);
xMOVZX(gprT3, ptr16[&mVU->regs->VI[_reg_].UL]);
xMOV (ptr32[&mVU->VIbackup], gprT3);
}
if (_reg_ == 0) { return; }
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
xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus));
#else
mVUallocSFLAGc(gprT1, fStatus);
mVUallocSFLAGc(gprT1, gprT2, fStatus);
xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], gprT1);
#endif
mVUallocMFLAGa(mVU, gprT1, fMac);

View File

@ -134,27 +134,25 @@ void doIbit(mV) {
void doSwapOp(mV) {
if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC);
xmm t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
xmm t2 = mVU->regAlloc->allocReg();
{
xmm t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
xMOVAPS(t2, t1);
mVU->regAlloc->clearNeeded(t1);
}
xMOVAPS(t2, t1);
mVU->regAlloc->clearNeeded(t1);
mVUopL(mVU, 1);
{
xmm t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
xXOR.PS(t2, t1);
xXOR.PS(t1, t2);
xXOR.PS(t2, t1);
mVU->regAlloc->clearNeeded(t1);
}
t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
xXOR.PS(t2, t1);
xXOR.PS(t1, t2);
xXOR.PS(t2, t1);
mVU->regAlloc->clearNeeded(t1);
incPC(1);
doUpperOp();
{
xmm t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
xMOVAPS(t1, t2);
mVU->regAlloc->clearNeeded(t1);
}
t1 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
xMOVAPS(t1, t2);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
}
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)
_f void handleBadOp(mV, int count) {
if (mVUinfo.isBadOp && count == 0) {
xMOV(ecx, (uptr)mVU);
xMOV(gprT2, (uptr)mVU);
if (!isVU1) xCALL(mVUbadOp0);
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) {
//u32* vu0jmp;
iPC = mVUstartPC;
mVUdebugNOW(0);
if (doEarlyExit(mVU)) {
xCMP(ptr32[&mVU->cycles], 0);
xForwardJG32 skip;
// FIXME: uh... actually kind of a pain with xForwardJump
//if (!isVU1) { TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); vu0jmp = JZ32(0); }
xMOV(ecx, (uptr)mVU);
if (isVU1) xCALL(mVUwarning1);
//else xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
mVUsavePipelineState(mVU);
mVUendProgram(mVU, NULL, 0);
//if (!isVU1) vu0jmp.SetTarget();
if (isVU0) {
// TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET);
// xFowardJZ32 vu0jmp;
// xMOV(gprT2, (uptr)mVU);
// xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
mVUsavePipelineState(mVU);
mVUendProgram(mVU, NULL, 0);
// vu0jmp.SetTarget();
}
else {
xMOV(gprT2, (uptr)mVU);
xCALL(mVUwarning1);
mVUsavePipelineState(mVU);
mVUendProgram(mVU, NULL, 0);
}
skip.SetTarget();
}
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
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
// Second Pass
@ -427,7 +441,7 @@ _r void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
else if (!mVUinfo.isBdelay) { incPC(1); }
else {
mVUsetupRange(mVU, xPC, 0);
mVUdebugNOW(1);
mVUdebugPrintBlocks(mVU,1);
incPC(-3); // Go back to branch opcode
switch (mVUlow.branch) {
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]);
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]);
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(xmmPQ, ptr128[&mVU->regs->VI[REG_Q].UL]);

View File

@ -178,17 +178,17 @@ _f void mVUsetupFlags(mV, microFlagCycles& mFC) {
xMOV(gprF[3], getFlagReg(bStatus[3]));
}
else if (sortRegs == 2) {
xMOV(gprT1, getFlagReg(bStatus[3]));
xMOV(gprF[0], getFlagReg(bStatus[0]));
xMOV(gprT1, getFlagReg (bStatus[3]));
xMOV(gprF[0], getFlagReg (bStatus[0]));
xMOV(gprF[1], getFlagReg2(bStatus[1]));
xMOV(gprF[2], getFlagReg2(bStatus[2]));
xMOV(gprF[3], gprT1);
}
else if (sortRegs == 3) {
int gFlag = (bStatus[0] == bStatus[1]) ? bStatus[2] : bStatus[1];
xMOV(gprT1, getFlagReg(gFlag));
xMOV(gprT2, getFlagReg(bStatus[3]));
xMOV(gprF[0], getFlagReg(bStatus[0]));
xMOV(gprT1, getFlagReg (gFlag));
xMOV(gprT2, getFlagReg (bStatus[3]));
xMOV(gprF[0], getFlagReg (bStatus[0]));
xMOV(gprF[1], getFlagReg3(bStatus[1]));
xMOV(gprF[2], getFlagReg4(bStatus[2]));
xMOV(gprF[3], gprT2);

View File

@ -255,8 +255,8 @@ void COP2_Interlock(bool mBitSync) {
void TEST_FBRST_RESET(FnType_Void* resetFunct, int vuIndex) {
xTEST(eax, (vuIndex) ? 0x200 : 0x002);
xForwardJZ8 skip;
xCALL(resetFunct);
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]);
xCALL(resetFunct);
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]);
skip.SetTarget();
}

View File

@ -87,6 +87,7 @@ typedef xRegister32 x32;
#define isCOP2 (mVU->cop2 != 0)
#define isVU1 (mVU->index != 0)
#define isVU0 (mVU->index == 0)
#define getIndex (isVU1 ? 1 : 0)
#define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16)
#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 mVUsaveReg(xmm reg, xAddressVoid ptr, int xyzw, bool modXYZW);
void mVUloadReg(xmm reg, xAddressVoid ptr, int xyzw);

View File

@ -22,10 +22,10 @@
void mVUunpack_xyzw(xmm dstreg, xmm srcreg, int xyzw)
{
switch ( xyzw ) {
case 0: xPSHUF.D(dstreg, srcreg, 0x00); break;
case 1: xPSHUF.D(dstreg, srcreg, 0x55); break;
case 2: xPSHUF.D(dstreg, srcreg, 0xaa); break;
case 3: xPSHUF.D(dstreg, srcreg, 0xff); break;
case 0: xPSHUF.D(dstreg, srcreg, 0x00); break; // XXXX
case 1: xPSHUF.D(dstreg, srcreg, 0x55); break; // YYYY
case 2: xPSHUF.D(dstreg, srcreg, 0xaa); break; // ZZZZ
case 3: xPSHUF.D(dstreg, srcreg, 0xff); break; // WWWW
}
}
@ -36,7 +36,7 @@ void mVUloadReg(xmm reg, xAddressVoid ptr, int xyzw)
case 4: xMOVSSZX(reg, ptr32[ptr+4]); break; // Y
case 2: xMOVSSZX(reg, ptr32[ptr+8]); break; // Z
case 1: xMOVSSZX(reg, ptr32[ptr+12]); break; // W
default: xMOVAPS(reg, ptr128[ptr]); break;
default: xMOVAPS (reg, ptr128[ptr]); break;
}
}
@ -135,10 +135,10 @@ void mVUsaveReg(xmm reg, xAddressVoid ptr, int xyzw, bool modXYZW)
case 1: if (!modXYZW) mVUunpack_xyzw(reg, reg, 3);
xMOVSS(ptr32[ptr+12], reg);
break; // W
case 8: xMOVSS(ptr32[ptr], reg); break; // X
case 12: xMOVL.PS(ptr64[ptr], reg); break; // XY
case 3: xMOVH.PS(ptr64[ptr+8], reg); break; // ZW
default: xMOVAPS(ptr128[ptr], reg); break; // XYZW
case 8: xMOVSS(ptr32[ptr], reg); break; // X
case 12: xMOVL.PS(ptr64[ptr], reg); break; // XY
case 3: xMOVH.PS(ptr64[ptr+8], reg); break; // ZW
default: xMOVAPS(ptr128[ptr], reg); break; // XYZW
}
}
@ -236,13 +236,13 @@ _f void mVUaddrFix(mV, x32 gprReg)
_f void mVUbackupRegs(microVU* mVU)
{
mVU->regAlloc->flushAll();
xMOVAPS(ptr128[&mVU->xmmPQb[0]], xmmPQ);
xMOVAPS(ptr128[mVU->xmmPQb], xmmPQ);
}
// Restore Volatile Regs
_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); } }
// 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) {
x32 mReg = gprT1;
bool regT2b = false;
static void mVUupdateFlags(mV, xmm reg, xmm regT1 = xEmptyReg, xmm regT2 = xEmptyReg, bool modXYZW = 1) {
x32 mReg = gprT1, sReg = getFlagReg(sFLAG.write);
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};
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
xmm regT1 = regT1in.IsEmpty() ? mVU->regAlloc->allocReg() : regT1in;
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW)))
{
if (regT2.IsEmpty())
{
regT2 = mVU->regAlloc->allocReg();
if (regT1.IsEmpty()) {
regT1 = mVU->regAlloc->allocReg();
regT1b = true;
}
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) {
if (regT2.IsEmpty()) {
regT2 = mVU->regAlloc->allocReg();
regT2b = true;
}
xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw
}
else
regT2 = reg;
else regT2 = reg;
if (sFLAG.doFlag) {
mVUallocSFLAGa(getFlagReg(sFLAG.write), sFLAG.lastWrite); // Get Prev Status Flag
if (sFLAG.doNonSticky) xAND(getFlagReg(sFLAG.write), 0xfffc00ff); // Clear O,U,S,Z flags
mVUallocSFLAGa(sReg, sFLAG.lastWrite); // Get Prev Status Flag
if (sFLAG.doNonSticky) xAND(sReg, 0xfffc00ff); // Clear O,U,S,Z flags
}
//-------------------------Check for Signed flags------------------------------
@ -56,12 +58,12 @@ static void mVUupdateFlags(mV, xmm reg, xmm regT1in = xEmptyReg, xmm regT2 = xEm
xCMPEQ.PS(regT1, regT2); // Set all F's if each vector is zero
xMOVMSKPS(gprT2, regT1); // Used for Zero Flag Calculation
xAND(mReg, AND_XYZW); // Grab "Is Signed" bits from the previous calculation
xAND(mReg, AND_XYZW); // Grab "Is Signed" bits from the previous calculation
xSHL(mReg, 4 + ADD_XYZW);
//-------------------------Check for Zero flags------------------------------
xAND(gprT2, AND_XYZW); // Grab "Is Zero" bits from the previous calculation
xAND(gprT2, AND_XYZW); // Grab "Is Zero" bits from the previous calculation
if (mFLAG.doFlag) { SHIFT_XYZW(gprT2); }
xOR(mReg, gprT2);
@ -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 (sFLAG.doFlag) {
xOR(getFlagReg(sFLAG.write), mReg);
xOR(sReg, mReg);
if (sFLAG.doNonSticky) {
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);
}
@ -350,7 +352,7 @@ mVUop(mVU_OPMSUB) {
}
// 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_); }
pass2 {
if (!_Ft_) return;
@ -377,7 +379,7 @@ static void mVU_FTOIx(mP, const float (*addr)[4], const char* opName) {
}
// 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_); }
pass2 {
if (!_Ft_) return;
@ -404,9 +406,9 @@ mVUop(mVU_CLIP) {
mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite);
xSHL(gprT1, 6);
xAND.PS(Ft, ptr128[&mVUglob.absclip[0]]);
xAND.PS(Ft, ptr128[mVUglob.absclip]);
xMOVAPS(t1, Ft);
xPOR(t1, ptr128[&mVUglob.signbit[0]]);
xPOR(t1, ptr128[mVUglob.signbit]);
xCMPNLE.PS(t1, 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_MINIw) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIw", 0); }
mVUop(mVU_FTOI0) { mVU_FTOIx(mX, NULL, "FTOI0"); }
mVUop(mVU_FTOI4) { mVU_FTOIx(mX, &mVUglob.FTOI_4, "FTOI4"); }
mVUop(mVU_FTOI12) { mVU_FTOIx(mX, &mVUglob.FTOI_12, "FTOI12"); }
mVUop(mVU_FTOI15) { mVU_FTOIx(mX, &mVUglob.FTOI_15, "FTOI15"); }
mVUop(mVU_FTOI4) { mVU_FTOIx(mX, mVUglob.FTOI_4, "FTOI4"); }
mVUop(mVU_FTOI12) { mVU_FTOIx(mX, mVUglob.FTOI_12, "FTOI12"); }
mVUop(mVU_FTOI15) { mVU_FTOIx(mX, mVUglob.FTOI_15, "FTOI15"); }
mVUop(mVU_ITOF0) { mVU_ITOFx(mX, NULL, "ITOF0"); }
mVUop(mVU_ITOF4) { mVU_ITOFx(mX, &mVUglob.ITOF_4, "ITOF4"); }
mVUop(mVU_ITOF12) { mVU_ITOFx(mX, &mVUglob.ITOF_12, "ITOF12"); }
mVUop(mVU_ITOF15) { mVU_ITOFx(mX, &mVUglob.ITOF_15, "ITOF15"); }
mVUop(mVU_ITOF4) { mVU_ITOFx(mX, mVUglob.ITOF_4, "ITOF4"); }
mVUop(mVU_ITOF12) { mVU_ITOFx(mX, mVUglob.ITOF_12, "ITOF12"); }
mVUop(mVU_ITOF15) { mVU_ITOFx(mX, mVUglob.ITOF_15, "ITOF15"); }
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 );
}
#if 0
#include "sVU_Compare.h"
#else
void recSuperVU1::Execute(u32 cycles)
{
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);
}
#endif