mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
956d041212
commit
8978e463ec
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))))
|
||||
|
|
Loading…
Reference in New Issue