microVU: more cleanups (mostly just change pointers to references)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4415 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2011-03-12 08:02:21 +00:00
parent 6c8dc7bcb6
commit c4d8356a1b
5 changed files with 130 additions and 164 deletions

View File

@ -16,64 +16,7 @@
// Micro VU recompiler! - author: cottonvibes(@gmail.com)
#include "PrecompiledHeader.h"
#include "Common.h"
#include "microVU.h"
#include "System/RecTypes.h"
// Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files)
#include "microVU_Clamp.inl"
#include "microVU_Misc.inl"
#include "microVU_Log.inl"
#include "microVU_Analyze.inl"
#include "microVU_Alloc.inl"
#include "microVU_Upper.inl"
#include "microVU_Lower.inl"
#include "microVU_Tables.inl"
#include "microVU_Flags.inl"
#include "microVU_Branch.inl"
#include "microVU_Compile.inl"
#include "microVU_Execute.inl"
#include "microVU_Macro.inl"
//------------------------------------------------------------------
// Micro VU - Global Variables
//------------------------------------------------------------------
__aligned16 microVU microVU0;
__aligned16 microVU microVU1;
const __aligned(32) mVU_Globals mVUglob = {
__four(0x7fffffff), // absclip
__four(0x80000000), // signbit
__four(0xff7fffff), // minvals
__four(0x7f7fffff), // maxvals
__four(0x3f800000), // ONE!
__four(0x3f490fdb), // PI4!
__four(0x3f7ffff5), // T1
__four(0xbeaaa61c), // T5
__four(0x3e4c40a6), // T2
__four(0xbe0e6c63), // T3
__four(0x3dc577df), // T4
__four(0xbd6501c4), // T6
__four(0x3cb31652), // T7
__four(0xbb84d7e7), // T8
__four(0xbe2aaaa4), // S2
__four(0x3c08873e), // S3
__four(0xb94fb21f), // S4
__four(0x362e9c14), // S5
__four(0x3e7fffa8), // E1
__four(0x3d0007f4), // E2
__four(0x3b29d3ff), // E3
__four(0x3933e553), // E4
__four(0x36b63510), // E5
__four(0x353961ac), // E6
__four(16.0), // FTOI_4
__four(4096.0), // FTOI_12
__four(32768.0), // FTOI_15
__four(0.0625f), // ITOF_4
__four(0.000244140625), // ITOF_12
__four(0.000030517578125) // ITOF_15
};
//------------------------------------------------------------------
// Micro VU - Main Functions
@ -162,11 +105,9 @@ void mVUreset(microVU& mVU, bool resetReserve) {
mVU.prog.prog[i] = new deque<microProgram*>();
continue;
}
deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin());
for ( ; it != mVU.prog.prog[i]->end(); ++it) {
if (mVU.index) mVUdeleteProg<1>(it[0]);
else mVUdeleteProg<0>(it[0]);
mVUdeleteProg(mVU, it[0]);
}
mVU.prog.prog[i]->clear();
mVU.prog.quick[i].block = NULL;
@ -178,7 +119,6 @@ void mVUreset(microVU& mVU, bool resetReserve) {
void mVUclose(microVU& mVU) {
safe_delete (mVU.cache_reserve);
SafeSysMunmap(mVU.dispCache, mVUdispCacheSize);
// Delete Programs and Block Managers
@ -186,8 +126,7 @@ void mVUclose(microVU& mVU) {
if (!mVU.prog.prog[i]) continue;
deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin());
for ( ; it != mVU.prog.prog[i]->end(); ++it) {
if (mVU.index) mVUdeleteProg<1>(it[0]);
else mVUdeleteProg<0>(it[0]);
mVUdeleteProg(mVU, it[0]);
}
safe_delete(mVU.prog.prog[i]);
}
@ -210,14 +149,13 @@ static __fi void mVUclear(mV, u32 addr, u32 size) {
//------------------------------------------------------------------
// Finds and Ages/Kills Programs if they haven't been used in a while.
static __fi void mVUvsyncUpdate(mV) {
static __ri void mVUvsyncUpdate(mV) {
//mVU->prog.curFrame++;
}
// Deletes a program
_mVUt __fi void mVUdeleteProg(microProgram*& prog) {
microVU* mVU = mVUx;
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
__ri void mVUdeleteProg(microVU& mVU, microProgram*& prog) {
for (u32 i = 0; i < (mVU.progSize / 2); i++) {
safe_delete(prog->block[i]);
}
safe_delete(prog->ranges);
@ -225,38 +163,35 @@ _mVUt __fi void mVUdeleteProg(microProgram*& prog) {
}
// Creates a new Micro Program
_mVUt __fi microProgram* mVUcreateProg(int startPC) {
microVU* mVU = mVUx;
__ri microProgram* mVUcreateProg(microVU& mVU, int startPC) {
microProgram* prog = (microProgram*)_aligned_malloc(sizeof(microProgram), 64);
memzero_ptr<sizeof(microProgram)>(prog);
prog->idx = mVU->prog.total++;
prog->idx = mVU.prog.total++;
prog->ranges = new deque<microRange>();
prog->startPC = startPC;
mVUcacheProg<vuIndex>(*prog); // Cache Micro Program
double cacheSize = (double)((u32)mVU->prog.x86end - (u32)mVU->prog.x86start);
double cacheUsed =((double)((u32)mVU->prog.x86ptr - (u32)mVU->prog.x86start)) / (double)_1mb;
double cachePerc =((double)((u32)mVU->prog.x86ptr - (u32)mVU->prog.x86start)) / cacheSize * 100;
ConsoleColors c = vuIndex ? Color_Orange : Color_Magenta;
mVUcacheProg(mVU, *prog); // Cache Micro Program
double cacheSize = (double)((u32)mVU.prog.x86end - (u32)mVU.prog.x86start);
double cacheUsed =((double)((u32)mVU.prog.x86ptr - (u32)mVU.prog.x86start)) / (double)_1mb;
double cachePerc =((double)((u32)mVU.prog.x86ptr - (u32)mVU.prog.x86start)) / cacheSize * 100;
ConsoleColors c = mVU.index ? Color_Orange : Color_Magenta;
DevCon.WriteLn(c, "microVU%d: Cached Prog = [%03d] [PC=%04x] [List=%02d] (Cache=%3.3f%%) [%3.1fmb]",
vuIndex, prog->idx, startPC*8, mVU->prog.prog[startPC]->size()+1, cachePerc, cacheUsed);
mVU.index, prog->idx, startPC*8, mVU.prog.prog[startPC]->size()+1, cachePerc, cacheUsed);
return prog;
}
// Caches Micro Program
_mVUt __fi void mVUcacheProg(microProgram& prog) {
microVU* mVU = mVUx;
if (!vuIndex) memcpy_const(prog.data, mVU->regs().Micro, 0x1000);
else memcpy_const(prog.data, mVU->regs().Micro, 0x4000);
__ri void mVUcacheProg(microVU& mVU, microProgram& prog) {
if (!mVU.index) memcpy_const(prog.data, mVU.regs().Micro, 0x1000);
else memcpy_const(prog.data, mVU.regs().Micro, 0x4000);
mVUdumpProg(prog);
}
// Generate Hash for partial program based on compiled ranges...
_mVUt __fi u64 mVUrangesHash(microProgram& prog) {
microVU* mVU = mVUx;
u64 mVUrangesHash(microVU& mVU, microProgram& prog) {
u32 hash[2] = {0, 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((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, it[0].start, it[0].end); }
for(int i = it[0].start/4; i < it[0].end/4; i++) {
hash[0] -= prog.data[i];
hash[1] ^= prog.data[i];
@ -266,15 +201,14 @@ _mVUt __fi u64 mVUrangesHash(microProgram& prog) {
}
// Prints the ratio of unique programs to total programs
_mVUt __fi void mVUprintUniqueRatio() {
microVU* mVU = mVUx;
void mVUprintUniqueRatio(microVU& mVU) {
vector<u64> v;
for(u32 pc = 0; pc < mProgSize/2; pc++) {
microProgramList* list = mVU->prog.prog[pc];
microProgramList* list = mVU.prog.prog[pc];
if (!list) continue;
deque<microProgram*>::iterator it(list->begin());
for ( ; it != list->end(); ++it) {
v.push_back(mVUrangesHash<vuIndex>(*it[0]));
v.push_back(mVUrangesHash(mVU, *it[0]));
}
}
u32 total = v.size();
@ -285,12 +219,11 @@ _mVUt __fi void mVUprintUniqueRatio() {
}
// Compare partial program by only checking compiled ranges...
_mVUt __fi bool mVUcmpPartial(microProgram& prog) {
microVU* mVU = mVUx;
__ri bool mVUcmpPartial(microVU& mVU, microProgram& prog) {
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))) {
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;
}
}
@ -298,13 +231,12 @@ _mVUt __fi bool mVUcmpPartial(microProgram& prog) {
}
// Compare Cached microProgram to mVU->regs().Micro
_mVUt __fi bool mVUcmpProg(microProgram& prog, const bool cmpWholeProg) {
microVU* mVU = mVUx;
if ((cmpWholeProg && !memcmp_mmx((u8*)prog.data, mVU->regs().Micro, mVU->microMemSize))
|| (!cmpWholeProg && mVUcmpPartial<vuIndex>(prog))) {
mVU->prog.cleared = 0;
mVU->prog.cur = &prog;
mVU->prog.isSame = cmpWholeProg ? 1 : -1;
__fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg) {
if ((cmpWholeProg && !memcmp_mmx((u8*)prog.data, mVU.regs().Micro, mVU.microMemSize))
|| (!cmpWholeProg && mVUcmpPartial(mVU, prog))) {
mVU.prog.cleared = 0;
mVU.prog.cur = &prog;
mVU.prog.isSame = cmpWholeProg ? 1 : -1;
return 1;
}
return 0;
@ -312,13 +244,13 @@ _mVUt __fi bool mVUcmpProg(microProgram& prog, const bool cmpWholeProg) {
// Searches for Cached Micro Program and sets prog.cur to it (returns entry-point to program)
_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
microVU* mVU = mVUx;
microProgramQuick& quick = mVU->prog.quick[startPC/8];
microProgramList* list = mVU->prog.prog [startPC/8];
microVU& mVU = mVUx;
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->begin());
for ( ; it != list->end(); ++it) {
if (mVUcmpProg<vuIndex>(*it[0], 0)) {
if (mVUcmpProg(mVU, *it[0], 0)) {
quick.block = it[0]->block[startPC/8];
quick.prog = it[0];
list->erase(it);
@ -328,19 +260,19 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
}
// If cleared and program not found, make a new program instance
mVU->prog.cleared = 0;
mVU->prog.isSame = 1;
mVU->prog.cur = mVUcreateProg<vuIndex>(startPC/8);
void* entryPoint = mVUblockFetch(mVU, startPC, pState);
quick.block = mVU->prog.cur->block[startPC/8];
quick.prog = mVU->prog.cur;
list->push_front(mVU->prog.cur);
//mVUprintUniqueRatio<vuIndex>();
mVU.prog.cleared = 0;
mVU.prog.isSame = 1;
mVU.prog.cur = mVUcreateProg( mVU, startPC/8);
void* entryPoint = mVUblockFetch(&mVU, startPC, pState);
quick.block = mVU.prog.cur->block[startPC/8];
quick.prog = mVU.prog.cur;
list->push_front(mVU.prog.cur);
//mVUprintUniqueRatio(mVU);
return entryPoint;
}
// If list.quick, then we've already found and recompiled the program ;)
mVU->prog.isSame = -1;
mVU->prog.cur = quick.prog;
mVU.prog.isSame = -1;
mVU.prog.cur = quick.prog;
return mVUentryGet(mVU, quick.block, startPC, pState);
}

View File

@ -21,12 +21,13 @@ using namespace std;
using namespace x86Emitter;
#include <deque>
#include "Common.h"
#include "VU.h"
#include "GS.h"
#include "Gif.h"
#include "iR5900.h"
#include "R5900OpcodeTables.h"
#include "System/RecTypes.h"
#include "x86emitter/x86emitter.h"
#include "microVU_Misc.h"
#include "microVU_IR.h"
@ -244,15 +245,16 @@ struct microVU {
};
// microVU rec structs
extern __aligned16 microVU microVU0;
extern __aligned16 microVU microVU1;
__aligned16 microVU microVU0;
__aligned16 microVU microVU1;
// Debug Helper
int mVUdebugNow = 0;
// Main Functions
static void mVUclear(mV, u32, u32);
static void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
extern void mVUclear(mV, u32, u32);
extern void mVUreset(microVU& mVU, bool resetReserve);
extern void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
_mVUt extern void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr);
// Prototypes for Linux
@ -262,10 +264,9 @@ mVUop(mVUopU);
mVUop(mVUopL);
// Private Functions
_mVUt extern void mVUcacheProg (microProgram& prog);
_mVUt extern void mVUdeleteProg(microProgram*& prog);
extern void mVUcacheProg (microVU& mVU, microProgram& prog);
extern void mVUdeleteProg(microVU& mVU, microProgram*& prog);
_mVUt extern void* mVUsearchProg(u32 startPC, uptr pState);
_mVUt extern microProgram* mVUfindLeastUsedProg();
extern void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles);
extern void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles);
@ -282,3 +283,18 @@ template<typename T>
void sortVector(T& v) {
sort(v.begin(), v.end());
}
// Include all the *.inl files (microVU compiles as 1 Translation Unit)
#include "microVU_Clamp.inl"
#include "microVU_Misc.inl"
#include "microVU_Log.inl"
#include "microVU_Analyze.inl"
#include "microVU_Alloc.inl"
#include "microVU_Upper.inl"
#include "microVU_Lower.inl"
#include "microVU_Tables.inl"
#include "microVU_Flags.inl"
#include "microVU_Branch.inl"
#include "microVU_Compile.inl"
#include "microVU_Execute.inl"
#include "microVU_Macro.inl"

View File

@ -36,8 +36,7 @@ static __fi void mVUcheckIsSame(mV) {
mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs().Micro, mVU->microMemSize);
}
if (mVU->prog.isSame == 0) {
if (!isVU1) mVUcacheProg<0>(*mVU->prog.cur);
else mVUcacheProg<1>(*mVU->prog.cur);
mVUcacheProg(*mVU, *mVU->prog.cur);
mVU->prog.isSame = 1;
}
}
@ -495,10 +494,10 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
}
// Returns the entry point of the block (compiles it if not found)
static __fi void* mVUentryGet(microVU* mVU, microBlockManager* block, u32 startPC, uptr pState) {
static __fi void* mVUentryGet(microVU& mVU, microBlockManager* block, u32 startPC, uptr pState) {
microBlock* pBlock = block->search((microRegInfo*)pState);
if (pBlock) return pBlock->x86ptrStart;
else return mVUcompile(mVU, startPC, pState);
else return mVUcompile(&mVU, startPC, pState);
}
// Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)
@ -509,18 +508,18 @@ static __fi void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
startPC &= mVU->microMemSize-8;
blockCreate(startPC/8);
return mVUentryGet(mVU, mVUblocks[startPC/8], startPC, pState);
return mVUentryGet(*mVU, mVUblocks[startPC/8], startPC, pState);
}
// mVUcompileJIT() - Called By JR/JALR during execution
_mVUt void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr) {
if (doJumpCaching) { // When doJumpCaching, ptr is a microBlock pointer
microVU* mVU = mVUx;
microVU& mVU = mVUx;
microBlock* pBlock = (microBlock*)ptr;
microJumpCache& jc = pBlock->jumpCache[startPC/8];
if (jc.prog && jc.prog == mVU->prog.quick[startPC/8].prog) return jc.x86ptrStart;
if (jc.prog && jc.prog == mVU.prog.quick[startPC/8].prog) return jc.x86ptrStart;
void* v = mVUsearchProg<vuIndex>(startPC, (uptr)&pBlock->pStateEnd);
jc.prog = mVU->prog.quick[startPC/8].prog;
jc.prog = mVU.prog.quick[startPC/8].prog;
jc.x86ptrStart = v;
return v;
}

View File

@ -19,10 +19,6 @@
// Dispatcher Functions
//------------------------------------------------------------------
#ifdef __GNUC__
extern void mVUreset(microVU& mVU, bool resetReserve);
#endif
// Generates the code for entering recompiled blocks
void mVUdispatcherA(mV) {
mVU->startFunct = x86Ptr;
@ -171,14 +167,14 @@ void mVUdispatcherD(mV) {
// Executes for number of cycles
_mVUt void* __fastcall mVUexecute(u32 startPC, u32 cycles) {
microVU* mVU = mVUx;
microVU& mVU = mVUx;
//DevCon.WriteLn("microVU%x: startPC = 0x%x, cycles = 0x%x", vuIndex, startPC, cycles);
mVU->cycles = cycles;
mVU->totalCycles = cycles;
mVU.cycles = cycles;
mVU.totalCycles = cycles;
xSetPtr(mVU->prog.x86ptr); // Set x86ptr to where last program left off
return mVUsearchProg<vuIndex>(startPC, (uptr)&mVU->prog.lpState); // Find and set correct program
xSetPtr(mVU.prog.x86ptr); // Set x86ptr to where last program left off
return mVUsearchProg<vuIndex>(startPC, (uptr)&mVU.prog.lpState); // Find and set correct program
}
//------------------------------------------------------------------
@ -186,24 +182,24 @@ _mVUt void* __fastcall mVUexecute(u32 startPC, u32 cycles) {
//------------------------------------------------------------------
_mVUt void mVUcleanUp() {
microVU* mVU = mVUx;
microVU& mVU = mVUx;
//mVUprint("microVU: Program exited successfully!");
//mVUprint("microVU: VF0 = {%x,%x,%x,%x}", mVU->regs().VF[0].UL[0], mVU->regs().VF[0].UL[1], mVU->regs().VF[0].UL[2], mVU->regs().VF[0].UL[3]);
//mVUprint("microVU: VI0 = %x", mVU->regs().VI[0].UL);
//mVUprint("microVU: VF0 = {%x,%x,%x,%x}", mVU.regs().VF[0].UL[0], mVU.regs().VF[0].UL[1], mVU.regs().VF[0].UL[2], mVU.regs().VF[0].UL[3]);
//mVUprint("microVU: VI0 = %x", mVU.regs().VI[0].UL);
mVU->prog.x86ptr = x86Ptr;
mVU.prog.x86ptr = x86Ptr;
if ((xGetPtr() < mVU->prog.x86start) || (xGetPtr() >= mVU->prog.x86end)) {
Console.WriteLn(vuIndex ? Color_Orange : Color_Magenta, "microVU%d: Program cache limit reached.", mVU->index);
mVUreset(*mVU, false);
if ((xGetPtr() < mVU.prog.x86start) || (xGetPtr() >= mVU.prog.x86end)) {
Console.WriteLn(vuIndex ? Color_Orange : Color_Magenta, "microVU%d: Program cache limit reached.", mVU.index);
mVUreset(mVU, false);
}
mVU->cycles = mVU->totalCycles - mVU->cycles;
mVU->regs().cycle += mVU->cycles;
cpuRegs.cycle += ((mVU->cycles < 3000) ? mVU->cycles : 3000) * EmuConfig.Speedhacks.VUCycleSteal;
mVU.cycles = mVU.totalCycles - mVU.cycles;
mVU.regs().cycle += mVU.cycles;
cpuRegs.cycle += ((mVU.cycles < 3000) ? mVU.cycles : 3000) * EmuConfig.Speedhacks.VUCycleSteal;
//static int ax = 0; ax++;
//if (!(ax % 100000)) {
// for (u32 i = 0; i < (mVU->progSize / 2); i++) {
// for (u32 i = 0; i < (mVU.progSize / 2); i++) {
// if (mVUcurProg.block[i]) {
// mVUcurProg.block[i]->printInfo(i*8);
// }

View File

@ -37,7 +37,39 @@ struct mVU_Globals {
float ITOF_4[4], ITOF_12[4], ITOF_15[4];
};
extern const __aligned(32) mVU_Globals mVUglob;
#define __four(val) { val, val, val, val }
static const __aligned(32) mVU_Globals mVUglob = {
__four(0x7fffffff), // absclip
__four(0x80000000), // signbit
__four(0xff7fffff), // minvals
__four(0x7f7fffff), // maxvals
__four(0x3f800000), // ONE!
__four(0x3f490fdb), // PI4!
__four(0x3f7ffff5), // T1
__four(0xbeaaa61c), // T5
__four(0x3e4c40a6), // T2
__four(0xbe0e6c63), // T3
__four(0x3dc577df), // T4
__four(0xbd6501c4), // T6
__four(0x3cb31652), // T7
__four(0xbb84d7e7), // T8
__four(0xbe2aaaa4), // S2
__four(0x3c08873e), // S3
__four(0xb94fb21f), // S4
__four(0x362e9c14), // S5
__four(0x3e7fffa8), // E1
__four(0x3d0007f4), // E2
__four(0x3b29d3ff), // E3
__four(0x3933e553), // E4
__four(0x36b63510), // E5
__four(0x353961ac), // E6
__four(16.0), // FTOI_4
__four(4096.0), // FTOI_12
__four(32768.0), // FTOI_15
__four(0.0625f), // ITOF_4
__four(0.000244140625), // ITOF_12
__four(0.000030517578125) // ITOF_15
};
static const uint _Ibit_ = 1 << 31;
static const uint _Ebit_ = 1 << 30;
@ -125,18 +157,10 @@ static const uint divD = 0x2080000;
typedef void __fastcall Fntype_mVUrecInst( microVU* mVU, int recPass );
typedef Fntype_mVUrecInst* Fnptr_mVUrecInst;
// Recursive Inline
#ifndef __LINUX__
#define __recInline __ri
#else
#define __recInline inline
#endif
// Function/Template Stuff
#define mVUx (vuIndex ? &microVU1 : &microVU0)
#define mVUx (vuIndex ? microVU1 : microVU0)
#define mVUop(opName) static void __fastcall opName (mP)
#define _mVUt template<int vuIndex>
#define _r static __recInline
// Define Passes
#define pass1 if (recPass == 0)
@ -168,7 +192,6 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
//------------------------------------------------------------------
// Misc Macros...
#define __four(val) { val, val, val, val }
#define mVUcurProg mVU->prog.cur[0]
#define mVUblocks mVU->prog.cur->block
#define mVUir mVU->prog.IRinfo