mVU: fixed some memleaks and fixed some rare bugs in microprogram range detection...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2692 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-03-11 04:03:08 +00:00
parent 956d041212
commit 8978e463ec
5 changed files with 65 additions and 81 deletions

View File

@ -132,6 +132,11 @@ _f void mVUreset(mV) {
mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - (_1mb * 3))); // 3mb "Safe Zone"
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
deque<microProgram*>::iterator it = mVU->prog.prog[i].list->begin();
for ( ; it != mVU->prog.prog[i].list->end(); it++) {
if (!isVU1) mVUdeleteProg<0>(it[0]);
else mVUdeleteProg<1>(it[0]);
}
mVU->prog.prog[i].list->clear();
mVU->prog.quick[i].block = NULL;
mVU->prog.quick[i].prog = NULL;
@ -147,7 +152,8 @@ _f void mVUclose(mV) {
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
deque<microProgram*>::iterator it = mVU->prog.prog[i].list->begin();
for ( ; it != mVU->prog.prog[i].list->end(); it++) {
safe_aligned_free(it[0]);
if (!isVU1) mVUdeleteProg<0>(it[0]);
else mVUdeleteProg<1>(it[0]);
}
safe_delete(mVU->prog.prog[i].list);
}
@ -176,18 +182,14 @@ _f void mVUvsyncUpdate(mV) {
//mVU->prog.curFrame++;
}
// Clears program data
_mVUt _f void mVUclearProg(microProgram& program, u32 startPC, bool deleteBlocks) {
// Deletes a program
_mVUt _f void mVUdeleteProg(microProgram*& prog) {
microVU* mVU = mVUx;
program.startPC = startPC;
for (int j = 0; j <= program.ranges.max; j++) {
program.ranges.range[j][0] = -1; // Set range to
program.ranges.range[j][1] = -1; // indeterminable status
program.ranges.total = -1;
}
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
if (deleteBlocks) safe_delete(program.block[i]);
safe_delete(prog->block[i]);
}
safe_delete(prog->ranges);
safe_aligned_free(prog);
}
// Creates a new Micro Program
@ -195,8 +197,9 @@ _mVUt _f microProgram* mVUcreateProg(int startPC) {
microVU* mVU = mVUx;
microProgram* prog = (microProgram*)_aligned_malloc(sizeof(microProgram), 64);
memzero_ptr<sizeof(microProgram)>(prog);
prog->idx = mVU->prog.total++;
mVUclearProg<vuIndex>(*prog, startPC);
prog->idx = mVU->prog.total++;
prog->ranges = new deque<microRange>();
prog->startPC = startPC;
mVUcacheProg<vuIndex>(*prog); // Cache Micro Program
float cacheSize = (float)((u32)mVU->prog.x86end - (u32)mVU->prog.x86start);
float cacheUsed =((float)((u32)mVU->prog.x86ptr - (u32)mVU->prog.x86start)) / cacheSize * 100;
@ -217,10 +220,10 @@ _mVUt _f void mVUcacheProg(microProgram& prog) {
// Compare partial program by only checking compiled ranges...
_mVUt _f bool mVUcmpPartial(microProgram& prog) {
microVU* mVU = mVUx;
for (int i = 0; i <= prog.ranges.total; i++) {
if((prog.ranges.range[i][0] < 0)
|| (prog.ranges.range[i][1] < 0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, i, prog.ranges.total); }
if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs->Micro), ((prog.ranges.range[i][1] + 8) - prog.ranges.range[i][0]))) {
deque<microRange>::const_iterator it = prog.ranges->begin();
for ( ; it != prog.ranges->end(); it++) {
if((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, it[0].start, it[0].end); }
if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs->Micro), ((it[0].end + 8) - it[0].start))) {
return 0;
}
}
@ -246,7 +249,7 @@ _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState) {
microProgramQuick& quick = mVU->prog.quick[startPC/8];
microProgramList& list = mVU->prog.prog [startPC/8];
if(!quick.prog) { // If null, we need to search for new program
deque<microProgram*>::iterator it = list.list->begin();
deque<microProgram*>::const_iterator it = list.list->begin();
for ( ; it != list.list->end(); it++) {
if (mVUcmpProg<vuIndex>(*it[0], 0)) {
quick.block = it[0]->block[startPC/8];

View File

@ -109,25 +109,16 @@ public:
}
};
#define mMaxRanges 128
struct microRange {
static const int max = mMaxRanges - 1;
int total;
s32 range[mMaxRanges][2];
};
enum microProgramAge {
isYoung = 0,
isAged = 1,
isOld = 2,
isDead = 3
s32 start; // Start PC (The opcode the block starts at)
s32 end; // End PC (The opcode the block ends with)
};
#define mProgSize (0x4000/4)
struct microProgram {
u32 data [mProgSize]; // Holds a copy of the VU microProgram
microBlockManager* block[mProgSize/2]; // Array of Block Managers
microRange ranges; // The ranges of the microProgram that have already been recompiled
deque<microRange>* ranges; // The ranges of the microProgram that have already been recompiled
u32 startPC; // Start PC of this program
int idx; // Program index
};
@ -214,8 +205,8 @@ mVUop(mVUopU);
mVUop(mVUopL);
// Private Functions
_mVUt _f void mVUclearProg(microProgram& prog, u32 startPC = -1, bool deleteBlocks = 1);
_mVUt _f void mVUcacheProg(microProgram& prog);
_mVUt _f void mVUcacheProg (microProgram& prog);
_mVUt _f void mVUdeleteProg(microProgram*& prog);
_mVUt _f void* mVUsearchProg(u32 startPC, uptr pState);
_mVUt _f microProgram* mVUfindLeastUsedProg();
void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles);

View File

@ -144,7 +144,7 @@ _f void mVUallocVIb(mV, int GPRreg, int _reg_) {
}
//------------------------------------------------------------------
// I/P/Q Reg Allocators
// P/Q Reg Allocators
//------------------------------------------------------------------
_f void getPreg(mV, int reg) {

View File

@ -44,64 +44,54 @@ _f void mVUcheckIsSame(mV) {
}
// Sets up microProgram PC ranges based on whats been recompiled
_f void mVUsetupRange(mV, s32 pc, bool isStartPC) {
_f void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {
deque<microRange>*& ranges = mVUcurProg.ranges;
pc &= mVU->microMemSize - 8;
if (isStartPC || !(mVUrange[1] == -1)) {
for (int i = 0; i <= mVUcurProg.ranges.total; i++) {
if ((pc >= mVUcurProg.ranges.range[i][0])
&& (pc <= mVUcurProg.ranges.range[i][1])) { return; }
if (isStartPC) { // Check if startPC is already within a block we've recompiled
deque<microRange>::const_iterator it = ranges->begin();
for ( ; it != ranges->end(); it++) {
if ((pc >= it[0].start) && (pc <= it[0].end)) {
if (it[0].start != it[0].end)
return; // Last case makes sure its not a 1-opcode EvilBlock
}
}
}
elif (mVUrange.end != -1) return; // Above case was true
mVUcheckIsSame(mVU);
if (isStartPC) {
if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) {
mVUcurProg.ranges.total++;
mVUrange[0] = pc;
microRange mRange = {pc, -1};
ranges->push_front(mRange);
return;
}
if (mVUrange.start <= pc) {
mVUrange.end = pc;
bool mergedRange = 0;
s32 rStart = mVUrange.start;
s32 rEnd = mVUrange.end;
deque<microRange>::iterator it = ranges->begin();
for (it++; it != ranges->end(); it++) {
if((it[0].start >= rStart) && (it[0].start <= rEnd)) {
it[0].end = aMax(it[0].end, rEnd);
mergedRange = 1;
}
elif((it[0].end >= rStart) && (it[0].end <= rEnd)) {
it[0].start = aMin(it[0].start, rStart);
mergedRange = 1;
}
}
else {
mVUcurProg.ranges.total = 0;
mVUrange[0] = 0;
mVUrange[1] = mVU->microMemSize - 8;
DevCon.Warning("microVU%d: Prog Range List Full", mVU->index);
if (mergedRange) {
//DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Merging", mVU->index);
ranges->erase(ranges->begin());
}
}
else {
if (mVUrange[0] <= pc) {
mVUrange[1] = pc;
bool mergedRange = 0;
for (int i = 0; i <= (mVUcurProg.ranges.total-1); i++) {
int rStart = (mVUrange[0] < 8) ? 0 : (mVUrange[0] - 8);
int rEnd = pc;
if((mVUcurProg.ranges.range[i][1] >= rStart)
&& (mVUcurProg.ranges.range[i][1] <= rEnd)){
mVUcurProg.ranges.range[i][1] = pc;
mergedRange = 1;
//DevCon.Status("microVU%d: Prog Range Merging", mVU->index);
}
}
if (mergedRange) {
mVUrange[0] = -1;
mVUrange[1] = -1;
mVUcurProg.ranges.total--;
}
}
else {
DevCon.WriteLn("microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange[0], mVUrange[1]);
mVUrange[1] = mVU->microMemSize - 8;
if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) {
mVUcurProg.ranges.total++;
mVUrange[0] = 0;
mVUrange[1] = pc;
}
else {
mVUcurProg.ranges.total = 0;
mVUrange[0] = 0;
mVUrange[1] = mVU->microMemSize - 8;
DevCon.Warning("microVU%d: Prog Range List Full", mVU->index);
}
}
//DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange.start, mVUrange.end);
mVUrange.end = mVU->microMemSize;
microRange mRange = {0, pc};
ranges->push_front(mRange);
}
}

View File

@ -177,7 +177,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define sFLAG mVUinfo.sFlag
#define mFLAG mVUinfo.mFlag
#define cFLAG mVUinfo.cFlag
#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total]
#define mVUrange (mVUcurProg.ranges[0])[0]
#define isEvilBlock (mVUpBlock->pState.blockType == 2)
#define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch)
#define xPC ((iPC / 2) * 8)
@ -189,7 +189,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
#define branchAddrN ((xPC + 16 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
#define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04))
#define cmpOffset(x) ((u8*)&(((u8*)x)[prog.ranges.range[i][0]]))
#define cmpOffset(x) ((u8*)&(((u8*)x)[it[0].start]))
#define Rmem (uptr)&mVU->regs->VI[REG_R].UL
#define aWrap(x, m) ((x > m) ? 0 : x)
#define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))