mirror of
https://github.com/libretro/pcsx2.git
synced 2024-12-23 10:19:10 +00:00
microVU:
- Crashes when "microVU Error: Program went over its cache limit" message occurs should be fixed. - Miscellaneous code changes and cleanups. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1211 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
0391b76015
commit
942e7e9231
@ -30,6 +30,7 @@ PCSX2_ALIGNED16(microVU microVU0);
|
||||
PCSX2_ALIGNED16(microVU microVU1);
|
||||
|
||||
declareAllVariables // Declares All Global Variables :D
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Micro VU - Main Functions
|
||||
//------------------------------------------------------------------
|
||||
@ -117,7 +118,6 @@ microVUt(void) mVUclose() {
|
||||
|
||||
// Clears Block Data in specified range
|
||||
microVUt(void) mVUclear(u32 addr, u32 size) {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
if (!mVU->prog.cleared) {
|
||||
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState));
|
||||
@ -139,7 +139,7 @@ microVUt(void) mVUclearProg(int progIndex) {
|
||||
mVU->prog.prog[progIndex].range[1] = -1;
|
||||
mVU->prog.prog[progIndex].x86ptr = mVU->prog.prog[progIndex].x86start;
|
||||
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
|
||||
if( mVU->prog.prog[progIndex].block[i] )
|
||||
if (mVU->prog.prog[progIndex].block[i])
|
||||
mVU->prog.prog[progIndex].block[i]->reset();
|
||||
}
|
||||
}
|
||||
@ -170,11 +170,9 @@ microVUt(int) mVUfindLeastUsedProg() {
|
||||
int smallidx = startidx;
|
||||
u32 smallval = mVU->prog.prog[startidx].used;
|
||||
|
||||
for (int i = startidx; i != endidx; i = (i+1)&mVU->prog.max)
|
||||
{
|
||||
for (int i = startidx; i != endidx; i = (i+1)&mVU->prog.max) {
|
||||
u32 used = mVU->prog.prog[i].used;
|
||||
if (smallval > used)
|
||||
{
|
||||
if (smallval > used) {
|
||||
smallval = used;
|
||||
smallidx = i;
|
||||
}
|
||||
@ -195,7 +193,6 @@ microVUt(int) mVUfindLeastUsedProg() {
|
||||
// frame-based decrementing system in combination with a program-execution-based incrementing
|
||||
// system. In english: if last_used >= 2 it means the program has been used for the current
|
||||
// or prev frame. if it's 0, the program hasn't been used for a while.
|
||||
//
|
||||
microVUt(void) __mVUvsyncUpdate() {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
@ -246,11 +243,7 @@ microVUt(int) mVUsearchProg() {
|
||||
for (int i = 0; i <= mVU->prog.total; i++) {
|
||||
if (mVUcmpProg<vuIndex>(i, !mVU->prog.prog[i].used, 0, 0))
|
||||
return 1; // Check Older Programs
|
||||
}
|
||||
/*for (int i = 0; i <= mVU->prog.total; i++) {
|
||||
if (mVUcmpProg<vuIndex>(i, 1, 1, 0))
|
||||
return 1; // Check Partial Program
|
||||
}*/
|
||||
}
|
||||
mVU->prog.cur = mVUfindLeastUsedProg<vuIndex>(); // If cleared and program not found, make a new program instance
|
||||
mVU->prog.cleared = 0;
|
||||
mVU->prog.isSame = 1;
|
||||
@ -260,27 +253,7 @@ microVUt(int) mVUsearchProg() {
|
||||
mVU->prog.prog[mVU->prog.cur].last_used = 3;
|
||||
return 1; // If !cleared, then we're still on the same program as last-time ;)
|
||||
}
|
||||
/*
|
||||
// Block Invalidation
|
||||
__forceinline void mVUinvalidateBlock(microVU* mVU, u32 addr, u32 size) {
|
||||
|
||||
int i = addr/8;
|
||||
int end = i+((size+(8-(size&7)))/8); // ToDo: Can be simplified to addr+size if Size is always a multiple of 8
|
||||
|
||||
if (!mVU->prog.cleared) {
|
||||
for ( ; i < end; i++) {
|
||||
if ( mVU->prog.prog[mVU->prog.cur].block[i]->clear() ) {
|
||||
mVU->prog.cleared = 1;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( ; i < end; i++) {
|
||||
mVU->prog.prog[mVU->prog.cur].block[i]->clearFast();
|
||||
}
|
||||
}
|
||||
*/
|
||||
//------------------------------------------------------------------
|
||||
// Wrapper Functions - Called by other parts of the Emu
|
||||
//------------------------------------------------------------------
|
||||
|
@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
//#define mVUdebug // Prints Extra Info to Console
|
||||
//#define mVUlogProg // Dumps MicroPrograms into microVU0.txt/microVU1.txt
|
||||
//#define mVUdebug // Prints Extra Info to Console
|
||||
//#define mVUlogProg // Dumps MicroPrograms to \logs\*.html
|
||||
|
||||
#include "Common.h"
|
||||
#include "VU.h"
|
||||
@ -27,24 +27,26 @@
|
||||
#include "microVU_Alloc.h"
|
||||
#include "microVU_Misc.h"
|
||||
|
||||
#define mMaxBlocks 32 // Max Blocks With Different Pipeline States
|
||||
#define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...)
|
||||
class microBlockManager {
|
||||
private:
|
||||
static const int MaxBlocks = mMaxBlocks - 1;
|
||||
int listSize; // Total Items - 1
|
||||
int listI; // Index to Add new block
|
||||
microBlock blockList[mMaxBlocks];
|
||||
|
||||
public:
|
||||
microBlockManager() { reset(); }
|
||||
~microBlockManager() {}
|
||||
void reset() { listSize = -1; };
|
||||
void reset() { listSize = -1; listI = -1; };
|
||||
microBlock* add(microBlock* pBlock) {
|
||||
microBlock* thisBlock = search(&pBlock->pState);
|
||||
if (!thisBlock) {
|
||||
listSize++;
|
||||
if (listSize > MaxBlocks) { Console::Error("microVU Warning: Block List Overflow"); listSize = 0; }
|
||||
memcpy_fast(&blockList[listSize], pBlock, sizeof(microBlock));
|
||||
thisBlock = &blockList[listSize];
|
||||
listI++;
|
||||
if (listSize < MaxBlocks) { listSize++; }
|
||||
if (listI > MaxBlocks) { Console::Error("microVU Warning: Block List Overflow"); listI = 0; }
|
||||
memcpy_fast(&blockList[listI], pBlock, sizeof(microBlock));
|
||||
thisBlock = &blockList[listI];
|
||||
}
|
||||
return thisBlock;
|
||||
}
|
||||
|
@ -49,6 +49,19 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define analyzeReg1b(reg) { \
|
||||
if (reg) { \
|
||||
analyzeReg1(reg); \
|
||||
if (mVUregsTemp.VFreg[0] == reg) { \
|
||||
if ((mVUregsTemp.VF[0].x && _X) \
|
||||
|| (mVUregsTemp.VF[0].y && _Y) \
|
||||
|| (mVUregsTemp.VF[0].z && _Z) \
|
||||
|| (mVUregsTemp.VF[0].w && _W)) \
|
||||
{ mVUinfo |= _swapOps; } \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
microVUt(void) mVUanalyzeFMAC1(int Fd, int Fs, int Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
mVUinfo |= _doStatus;
|
||||
@ -136,6 +149,13 @@ microVUt(void) mVUanalyzeIALU2(int Is, int It) {
|
||||
if (_Y) { mVUstall = aMax(mVUstall, aReg(reg).z); } \
|
||||
if (_Z) { mVUstall = aMax(mVUstall, aReg(reg).w); } \
|
||||
if (_W) { mVUstall = aMax(mVUstall, aReg(reg).x); } \
|
||||
if (mVUregsTemp.VFreg[0] == reg) { \
|
||||
if ((mVUregsTemp.VF[0].y && _X) \
|
||||
|| (mVUregsTemp.VF[0].z && _Y) \
|
||||
|| (mVUregsTemp.VF[0].w && _Z) \
|
||||
|| (mVUregsTemp.VF[0].x && _W)) \
|
||||
{ mVUinfo |= _swapOps; } \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -158,6 +178,13 @@ microVUt(void) mVUanalyzeMR32(int Fs, int Ft) {
|
||||
case 2: mVUstall = aMax(mVUstall, aReg(reg).z); break; \
|
||||
case 3: mVUstall = aMax(mVUstall, aReg(reg).w); break; \
|
||||
} \
|
||||
if (mVUregsTemp.VFreg[0] == reg) { \
|
||||
if ((mVUregsTemp.VF[0].x && (fxf == 0)) \
|
||||
|| (mVUregsTemp.VF[0].y && (fxf == 1)) \
|
||||
|| (mVUregsTemp.VF[0].z && (fxf == 2)) \
|
||||
|| (mVUregsTemp.VF[0].w && (fxf == 3))) \
|
||||
{ mVUinfo |= _swapOps; } \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -186,7 +213,7 @@ microVUt(void) mVUanalyzeEFU1(int Fs, int Fsf, u8 xCycles) {
|
||||
microVUt(void) mVUanalyzeEFU2(int Fs, u8 xCycles) {
|
||||
microVU* mVU = mVUx;
|
||||
mVUprint("microVU: EFU Opcode");
|
||||
analyzeReg1(Fs);
|
||||
analyzeReg1b(Fs);
|
||||
analyzePreg(xCycles);
|
||||
}
|
||||
|
||||
@ -207,8 +234,7 @@ microVUt(void) mVUanalyzeMFP(int Ft) {
|
||||
microVUt(void) mVUanalyzeMOVE(int Fs, int Ft) {
|
||||
microVU* mVU = mVUx;
|
||||
if (!Ft || (Ft == Fs)) { mVUinfo |= _isNOP; }
|
||||
if (mVUregsTemp.VFreg[0] == Fs) { mVUinfo |= _swapOps; }
|
||||
analyzeReg1(Fs);
|
||||
analyzeReg1b(Fs);
|
||||
analyzeReg2(Ft, 1);
|
||||
}
|
||||
|
||||
@ -231,10 +257,9 @@ microVUt(void) mVUanalyzeLQ(int Ft, int Is, bool writeIs) {
|
||||
|
||||
microVUt(void) mVUanalyzeSQ(int Fs, int It, bool writeIt) {
|
||||
microVU* mVU = mVUx;
|
||||
analyzeReg1(Fs);
|
||||
analyzeReg1b(Fs);
|
||||
analyzeVIreg1(It);
|
||||
if (writeIt) { analyzeVIreg2(It, 1); }
|
||||
if (mVUregsTemp.VFreg[0] == Fs) { mVUinfo |= _swapOps; }
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -45,6 +45,36 @@
|
||||
// Helper Functions
|
||||
//------------------------------------------------------------------
|
||||
|
||||
// Used by mVUsetupRange
|
||||
microVUt(void) mVUcheckIsSame() {
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
if (mVU->prog.isSame == -1) {
|
||||
mVU->prog.isSame = !!memcmp_mmx(mVU->prog.prog[mVU->prog.cur].data, mVU->regs->Micro, mVU->microSize);
|
||||
}
|
||||
if (mVU->prog.isSame == 0) {
|
||||
mVUcacheProg<vuIndex>(mVU->prog.cur);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets up microProgram PC ranges based on whats been recompiled
|
||||
microVUt(void) mVUsetupRange(u32 pc) {
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
if (mVUcurProg.range[0] == -1) {
|
||||
mVUcurProg.range[0] = (s32)pc;
|
||||
mVUcurProg.range[1] = (s32)pc;
|
||||
}
|
||||
else if (mVUcurProg.range[0] > (s32)pc) {
|
||||
mVUcurProg.range[0] = (s32)pc;
|
||||
mVUcheckIsSame<vuIndex>();
|
||||
}
|
||||
else if (mVUcurProg.range[1] < (s32)pc) {
|
||||
mVUcurProg.range[1] = (s32)pc;
|
||||
mVUcheckIsSame<vuIndex>();
|
||||
}
|
||||
}
|
||||
|
||||
// Recompiles Code for Proper Flags and Q/P regs on Block Linkings
|
||||
microVUt(void) mVUsetupBranch(int* xStatus, int* xMac, int* xClip, int xCycles) {
|
||||
microVU* mVU = mVUx;
|
||||
@ -150,34 +180,6 @@ microVUt(void) mVUtestCycles() {
|
||||
SUB32ItoM((uptr)&mVU->cycles, mVUcycles);
|
||||
}
|
||||
|
||||
microVUt(void) mVUcheckIsSame() {
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
if (mVU->prog.isSame == -1) {
|
||||
mVU->prog.isSame = !!memcmp_mmx(mVU->prog.prog[mVU->prog.cur].data, mVU->regs->Micro, mVU->microSize);
|
||||
}
|
||||
if (mVU->prog.isSame == 0) {
|
||||
mVUcacheProg<vuIndex>(mVU->prog.cur);
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) mVUsetupRange(u32 pc) {
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
if (mVUcurProg.range[0] == -1) {
|
||||
mVUcurProg.range[0] = (s32)pc;
|
||||
mVUcurProg.range[1] = (s32)pc;
|
||||
}
|
||||
else if (mVUcurProg.range[0] > (s32)pc) {
|
||||
mVUcurProg.range[0] = (s32)pc;
|
||||
mVUcheckIsSame<vuIndex>();
|
||||
}
|
||||
else if (mVUcurProg.range[1] < (s32)pc) {
|
||||
mVUcurProg.range[1] = (s32)pc;
|
||||
mVUcheckIsSame<vuIndex>();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Recompiler
|
||||
//------------------------------------------------------------------
|
||||
@ -276,7 +278,7 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
|
||||
incPC(-3); // Go back to branch opcode (to get branch imm addr)
|
||||
mVUsetupBranch<vuIndex>(xStatus, xMac, xClip, xCycles);
|
||||
|
||||
if( mVUblocks[branchAddr/8] == NULL )
|
||||
if (mVUblocks[branchAddr/8] == NULL)
|
||||
mVUblocks[branchAddr/8] = new microBlockManager();
|
||||
|
||||
// Check if branch-block has already been compiled
|
||||
@ -293,7 +295,6 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
|
||||
|
||||
mVUbackupRegs<vuIndex>();
|
||||
MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX first argument for __fastcall)
|
||||
//AND32ItoR(gprT2, (vuIndex)?0x3ff8:0xff8); // Ensure valid jump address
|
||||
MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall)
|
||||
|
||||
if (!vuIndex) CALLFunc((uptr)mVUcompileVU0); //(u32 startPC, uptr pState)
|
||||
|
@ -26,7 +26,7 @@ microVUt(void) mVUdivSet() {
|
||||
if (doDivFlag) {
|
||||
getFlagReg(flagReg1, fsInstance);
|
||||
if (!doStatus) { getFlagReg(flagReg2, fpsInstance); MOV32RtoR(flagReg1, flagReg2); }
|
||||
AND16ItoR(flagReg1, 0x0fcf);
|
||||
AND32ItoR(flagReg1, 0x0fcf);
|
||||
OR32MtoR (flagReg1, (uptr)&mVU->divFlag);
|
||||
}
|
||||
}
|
||||
@ -223,8 +223,7 @@ microVUt(void) mVUsetFlagInfo() {
|
||||
mVUflagInfo = 0;
|
||||
incPC(4); // Branch Not Taken
|
||||
mVUpass4<vuIndex>(xPC);
|
||||
incPC(-3);
|
||||
//if (mVUflagInfo != backupFlagInfo) { mVUflagInfo |= __NeedExact; }
|
||||
incPC(-3);
|
||||
mVUflagInfo |= backupFlagInfo;
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +293,10 @@ declareAllVariables
|
||||
#define CHECK_VU_MINMAXHACK 0 // Min/Max Speed Hack
|
||||
|
||||
// Cache Limit Check
|
||||
#define mVUcacheCheck(ptr, start, limit) { \
|
||||
uptr diff = ptr - start; \
|
||||
if (diff >= limit) { Console::Error("microVU Error: Program went over its cache limit. Size = 0x%x", params diff); } \
|
||||
#define mVUcacheCheck(ptr, start, limit) { \
|
||||
uptr diff = ptr - start; \
|
||||
if (diff >= limit) { \
|
||||
Console::Error("microVU Error: Program went over its cache limit. Size = 0x%x", params diff); \
|
||||
mVUreset<vuIndex>(); \
|
||||
} \
|
||||
}
|
||||
|
@ -302,12 +302,9 @@ microVUt(void) mVUrestoreRegs() {
|
||||
// Reads entire microProgram and finds out if Status Flag is Used
|
||||
microVUt(void) mVUcheckSflag(int progIndex) {
|
||||
if (CHECK_VU_FLAGHACK) {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
mVUsFlagHack = 1;
|
||||
for (u32 i = 0; i < mVU->progSize; i+=2) {
|
||||
mVU->code = mVU->prog.prog[progIndex].data[i+1];
|
||||
mVUopU<vuIndex, 3>();
|
||||
mVU->code = mVU->prog.prog[progIndex].data[i];
|
||||
mVUopL<vuIndex, 3>();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user