microVU cleanups (mostly changing pointers to references)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4514 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2011-03-31 03:08:48 +00:00
parent 9afb0d9edf
commit 69896ce034
16 changed files with 517 additions and 511 deletions

View File

@ -77,10 +77,10 @@ void mVUreset(microVU& mVU, bool resetReserve) {
if (resetReserve) mVU.cache_reserve->Reset();
x86SetPtr(mVU.dispCache);
mVUdispatcherA(&mVU);
mVUdispatcherB(&mVU);
mVUdispatcherC(&mVU);
mVUdispatcherD(&mVU);
mVUdispatcherA(mVU);
mVUdispatcherB(mVU);
mVUdispatcherC(mVU);
mVUdispatcherD(mVU);
mVUemitSearch();
// Clear All Program Data
@ -134,12 +134,12 @@ void mVUclose(microVU& mVU) {
// Clears Block Data in specified range
__fi void mVUclear(mV, u32 addr, u32 size) {
if(!mVU->prog.cleared) {
mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram
memzero(mVU->prog.lpState); // Clear pipeline state
for(u32 i = 0; i < (mVU->progSize / 2); i++) {
mVU->prog.quick[i].block = NULL; // Clear current quick-reference block
mVU->prog.quick[i].prog = NULL; // Clear current quick-reference prog
if(!mVU.prog.cleared) {
mVU.prog.cleared = 1; // Next execution searches/creates a new microprogram
memzero(mVU.prog.lpState); // Clear pipeline state
for(u32 i = 0; i < (mVU.progSize / 2); i++) {
mVU.prog.quick[i].block = NULL; // Clear current quick-reference block
mVU.prog.quick[i].prog = NULL; // Clear current quick-reference prog
}
}
}
@ -150,7 +150,7 @@ __fi void mVUclear(mV, u32 addr, u32 size) {
// Finds and Ages/Kills Programs if they haven't been used in a while.
__ri void mVUvsyncUpdate(mV) {
//mVU->prog.curFrame++;
//mVU.prog.curFrame++;
}
// Deletes a program
@ -183,7 +183,7 @@ __ri microProgram* mVUcreateProg(microVU& mVU, int startPC) {
__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);
mVUdumpProg(mVU, prog);
}
// Generate Hash for partial program based on compiled ranges...
@ -230,7 +230,7 @@ __ri bool mVUcmpPartial(microVU& mVU, microProgram& prog) {
return 1;
}
// Compare Cached microProgram to mVU->regs().Micro
// Compare Cached microProgram to mVU.regs().Micro
__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))) {
@ -262,8 +262,8 @@ _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( mVU, startPC/8);
void* entryPoint = mVUblockFetch(&mVU, startPC, pState);
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);
@ -282,8 +282,8 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
recMicroVU0::recMicroVU0() { m_Idx = 0; IsInterpreter = false; }
recMicroVU1::recMicroVU1() { m_Idx = 1; IsInterpreter = false; }
void recMicroVU0::Vsync() throw() { mVUvsyncUpdate(&microVU0); }
void recMicroVU1::Vsync() throw() { mVUvsyncUpdate(&microVU1); }
void recMicroVU0::Vsync() throw() { mVUvsyncUpdate(microVU0); }
void recMicroVU1::Vsync() throw() { mVUvsyncUpdate(microVU1); }
void recMicroVU0::Reserve() {
if (AtomicExchange(m_Reserved, 1) == 0)
@ -331,11 +331,11 @@ void recMicroVU1::Execute(u32 cycles) {
void recMicroVU0::Clear(u32 addr, u32 size) {
pxAssert(m_Reserved); // please allocate me first! :|
mVUclear(&microVU0, addr, size);
mVUclear(microVU0, addr, size);
}
void recMicroVU1::Clear(u32 addr, u32 size) {
pxAssert(m_Reserved); // please allocate me first! :|
mVUclear(&microVU1, addr, size);
mVUclear(microVU1, addr, size);
}
uint recMicroVU0::GetCacheReserve() const {

View File

@ -155,7 +155,7 @@ struct microProgManager {
microProgramQuick quick[mProgSize/2]; // Quick reference to valid microPrograms for current execution
microProgram* cur; // Pointer to currently running MicroProgram
int total; // Total Number of valid MicroPrograms
int isSame; // Current cached microProgram is Exact Same program as mVU->regs().Micro (-1 = unknown, 0 = No, 1 = Yes)
int isSame; // Current cached microProgram is Exact Same program as mVU.regs().Micro (-1 = unknown, 0 = No, 1 = Yes)
int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one)
u32 curFrame; // Frame Counter
u8* x86ptr; // Pointer to program's recompilation code
@ -255,7 +255,7 @@ int mVUdebugNow = 0;
// Main Functions
extern void mVUclear(mV, u32, u32);
extern void mVUreset(microVU& mVU, bool resetReserve);
static void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
extern void* mVUblockFetch(microVU& mVU, u32 startPC, uptr pState);
_mVUt extern void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr);
// Prototypes for Linux

View File

@ -103,26 +103,26 @@ __ri void mVUallocSFLAGd(u32* memAddr, bool setAllflags) {
__fi void mVUallocMFLAGa(mV, const x32& reg, int fInstance)
{
xMOVZX(reg, ptr16[&mVU->macFlag[fInstance]]);
xMOVZX(reg, ptr16[&mVU.macFlag[fInstance]]);
}
__fi void mVUallocMFLAGb(mV, const x32& reg, int fInstance)
{
//xAND(reg, 0xffff);
if (fInstance < 4) xMOV(ptr32[&mVU->macFlag[fInstance]], reg); // microVU
else xMOV(ptr32[&mVU->regs().VI[REG_MAC_FLAG].UL], reg); // macroVU
if (fInstance < 4) xMOV(ptr32[&mVU.macFlag[fInstance]], reg); // microVU
else xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], reg); // macroVU
}
__fi void mVUallocCFLAGa(mV, const x32& reg, int fInstance)
{
if (fInstance < 4) xMOV(reg, ptr32[&mVU->clipFlag[fInstance]]); // microVU
else xMOV(reg, ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL]); // macroVU
if (fInstance < 4) xMOV(reg, ptr32[&mVU.clipFlag[fInstance]]); // microVU
else xMOV(reg, ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL]); // macroVU
}
__fi void mVUallocCFLAGb(mV, const x32& reg, int fInstance)
{
if (fInstance < 4) xMOV(ptr32[&mVU->clipFlag[fInstance]], reg); // microVU
else xMOV(ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL], reg); // macroVU
if (fInstance < 4) xMOV(ptr32[&mVU.clipFlag[fInstance]], reg); // microVU
else xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], reg); // macroVU
}
//------------------------------------------------------------------
@ -135,19 +135,19 @@ __ri void mVUallocVIa(mV, const x32& GPRreg, int _reg_, bool signext = false)
xXOR(GPRreg, GPRreg);
else
if (signext)
xMOVSX(GPRreg, ptr16[&mVU->regs().VI[_reg_].SL]);
xMOVSX(GPRreg, ptr16[&mVU.regs().VI[_reg_].SL]);
else
xMOVZX(GPRreg, ptr16[&mVU->regs().VI[_reg_].UL]);
xMOVZX(GPRreg, ptr16[&mVU.regs().VI[_reg_].UL]);
}
__ri void mVUallocVIb(mV, const x32& GPRreg, int _reg_)
{
if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch)
xMOVZX(gprT3, ptr16[&mVU->regs().VI[_reg_].UL]);
xMOV (ptr32[&mVU->VIbackup], gprT3);
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)); }
else if (_reg_ < 16) { xMOV(ptr16[&mVU.regs().VI[_reg_].UL], xRegister16(GPRreg.Id)); }
}
//------------------------------------------------------------------

View File

@ -445,7 +445,7 @@ __ri int mVUbranchCheck(mV) {
mVUlow.evilBranch = 1;
mVUregs.blockType = 2;
mVUregs.needExactMatch |= 7; // This might not be necessary, but w/e...
DevCon.Warning("microVU%d Warning: Branch in Branch delay slot! [%04x]", mVU->index, xPC);
DevCon.Warning("microVU%d Warning: Branch in Branch delay slot! [%04x]", mVU.index, xPC);
return 1;
}
incPC(2);
@ -482,7 +482,7 @@ __ri void mVUanalyzeJump(mV, int Is, int It, bool isJALR) {
if (mVUconstReg[Is].isValid && doConstProp) {
mVUlow.constJump.isValid = 1;
mVUlow.constJump.regValue = mVUconstReg[Is].regValue;
//DevCon.Status("microVU%d: Constant JR/JALR Address Optimization", mVU->index);
//DevCon.Status("microVU%d: Constant JR/JALR Address Optimization", mVU.index);
}
analyzeVIreg1(Is, mVUlow.VI_read[0]);
if (isJALR) {

View File

@ -15,9 +15,9 @@
#pragma once
extern bool doEarlyExit (microVU* mVU);
extern void mVUincCycles(microVU* mVU, int x);
extern void* mVUcompile (microVU* mVU, u32 startPC, uptr pState);
extern bool doEarlyExit (microVU& mVU);
extern void mVUincCycles(microVU& mVU, int x);
extern void* mVUcompile (microVU& mVU, u32 startPC, uptr pState);
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
#define sI ((mVUpBlock->pState.needExactMatch & 1) ? 3 : ((mVUpBlock->pState.flags >> 0) & 3))
@ -33,15 +33,15 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
int fClip = (isEbit) ? findFlagInst(mFC->xClip, 0x7fffffff) : cI;
int qInst = 0;
int pInst = 0;
mVU->regAlloc->flushAll();
mVU.regAlloc->flushAll();
if (isEbit) {
memzero(mVUinfo);
memzero(mVUregsTemp);
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
mVUcycles -= 100;
qInst = mVU->q;
pInst = mVU->p;
qInst = mVU.q;
pInst = mVU.p;
if (mVUinfo.doDivFlag) {
sFLAG.doFlag = 1;
sFLAG.write = fStatus;
@ -56,46 +56,46 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
// Save P/Q Regs
if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); }
xMOVSS(ptr32[&mVU->regs().VI[REG_Q].UL], xmmPQ);
xMOVSS(ptr32[&mVU.regs().VI[REG_Q].UL], xmmPQ);
if (isVU1) {
xPSHUF.D(xmmPQ, xmmPQ, pInst ? 3 : 2);
xMOVSS(ptr32[&mVU->regs().VI[REG_P].UL], xmmPQ);
xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ);
}
// Save Flag Instances
#if 1 // CHECK_MACROVU0 - Always on now
xMOV(ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus));
xMOV(ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus));
#else
mVUallocSFLAGc(gprT1, gprT2, fStatus);
xMOV(ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL], gprT1);
xMOV(ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL], gprT1);
#endif
mVUallocMFLAGa(mVU, gprT1, fMac);
mVUallocCFLAGa(mVU, gprT2, fClip);
xMOV(ptr32[&mVU->regs().VI[REG_MAC_FLAG].UL], gprT1);
xMOV(ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL], gprT2);
xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1);
xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2);
if (isEbit || isVU1) { // Clear 'is busy' Flags
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
xAND(ptr32[&mVU->getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
}
if (isEbit != 2) { // Save PC, and Jump to Exit Point
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC);
xJMP(mVU->exitFunct);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU.exitFunct);
}
}
// Recompiles Code for Proper Flags and Q/P regs on Block Linkings
void mVUsetupBranch(mV, microFlagCycles& mFC) {
mVU->regAlloc->flushAll(); // Flush Allocated Regs
mVU.regAlloc->flushAll(); // Flush Allocated Regs
mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances
// Shuffle P/Q regs since every block starts at instance #0
if (mVU->p || mVU->q) { xPSHUF.D(xmmPQ, xmmPQ, shufflePQ); }
if (mVU.p || mVU.q) { xPSHUF.D(xmmPQ, xmmPQ, shufflePQ); }
}
void normBranchCompile(microVU* mVU, u32 branchPC) {
void normBranchCompile(microVU& mVU, u32 branchPC) {
microBlock* pBlock;
blockCreate(branchPC/8);
pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs);
@ -112,12 +112,12 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) {
mVUpBlock->jumpCache = new microJumpCache[mProgSize/2];
}
if (isEvilJump) xMOV(gprT2, ptr32[&mVU->evilBranch]);
else xMOV(gprT2, ptr32[&mVU->branch]);
if (isEvilJump) xMOV(gprT2, ptr32[&mVU.evilBranch]);
else xMOV(gprT2, ptr32[&mVU.branch]);
if (doJumpCaching) xMOV(gprT3, (uptr)mVUpBlock);
else xMOV(gprT3, (uptr)&mVUpBlock->pStateEnd);
if (!mVU->index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState)
if (!mVU.index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState)
else xCALL(mVUcompileJIT<1>);
mVUrestoreRegs(mVU);
@ -136,19 +136,19 @@ void normBranch(mV, microFlagCycles& mFC) {
void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
mVUsetupBranch(mVU, mFC);
xCMP(ptr16[&mVU->branch], 0);
xCMP(ptr16[&mVU.branch], 0);
incPC(3);
if (mVUup.eBit) { // Conditional Branch With E-Bit Set
mVUendProgram(mVU, &mFC, 2);
xForwardJump8 eJMP((JccComparisonType)JMPcc);
incPC(1); // Set PC to First instruction of Non-Taken Side
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC);
xJMP(mVU->exitFunct);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU.exitFunct);
eJMP.SetTarget();
incPC(-4); // Go Back to Branch Opcode to get branchAddr
iPC = branchAddr/4;
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC);
xJMP(mVU->exitFunct);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU.exitFunct);
return;
}
else { // Normal Conditional Branch
@ -182,11 +182,11 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
void normJump(mV, microFlagCycles& mFC) {
if (mVUlow.constJump.isValid) { // Jump Address is Constant
if (mVUup.eBit) { // E-bit Jump
iPC = (mVUlow.constJump.regValue*2) & (mVU->progMemMask);
iPC = (mVUlow.constJump.regValue*2) & (mVU.progMemMask);
mVUendProgram(mVU, &mFC, 1);
return;
}
int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8);
int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU.microMemSize-8);
mVUsetupBranch(mVU, mFC);
normBranchCompile(mVU, jumpAddr);
return;
@ -194,9 +194,9 @@ void normJump(mV, microFlagCycles& mFC) {
if (mVUup.eBit) { // E-bit Jump
mVUendProgram(mVU, &mFC, 2);
xMOV(gprT1, ptr32[&mVU->branch]);
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], gprT1);
xJMP(mVU->exitFunct);
xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xJMP(mVU.exitFunct);
}
else normJumpCompile(mVU, mFC, 0);
}

View File

@ -54,7 +54,7 @@ void mVUclamp1(const xmm& reg, const xmm& regT1, int xyzw, bool bClampE = 0) {
// Note 2: Using regalloc here seems to contaminate some regs in certain games.
// Must be some specific case I've overlooked (or I used regalloc improperly on an opcode)
// so we just use a temporary mem location for our backup for now... (non-sse4 version only)
void mVUclamp2(microVU* mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool bClampE = 0) {
void mVUclamp2(microVU& mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool bClampE = 0) {
if ((!clampE && CHECK_VU_SIGN_OVERFLOW) || (clampE && bClampE && CHECK_VU_SIGN_OVERFLOW)) {
if (x86caps.hasStreamingSIMD4Extensions) {
int i = (xyzw==1||xyzw==2||xyzw==4||xyzw==8) ? 0: 1;
@ -62,9 +62,9 @@ void mVUclamp2(microVU* mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool
xPMIN.UD(reg, ptr128[&sse4_minvals[i][0]]);
return;
}
//const xmm& regT1 = regT1b ? mVU->regAlloc->allocReg() : regT1in;
//const xmm& regT1 = regT1b ? mVU.regAlloc->allocReg() : regT1in;
const xmm& regT1 = regT1in.IsEmpty() ? xmm((reg.Id + 1) % 8) : regT1in;
if (regT1 != regT1in) xMOVAPS(ptr128[mVU->xmmCTemp], regT1);
if (regT1 != regT1in) xMOVAPS(ptr128[mVU.xmmCTemp], regT1);
switch (xyzw) {
case 1: case 2: case 4: case 8:
xMOVAPS(regT1, reg);
@ -81,14 +81,14 @@ void mVUclamp2(microVU* mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool
xOR.PS (reg, regT1);
break;
}
//if (regT1 != regT1in) mVU->regAlloc->clearNeeded(regT1);
if (regT1 != regT1in) xMOVAPS(regT1, ptr128[mVU->xmmCTemp]);
//if (regT1 != regT1in) mVU.regAlloc->clearNeeded(regT1);
if (regT1 != regT1in) xMOVAPS(regT1, ptr128[mVU.xmmCTemp]);
}
else mVUclamp1(reg, regT1in, xyzw, bClampE);
}
// Used for operand clamping on every SSE instruction (add/sub/mul/div)
void mVUclamp3(microVU* mVU, const xmm& reg, const xmm& regT1, int xyzw) {
void mVUclamp3(microVU& mVU, const xmm& reg, const xmm& regT1, int xyzw) {
if (clampE) mVUclamp2(mVU, reg, regT1, xyzw, 1);
}

View File

@ -31,20 +31,20 @@ static void __fastcall mVUprintPC2(u32 pc) { Console.WriteLn("Block End PC =
//------------------------------------------------------------------
// Used by mVUsetupRange
static __fi void mVUcheckIsSame(mV) {
if (mVU->prog.isSame == -1) {
mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs().Micro, mVU->microMemSize);
__fi void mVUcheckIsSame(mV) {
if (mVU.prog.isSame == -1) {
mVU.prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU.regs().Micro, mVU.microMemSize);
}
if (mVU->prog.isSame == 0) {
mVUcacheProg(*mVU, *mVU->prog.cur);
mVU->prog.isSame = 1;
if (mVU.prog.isSame == 0) {
mVUcacheProg(mVU, *mVU.prog.cur);
mVU.prog.isSame = 1;
}
}
// Sets up microProgram PC ranges based on whats been recompiled
static void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {
void mVUsetupRange(microVU& mVU, s32 pc, bool isStartPC) {
deque<microRange>*& ranges = mVUcurProg.ranges;
pc &= mVU->microMemSize - 8;
pc &= mVU.microMemSize - 8;
if (isStartPC) { // Check if startPC is already within a block we've recompiled
deque<microRange>::const_iterator it(ranges->begin());
@ -81,13 +81,13 @@ static void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {
}
}
if (mergedRange) {
//DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Merging", mVU->index);
//DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Merging", mVU.index);
ranges->erase(ranges->begin());
}
}
else {
DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange.start, mVUrange.end);
mVUrange.end = mVU->microMemSize;
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);
}
@ -99,55 +99,55 @@ static void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {
__ri void doUpperOp(mV) { mVUopU(mVU, 1); mVUdivSet(mVU); }
__ri void doLowerOp(mV) { incPC(-1); mVUopL(mVU, 1); incPC(1); }
__ri void flushRegs(mV) { if (!doRegAlloc) mVU->regAlloc->flushAll(); }
__ri void flushRegs(mV) { if (!doRegAlloc) mVU.regAlloc->flushAll(); }
static void doIbit(mV) {
void doIbit(mV) {
if (mVUup.iBit) {
incPC(-1);
u32 tempI;
mVU->regAlloc->clearRegVF(33);
mVU.regAlloc->clearRegVF(33);
if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) {
DevCon.WriteLn(Color_Green,"microVU%d: Clamping I Reg", mVU->index);
DevCon.WriteLn(Color_Green,"microVU%d: Clamping I Reg", mVU.index);
tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg
}
else tempI = curI;
xMOV(ptr32[&mVU->getVI(REG_I)], tempI);
xMOV(ptr32[&mVU.getVI(REG_I)], tempI);
incPC(1);
}
}
static void doSwapOp(mV) {
void doSwapOp(mV) {
if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC);
// Allocate t1 first for better chance of reg-alloc
const xmm& t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg);
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& t1 = mVU.regAlloc->allocReg(mVUlow.VF_write.reg);
const xmm& t2 = mVU.regAlloc->allocReg();
xMOVAPS(t2, t1); // Backup VF reg
mVU->regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t1);
mVUopL(mVU, 1);
const xmm& t3 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
const xmm& t3 = mVU.regAlloc->allocReg(mVUlow.VF_write.reg, mVUlow.VF_write.reg, 0xf, 0);
xXOR.PS(t2, t3); // Swap new and old values of the register
xXOR.PS(t3, t2); // Uses xor swap trick...
xXOR.PS(t2, t3);
mVU->regAlloc->clearNeeded(t3);
mVU.regAlloc->clearNeeded(t3);
incPC(1);
doUpperOp(mVU);
const xmm& t4 = mVU->regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
const xmm& t4 = mVU.regAlloc->allocReg(-1, mVUlow.VF_write.reg, 0xf);
xMOVAPS(t4, t2);
mVU->regAlloc->clearNeeded(t4);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(t4);
mVU.regAlloc->clearNeeded(t2);
}
else { mVUopL(mVU, 1); incPC(1); flushRegs(mVU); doUpperOp(mVU); }
}
static void mVUexecuteInstruction(mV) {
void mVUexecuteInstruction(mV) {
if (mVUlow.isNOP) { incPC(1); doUpperOp(mVU); flushRegs(mVU); doIbit(mVU); }
elif(!mVUinfo.swapOps) { incPC(1); doUpperOp(mVU); flushRegs(mVU); doLowerOp(mVU); }
else doSwapOp(mVU);
@ -159,7 +159,7 @@ static void mVUexecuteInstruction(mV) {
//------------------------------------------------------------------
// If 1st op in block is a bad opcode, then don't compile rest of block (Dawn of Mana Level 2)
static __fi void mVUcheckBadOp(mV) {
__fi void mVUcheckBadOp(mV) {
if (mVUinfo.isBadOp && mVUcount == 0) {
mVUinfo.isEOB = true;
Console.Warning("microVU Warning: First Instruction of block contains illegal opcode...");
@ -167,10 +167,10 @@ static __fi void mVUcheckBadOp(mV) {
}
// Prints msg when exiting block early if 1st op was a bad opcode (Dawn of Mana Level 2)
static __fi void handleBadOp(mV, int count) {
__fi void handleBadOp(mV, int count) {
if (mVUinfo.isBadOp && count == 0) {
mVUbackupRegs(mVU, true);
xMOV(gprT2, mVU->prog.cur->idx);
xMOV(gprT2, mVU.prog.cur->idx);
xMOV(gprT3, xPC);
if (!isVU1) xCALL(mVUbadOp0);
else xCALL(mVUbadOp1);
@ -178,11 +178,11 @@ static __fi void handleBadOp(mV, int count) {
}
}
static __ri void branchWarning(mV) {
__ri void branchWarning(mV) {
incPC(-2);
if (mVUup.eBit && mVUbranch) {
incPC(2);
Console.Error("microVU%d Warning: Branch in E-bit delay slot! [%04x]", mVU->index, xPC);
Console.Error("microVU%d Warning: Branch in E-bit delay slot! [%04x]", mVU.index, xPC);
mVUlow.isNOP = 1;
}
else incPC(2);
@ -194,19 +194,19 @@ static __ri void branchWarning(mV) {
}
}
static __fi void eBitPass1(mV, int& branch) {
__fi void eBitPass1(mV, int& branch) {
if (mVUregs.blockType != 1) {
branch = 1;
mVUup.eBit = 1;
}
}
static __ri void eBitWarning(mV) {
if (mVUpBlock->pState.blockType == 1) Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", mVU->index, xPC);
if (mVUpBlock->pState.blockType == 2) Console.Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU->index, xPC);
__ri void eBitWarning(mV) {
if (mVUpBlock->pState.blockType == 1) Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", mVU.index, xPC);
if (mVUpBlock->pState.blockType == 2) Console.Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU.index, xPC);
incPC(2);
if (curI & _Ebit_) {
DevCon.Warning("microVU%d: E-bit in Branch delay slot! [%04x]", mVU->index, xPC);
DevCon.Warning("microVU%d: E-bit in Branch delay slot! [%04x]", mVU.index, xPC);
mVUregs.blockType = 1;
}
incPC(-2);
@ -218,14 +218,14 @@ static __ri void eBitWarning(mV) {
__fi void optimizeReg(u8& rState) { rState = (rState==1) ? 0 : rState; }
__fi void calcCycles(u8& reg, u8 x) { reg = ((reg > x) ? (reg - x) : 0); }
__fi void tCycles(u8& dest, u8& src) { dest = aMax(dest, src); }
__fi void incP(mV) { mVU->p ^= 1; }
__fi void incQ(mV) { mVU->q ^= 1; }
__fi void incP(mV) { mVU.p ^= 1; }
__fi void incQ(mV) { mVU.q ^= 1; }
// Optimizes the End Pipeline State Removing Unnecessary Info
// If the cycles remaining is just '1', we don't have to transfer it to the next block
// because mVU automatically decrements this number at the start of its loop,
// so essentially '1' will be the same as '0'...
static void mVUoptimizePipeState(mV) {
void mVUoptimizePipeState(mV) {
for (int i = 0; i < 32; i++) {
optimizeReg(mVUregs.VF[i].x);
optimizeReg(mVUregs.VF[i].y);
@ -312,7 +312,7 @@ void mVUsetCycles(mV) {
}
// Prints Start/End PC of blocks executed, for debugging...
static void mVUdebugPrintBlocks(microVU* mVU, bool isEndPC) {
void mVUdebugPrintBlocks(microVU& mVU, bool isEndPC) {
if (mVUdebugNow) {
mVUbackupRegs(mVU, true);
xMOV(gprT2, xPC);
@ -323,29 +323,29 @@ static void mVUdebugPrintBlocks(microVU* mVU, bool isEndPC) {
}
// vu0 is allowed to exit early, so are dev builds (for inf loops)
__fi bool doEarlyExit(microVU* mVU) {
__fi bool doEarlyExit(microVU& mVU) {
return IsDevBuild || !isVU1;
}
// Saves Pipeline State for resuming from early exits
static __fi void mVUsavePipelineState(microVU* mVU) {
u32* lpS = (u32*)&mVU->prog.lpState;
__fi void mVUsavePipelineState(microVU& mVU) {
u32* lpS = (u32*)&mVU.prog.lpState;
for (int i = 0; i < (sizeof(microRegInfo)-4)/4; i++, lpS++) {
xMOV(ptr32[lpS], lpS[0]);
}
}
// Test cycles to see if we need to exit-early...
static void mVUtestCycles(microVU* mVU) {
void mVUtestCycles(microVU& mVU) {
iPC = mVUstartPC;
if (doEarlyExit(mVU)) {
xCMP(ptr32[&mVU->cycles], 0);
xCMP(ptr32[&mVU.cycles], 0);
xForwardJG32 skip;
if (isVU0) {
// TEST32ItoM((uptr)&mVU->regs().flags, VUFLAG_MFLAGSET);
// TEST32ItoM((uptr)&mVU.regs().flags, VUFLAG_MFLAGSET);
// xFowardJZ32 vu0jmp;
// mVUbackupRegs(mVU, true);
// xMOV(gprT2, mVU->prog.cur->idx);
// xMOV(gprT2, mVU.prog.cur->idx);
// xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
// mVUbackupRegs(mVU, true);
mVUsavePipelineState(mVU);
@ -354,7 +354,7 @@ static void mVUtestCycles(microVU* mVU) {
}
else {
mVUbackupRegs(mVU, true);
xMOV(gprT2, mVU->prog.cur->idx);
xMOV(gprT2, mVU.prog.cur->idx);
xCALL(mVUwarning1);
mVUbackupRegs(mVU, true);
mVUsavePipelineState(mVU);
@ -362,7 +362,7 @@ static void mVUtestCycles(microVU* mVU) {
}
skip.SetTarget();
}
xSUB(ptr32[&mVU->cycles], mVUcycles);
xSUB(ptr32[&mVU.cycles], mVUcycles);
}
//------------------------------------------------------------------
@ -370,7 +370,7 @@ static void mVUtestCycles(microVU* mVU) {
//------------------------------------------------------------------
// This gets run at the start of every loop of mVU's first pass
static __fi void startLoop(mV) {
__fi void startLoop(mV) {
if (curI & _Mbit_) { DevCon.WriteLn (Color_Green, "microVU%d: M-bit set!", getIndex); }
if (curI & _Dbit_) { DevCon.WriteLn (Color_Green, "microVU%d: D-bit set!", getIndex); }
if (curI & _Tbit_) { DevCon.WriteLn (Color_Green, "microVU%d: T-bit set!", getIndex); }
@ -379,7 +379,7 @@ static __fi void startLoop(mV) {
}
// Initialize VI Constants (vi15 propagates through blocks)
static __fi void mVUinitConstValues(microVU* mVU) {
__fi void mVUinitConstValues(microVU& mVU) {
for (int i = 0; i < 16; i++) {
mVUconstReg[i].isValid = 0;
mVUconstReg[i].regValue = 0;
@ -389,18 +389,18 @@ static __fi void mVUinitConstValues(microVU* mVU) {
}
// Initialize Variables
static __fi void mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {
__fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr) {
mVUstartPC = iPC; // Block Start PC
mVUbranch = 0; // Branch Type
mVUcount = 0; // Number of instructions ran
mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage
mVU->p = 0; // All blocks start at p index #0
mVU->q = 0; // All blocks start at q index #0
mVU.p = 0; // All blocks start at p index #0
mVU.q = 0; // All blocks start at q index #0
if ((uptr)&mVUregs != pState) { // Loads up Pipeline State Info
memcpy_const((u8*)&mVUregs, (u8*)pState, sizeof(microRegInfo));
}
if (doEarlyExit(mVU) && ((uptr)&mVU->prog.lpState != pState)) {
memcpy_const((u8*)&mVU->prog.lpState, (u8*)pState, sizeof(microRegInfo));
if (doEarlyExit(mVU) && ((uptr)&mVU.prog.lpState != pState)) {
memcpy_const((u8*)&mVU.prog.lpState, (u8*)pState, sizeof(microRegInfo));
}
mVUblock.x86ptrStart = thisPtr;
mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager
@ -416,16 +416,16 @@ static __fi void mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {
// Recompiler
//------------------------------------------------------------------
void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) {
microFlagCycles mFC;
u8* thisPtr = x86Ptr;
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU->microMemSize / 8);
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU.microMemSize / 8);
// First Pass
iPC = startPC / 4;
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
mVU->regAlloc->reset(); // Reset regAlloc
mVU.regAlloc->reset(); // Reset regAlloc
mVUinitFirstPass(mVU, pState, thisPtr);
for (int branch = 0; mVUcount < endCount; mVUcount++) {
incPC(1);
@ -439,10 +439,10 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; }
else { incPC(-1); mVUopL(mVU, 0); incPC(1); }
mVUsetCycles(mVU);
mVUinfo.readQ = mVU->q;
mVUinfo.writeQ = !mVU->q;
mVUinfo.readP = mVU->p;
mVUinfo.writeP = !mVU->p;
mVUinfo.readQ = mVU.q;
mVUinfo.writeQ = !mVU.q;
mVUinfo.readP = mVU.p;
mVUinfo.writeP = !mVU.p;
if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; }
else if (branch == 1) { branch = 2; }
if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; }
@ -464,7 +464,7 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
u32 x = 0;
for (; x < endCount; x++) {
if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; }
if (mVUup.mBit) { xOR(ptr32[&mVU->regs().flags], VUFLAG_MFLAGSET); }
if (mVUup.mBit) { xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET); }
mVUexecuteInstruction(mVU);
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }
@ -485,7 +485,7 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
}
}
}
if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU->index); }
if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); }
// E-bit End
mVUsetupRange(mVU, xPC-8, 0);
@ -494,21 +494,21 @@ 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) {
__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)
static __fi void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
__fi void* mVUblockFetch(microVU& mVU, u32 startPC, uptr pState) {
pxAssumeDev((startPC & 7) == 0, pxsFmt("microVU%d: unaligned startPC=0x%04x", mVU->index, startPC) );
pxAssumeDev( startPC < mVU->microMemSize-8, pxsFmt("microVU%d: invalid startPC=0x%04x", mVU->index, startPC) );
startPC &= mVU->microMemSize-8;
pxAssumeDev((startPC & 7) == 0, pxsFmt("microVU%d: unaligned startPC=0x%04x", mVU.index, startPC) );
pxAssumeDev( startPC < mVU.microMemSize-8, pxsFmt("microVU%d: invalid startPC=0x%04x", mVU.index, startPC) );
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

View File

@ -21,7 +21,7 @@
// Generates the code for entering recompiled blocks
void mVUdispatcherA(mV) {
mVU->startFunct = x86Ptr;
mVU.startFunct = x86Ptr;
// Backup cpu state
xPUSH(ebp);
@ -43,35 +43,35 @@ void mVUdispatcherA(mV) {
// Load Regs
#if 1 // CHECK_MACROVU0 - Always on now
xMOV(gprF0, ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL]);
xMOV(gprF0, ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL]);
xMOV(gprF1, gprF0);
xMOV(gprF2, gprF0);
xMOV(gprF3, gprF0);
#else
mVUallocSFLAGd((uptr)&mVU->regs().VI[REG_STATUS_FLAG].UL, 1);
mVUallocSFLAGd((uptr)&mVU.regs().VI[REG_STATUS_FLAG].UL, 1);
#endif
xMOVAPS (xmmT1, ptr128[&mVU->regs().VI[REG_MAC_FLAG].UL]);
xMOVAPS (xmmT1, ptr128[&mVU.regs().VI[REG_MAC_FLAG].UL]);
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS (ptr128[mVU->macFlag], xmmT1);
xMOVAPS (ptr128[mVU.macFlag], xmmT1);
xMOVAPS (xmmT1, ptr128[&mVU->regs().VI[REG_CLIP_FLAG].UL]);
xMOVAPS (xmmT1, ptr128[&mVU.regs().VI[REG_CLIP_FLAG].UL]);
xSHUF.PS(xmmT1, xmmT1, 0);
xMOVAPS (ptr128[mVU->clipFlag], xmmT1);
xMOVAPS (ptr128[mVU.clipFlag], xmmT1);
xMOVAPS (xmmT1, ptr128[&mVU->regs().VI[REG_P].UL]);
xMOVAPS (xmmPQ, ptr128[&mVU->regs().VI[REG_Q].UL]);
xMOVAPS (xmmT1, ptr128[&mVU.regs().VI[REG_P].UL]);
xMOVAPS (xmmPQ, ptr128[&mVU.regs().VI[REG_Q].UL]);
xSHUF.PS(xmmPQ, xmmT1, 0); // wzyx = PPQQ
// Jump to Recompiled Code Block
xJMP(eax);
pxAssertDev(xGetPtr() < (mVU->dispCache + mVUdispCacheSize),
pxAssertDev(xGetPtr() < (mVU.dispCache + mVUdispCacheSize),
"microVU: Dispatcher generation exceeded reserved cache area!");
}
// Generates the code to exit from recompiled blocks
void mVUdispatcherB(mV) {
mVU->exitFunct = x86Ptr;
mVU.exitFunct = x86Ptr;
// Load EE's MXCSR state
xLDMXCSR(g_sseMXCSR);
@ -93,13 +93,13 @@ void mVUdispatcherB(mV) {
xPOP(ebp);
xRET();
pxAssertDev(xGetPtr() < (mVU->dispCache + mVUdispCacheSize),
pxAssertDev(xGetPtr() < (mVU.dispCache + mVUdispCacheSize),
"microVU: Dispatcher generation exceeded reserved cache area!");
}
// Generates the code for resuming xgkick
void mVUdispatcherC(mV) {
mVU->startFunctXG = x86Ptr;
mVU.startFunctXG = x86Ptr;
// Backup cpu state
xPUSH(ebp);
@ -117,29 +117,29 @@ void mVUdispatcherC(mV) {
mVUrestoreRegs(mVU);
xMOV(gprF0, ptr32[&mVU->statFlag[0]]);
xMOV(gprF1, ptr32[&mVU->statFlag[1]]);
xMOV(gprF2, ptr32[&mVU->statFlag[2]]);
xMOV(gprF3, ptr32[&mVU->statFlag[3]]);
xMOV(gprF0, ptr32[&mVU.statFlag[0]]);
xMOV(gprF1, ptr32[&mVU.statFlag[1]]);
xMOV(gprF2, ptr32[&mVU.statFlag[2]]);
xMOV(gprF3, ptr32[&mVU.statFlag[3]]);
// Jump to Recompiled Code Block
xJMP(ptr32[&mVU->resumePtrXG]);
pxAssertDev(xGetPtr() < (mVU->dispCache + mVUdispCacheSize),
xJMP(ptr32[&mVU.resumePtrXG]);
pxAssertDev(xGetPtr() < (mVU.dispCache + mVUdispCacheSize),
"microVU: Dispatcher generation exceeded reserved cache area!");
}
// Generates the code to exit from xgkick
void mVUdispatcherD(mV) {
mVU->exitFunctXG = x86Ptr;
mVU.exitFunctXG = x86Ptr;
//xPOP(gprT1); // Pop return address
//xMOV(ptr32[&mVU->resumePtrXG], gprT1);
//xMOV(ptr32[&mVU.resumePtrXG], gprT1);
// Backup Status Flag (other regs were backed up on xgkick)
xMOV(ptr32[&mVU->statFlag[0]], gprF0);
xMOV(ptr32[&mVU->statFlag[1]], gprF1);
xMOV(ptr32[&mVU->statFlag[2]], gprF2);
xMOV(ptr32[&mVU->statFlag[3]], gprF3);
xMOV(ptr32[&mVU.statFlag[0]], gprF0);
xMOV(ptr32[&mVU.statFlag[1]], gprF1);
xMOV(ptr32[&mVU.statFlag[2]], gprF2);
xMOV(ptr32[&mVU.statFlag[3]], gprF3);
// Load EE's MXCSR state
xLDMXCSR(g_sseMXCSR);
@ -156,7 +156,7 @@ void mVUdispatcherD(mV) {
xPOP(ebp);
xRET();
pxAssertDev(xGetPtr() < (mVU->dispCache + mVUdispCacheSize),
pxAssertDev(xGetPtr() < (mVU.dispCache + mVUdispCacheSize),
"microVU: Dispatcher generation exceeded reserved cache area!");
}

View File

@ -23,7 +23,7 @@ __fi void mVUdivSet(mV) {
if (mVUinfo.doDivFlag) {
if (!sFLAG.doFlag) { xMOV(getFlagReg(sFLAG.write), getFlagReg(sFLAG.lastWrite)); }
xAND(getFlagReg(sFLAG.write), 0xfff3ffff);
xOR (getFlagReg(sFLAG.write), ptr32[&mVU->divFlag]);
xOR (getFlagReg(sFLAG.write), ptr32[&mVU.divFlag]);
}
}
@ -166,7 +166,12 @@ __fi void mVUsetFlags(mV, microFlagCycles& mFC) {
// Recompiles Code for Proper Flags on Block Linkings
__fi void mVUsetupFlags(mV, microFlagCycles& mFC) {
const bool pf = 0; // Print Flag Info
if (pf) DevCon.WriteLn("mVU%d - [#%d][sPC=%04x][bPC=%04x][mVUBranch=%d][branch=%d]",
mVU.index, mVU.prog.cur->idx, mVUstartPC/2*8, xPC, mVUbranch, mVUlow.branch);
if (__Status) {
if (pf) DevCon.WriteLn("mVU%d - Status Flag", mVU.index);
int bStatus[4];
int sortRegs = sortFlag(mFC.xStatus, bStatus, mFC.cycles);
// DevCon::Status("sortRegs = %d", params sortRegs);
@ -205,19 +210,21 @@ __fi void mVUsetupFlags(mV, microFlagCycles& mFC) {
}
if (__Mac) {
if (pf) DevCon.WriteLn("mVU%d - Mac Flag", mVU.index);
int bMac[4];
sortFlag(mFC.xMac, bMac, mFC.cycles);
xMOVAPS(xmmT1, ptr128[mVU->macFlag]);
xMOVAPS(xmmT1, ptr128[mVU.macFlag]);
xSHUF.PS(xmmT1, xmmT1, shuffleMac);
xMOVAPS(ptr128[mVU->macFlag], xmmT1);
xMOVAPS(ptr128[mVU.macFlag], xmmT1);
}
if (__Clip) {
if (pf) DevCon.WriteLn("mVU%d - Clip Flag", mVU.index);
int bClip[4];
sortFlag(mFC.xClip, bClip, mFC.cycles);
xMOVAPS(xmmT2, ptr128[mVU->clipFlag]);
xMOVAPS(xmmT2, ptr128[mVU.clipFlag]);
xSHUF.PS(xmmT2, xmmT2, shuffleClip);
xMOVAPS(ptr128[mVU->clipFlag], xmmT2);
xMOVAPS(ptr128[mVU.clipFlag], xmmT2);
}
}
@ -287,7 +294,7 @@ __fi void mVUsetFlagInfo(mV) {
branchType1 { incPC(-1); mVUflagPass(mVU, branchAddr); incPC(1); }
branchType2 { // This case can possibly be turned off via a hack for a small speedup...
if (!mVUlow.constJump.isValid || !doConstProp) { mVUregs.needExactMatch |= 0x7; }
else { mVUflagPass(mVU, (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8)); }
else { mVUflagPass(mVU, (mVUlow.constJump.regValue*8)&(mVU.microMemSize-8)); }
}
branchType3 {
incPC(-1);

View File

@ -17,11 +17,11 @@
#include "Utilities/AsciiFile.h"
// writes text directly to mVU->logFile, no newlines appended.
// writes text directly to mVU.logFile, no newlines appended.
_mVUt void __mVULog(const char* fmt, ...) {
microVU* mVU = mVUx;
if (!mVU->logFile) return;
microVU& mVU = mVUx;
if (!mVU.logFile) return;
char tmp[2024];
va_list list;
@ -31,28 +31,27 @@ _mVUt void __mVULog(const char* fmt, ...) {
int length = vsprintf(tmp, fmt, list);
va_end(list);
mVU->logFile->Write( tmp );
mVU->logFile->Flush();
mVU.logFile->Write( tmp );
mVU.logFile->Flush();
}
#define commaIf() { if (bitX[6]) { mVUlog(","); bitX[6] = 0; } }
#include "AppConfig.h"
_mVUt void __mVUdumpProgram(microProgram& prog) {
microVU* mVU = mVUx;
void __mVUdumpProgram(microVU& mVU, microProgram& prog) {
bool bitX[7];
int delay = 0;
int bBranch = mVUbranch;
int bCode = mVU->code;
int bCode = mVU.code;
int bPC = iPC;
mVUbranch = 0;
const wxString logname(wxsFormat(L"microVU%d prog - %02d.html", vuIndex, prog.idx));
mVU->logFile = new AsciiFile(Path::Combine(g_Conf->Folders.Logs, logname), L"w");
const wxString logname(wxsFormat(L"microVU%d prog - %02d.html", mVU.index, prog.idx));
mVU.logFile = new AsciiFile(Path::Combine(g_Conf->Folders.Logs, logname), L"w");
mVUlog("<html>\n");
mVUlog("<title>microVU%d MicroProgram Log</title>\n", vuIndex);
mVUlog("<title>microVU%d MicroProgram Log</title>\n", mVU.index);
mVUlog("<body bgcolor=\"#000000\" LINK=\"#1111ff\" VLINK=\"#1111ff\">\n");
mVUlog("<font face=\"Courier New\" color=\"#ffffff\">\n");
@ -62,11 +61,11 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
mVUlog("*********************\n\n<br><br>", prog.idx);
mVUlog("</font>");
for (u32 i = 0; i < mVU->progSize; i+=2) {
for (u32 i = 0; i < mVU.progSize; i+=2) {
if (delay) { delay--; mVUlog("</font>"); if (!delay) mVUlog("<hr/>"); }
if (mVUbranch) { delay = 1; mVUbranch = 0; }
mVU->code = prog.data[i+1];
mVU.code = prog.data[i+1];
bitX[0] = 0;
bitX[1] = 0;
@ -76,18 +75,18 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
bitX[5] = 0;
bitX[6] = 0;
if (mVU->code & _Ibit_) { bitX[0] = 1; bitX[5] = 1; }
if (mVU->code & _Ebit_) { bitX[1] = 1; bitX[5] = 1; delay = 2; }
if (mVU->code & _Mbit_) { bitX[2] = 1; bitX[5] = 1; }
if (mVU->code & _Dbit_) { bitX[3] = 1; bitX[5] = 1; }
if (mVU->code & _Tbit_) { bitX[4] = 1; bitX[5] = 1; }
if (mVU.code & _Ibit_) { bitX[0] = 1; bitX[5] = 1; }
if (mVU.code & _Ebit_) { bitX[1] = 1; bitX[5] = 1; delay = 2; }
if (mVU.code & _Mbit_) { bitX[2] = 1; bitX[5] = 1; }
if (mVU.code & _Dbit_) { bitX[3] = 1; bitX[5] = 1; }
if (mVU.code & _Tbit_) { bitX[4] = 1; bitX[5] = 1; }
if (delay == 2) { mVUlog("<font color=\"#FFFF00\">"); }
if (delay == 1) { mVUlog("<font color=\"#999999\">"); }
iPC = (i+1);
mVUlog("<a name=\"addr%04x\">", i*4);
mVUlog("[%04x] (%08x)</a> ", i*4, mVU->code);
mVUlog("[%04x] (%08x)</a> ", i*4, mVU.code);
mVUopU(mVU, 2);
if (bitX[5]) {
@ -101,15 +100,15 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
}
iPC = i;
mVU->code = prog.data[i];
mVU.code = prog.data[i];
if(bitX[0]) {
mVUlog("<br>\n<font color=\"#FF7000\">");
mVUlog("[%04x] (%08x) %f", i*4, mVU->code, *(float*)&mVU->code);
mVUlog("[%04x] (%08x) %f", i*4, mVU.code, *(float*)&mVU.code);
mVUlog("</font>\n\n<br><br>");
}
else {
mVUlog("<br>\n[%04x] (%08x) ", i*4, mVU->code);
mVUlog("<br>\n[%04x] (%08x) ", i*4, mVU.code);
mVUopL(mVU, 2);
mVUlog("\n\n<br><br>");
}
@ -119,10 +118,10 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
mVUlog("</html>\n");
mVUbranch = bBranch;
mVU->code = bCode;
mVU.code = bCode;
iPC = bPC;
setCode();
mVU->logFile.Delete();
mVU.logFile.Delete();
}

View File

@ -41,7 +41,7 @@ static __fi void testNeg(mV, const xmm& xmmReg, const x32& gprTemp)
xMOVMSKPS(gprTemp, xmmReg);
xTEST(gprTemp, 1);
xForwardJZ8 skip;
xMOV(ptr32[&mVU->divFlag], divI);
xMOV(ptr32[&mVU.divFlag], divI);
xAND.PS(xmmReg, ptr128[mVUglob.absclip]);
skip.SetTarget();
}
@ -50,20 +50,20 @@ mVUop(mVU_DIV) {
pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 7); }
pass2 {
xmm Ft;
if (_Ftf_) Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
else Ft = mVU->regAlloc->allocReg(_Ft_);
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg();
if (_Ftf_) Ft = mVU.regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
else Ft = mVU.regAlloc->allocReg(_Ft_);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU.regAlloc->allocReg();
testZero(Ft, t1, gprT1); // Test if Ft is zero
xForwardJZ8 cjmp; // Skip if not zero
testZero(Fs, t1, gprT1); // Test if Fs is zero
xForwardJZ8 ajmp;
xMOV(ptr32[&mVU->divFlag], divI); // Set invalid flag (0/0)
xMOV(ptr32[&mVU.divFlag], divI); // Set invalid flag (0/0)
xForwardJump8 bjmp;
ajmp.SetTarget();
xMOV(ptr32[&mVU->divFlag], divD); // Zero divide (only when not 0/0)
xMOV(ptr32[&mVU.divFlag], divD); // Zero divide (only when not 0/0)
bjmp.SetTarget();
xXOR.PS(Fs, Ft);
@ -72,16 +72,16 @@ mVUop(mVU_DIV) {
xForwardJump8 djmp;
cjmp.SetTarget();
xMOV(ptr32[&mVU->divFlag], 0); // Clear I/D flags
xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags
SSE_DIVSS(mVU, Fs, Ft);
mVUclamp1(Fs, t1, 8, 1);
djmp.SetTarget();
writeQreg(Fs, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(t1);
}
pass3 { mVUlog("DIV Q, vf%02d%s, vf%02d%s", _Fs_, _Fsf_String, _Ft_, _Ftf_String); }
}
@ -89,16 +89,16 @@ mVUop(mVU_DIV) {
mVUop(mVU_SQRT) {
pass1 { mVUanalyzeFDIV(mVU, 0, 0, _Ft_, _Ftf_, 7); }
pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
xMOV(ptr32[&mVU->divFlag], 0); // Clear I/D flags
xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags
testNeg(mVU, Ft, gprT1); // Check for negative sqrt
if (CHECK_VU_OVERFLOW) xMIN.SS(Ft, ptr32[mVUglob.maxvals]); // Clamp infinities (only need to do positive clamp since xmmFt is positive)
xSQRT.SS(Ft, Ft);
writeQreg(Ft, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
pass3 { mVUlog("SQRT Q, vf%02d%s", _Ft_, _Ftf_String); }
}
@ -106,11 +106,11 @@ mVUop(mVU_SQRT) {
mVUop(mVU_RSQRT) {
pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 13); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
const xmm& t1 = mVU.regAlloc->allocReg();
xMOV(ptr32[&mVU->divFlag], 0); // Clear I/D flags
xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags
testNeg(mVU, Ft, gprT1); // Check for negative sqrt
xSQRT.SS(Ft, Ft);
@ -119,10 +119,10 @@ mVUop(mVU_RSQRT) {
testZero(Fs, t1, gprT1); // Test if Fs is zero
xForwardJZ8 bjmp; // Skip if none are
xMOV(ptr32[&mVU->divFlag], divI); // Set invalid flag (0/0)
xMOV(ptr32[&mVU.divFlag], divI); // Set invalid flag (0/0)
xForwardJump8 cjmp;
bjmp.SetTarget();
xMOV(ptr32[&mVU->divFlag], divD); // Zero divide flag (only when not 0/0)
xMOV(ptr32[&mVU.divFlag], divD); // Zero divide flag (only when not 0/0)
cjmp.SetTarget();
xAND.PS(Fs, ptr128[mVUglob.signbit]);
@ -136,9 +136,9 @@ mVUop(mVU_RSQRT) {
writeQreg(Fs, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(t1);
}
pass3 { mVUlog("RSQRT Q, vf%02d%s, vf%02d%s", _Fs_, _Fsf_String, _Ft_, _Ftf_String); }
}
@ -174,18 +174,18 @@ static __fi void mVU_EATAN_(mV, const xmm& PQ, const xmm& Fs, const xmm& t1, con
mVUop(mVU_EATAN) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 54); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs);
xSUB.SS(Fs, ptr32[mVUglob.one]);
xADD.SS(xmmPQ, ptr32[mVUglob.one]);
SSE_DIVSS(mVU, Fs, xmmPQ);
mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t2);
}
pass3 { mVUlog("EATAN P"); }
}
@ -193,9 +193,9 @@ mVUop(mVU_EATAN) {
mVUop(mVU_EATANxy) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 54); }
pass2 {
const xmm& t1 = mVU->regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Fs = mVU->regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& t1 = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Fs = mVU.regAlloc->allocReg();
const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(Fs, t1, 0x01);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs);
@ -203,9 +203,9 @@ mVUop(mVU_EATANxy) {
SSE_ADDSS (mVU, t1, xmmPQ);
SSE_DIVSS (mVU, Fs, t1);
mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t2);
}
pass3 { mVUlog("EATANxy P"); }
}
@ -213,9 +213,9 @@ mVUop(mVU_EATANxy) {
mVUop(mVU_EATANxz) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 54); }
pass2 {
const xmm& t1 = mVU->regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Fs = mVU->regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& t1 = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Fs = mVU.regAlloc->allocReg();
const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(Fs, t1, 0x02);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs);
@ -223,9 +223,9 @@ mVUop(mVU_EATANxz) {
SSE_ADDSS (mVU, t1, xmmPQ);
SSE_DIVSS (mVU, Fs, t1);
mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t2);
}
pass3 { mVUlog("EATANxz P"); }
}
@ -240,9 +240,9 @@ mVUop(mVU_EATANxz) {
mVUop(mVU_EEXP) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 44); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs);
xMUL.SS (xmmPQ, ptr32[mVUglob.E1]);
@ -264,9 +264,9 @@ mVUop(mVU_EEXP) {
SSE_DIVSS(mVU, t2, xmmPQ);
xMOVSS (xmmPQ, t2);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t2);
}
pass3 { mVUlog("EEXP P"); }
}
@ -290,12 +290,12 @@ static __fi void mVU_sumXYZ(mV, const xmm& PQ, const xmm& Fs) {
mVUop(mVU_ELENG) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 18); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs);
xSQRT.SS (xmmPQ, xmmPQ);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ELENG P"); }
}
@ -303,14 +303,14 @@ mVUop(mVU_ELENG) {
mVUop(mVU_ERCPR) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 12); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs);
xMOVSSZX (Fs, ptr32[mVUglob.one]);
SSE_DIVSS(mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ERCPR P"); }
}
@ -318,7 +318,7 @@ mVUop(mVU_ERCPR) {
mVUop(mVU_ERLENG) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 24); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs);
xSQRT.SS (xmmPQ, xmmPQ);
@ -326,7 +326,7 @@ mVUop(mVU_ERLENG) {
SSE_DIVSS (mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ERLENG P"); }
}
@ -334,14 +334,14 @@ mVUop(mVU_ERLENG) {
mVUop(mVU_ERSADD) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 18); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs);
xMOVSSZX (Fs, ptr32[mVUglob.one]);
SSE_DIVSS (mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ERSADD P"); }
}
@ -349,7 +349,7 @@ mVUop(mVU_ERSADD) {
mVUop(mVU_ERSQRT) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 18); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xAND.PS (Fs, ptr128[mVUglob.absclip]);
xSQRT.SS (xmmPQ, Fs);
@ -357,7 +357,7 @@ mVUop(mVU_ERSQRT) {
SSE_DIVSS(mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ERSQRT P"); }
}
@ -365,11 +365,11 @@ mVUop(mVU_ERSQRT) {
mVUop(mVU_ESADD) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 11); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ESADD P"); }
}
@ -384,9 +384,9 @@ mVUop(mVU_ESADD) {
mVUop(mVU_ESIN) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 29); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs);
xMOVAPS (t1, Fs);
@ -402,9 +402,9 @@ mVUop(mVU_ESIN) {
xMUL.SS (t2, ptr32[mVUglob.S5]);
SSE_ADDSS(mVU, xmmPQ, t2);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t2);
}
pass3 { mVUlog("ESIN P"); }
}
@ -412,12 +412,12 @@ mVUop(mVU_ESIN) {
mVUop(mVU_ESQRT) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 12); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xAND.PS (Fs, ptr128[mVUglob.absclip]);
xSQRT.SS(xmmPQ, Fs);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ESQRT P"); }
}
@ -425,8 +425,8 @@ mVUop(mVU_ESQRT) {
mVUop(mVU_ESUM) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 12); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& t1 = mVU.regAlloc->allocReg();
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xPSHUF.D (t1, Fs, 0x1b);
SSE_ADDPS(mVU, Fs, t1);
@ -434,8 +434,8 @@ mVUop(mVU_ESUM) {
SSE_ADDSS(mVU, Fs, t1);
xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
}
pass3 { mVUlog("ESUM P"); }
}
@ -719,11 +719,11 @@ mVUop(mVU_ISUBIU) {
mVUop(mVU_MFIR) {
pass1 { if (!_Ft_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeReg2(_Ft_, mVUlow.VF_write, 1); }
pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
mVUallocVIa(mVU, gprT1, _Is_, true);
xMOVDZX(Ft, gprT1);
if (!_XYZW_SS) { mVUunpack_xyzw(Ft, Ft, 0); }
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
pass3 { mVUlog("MFIR.%s vf%02d, vi%02d", _XYZW_String, _Ft_, _Fs_); }
}
@ -731,9 +731,9 @@ mVUop(mVU_MFIR) {
mVUop(mVU_MFP) {
pass1 { mVUanalyzeMFP(mVU, _Ft_); }
pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
getPreg(mVU, Ft);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
pass3 { mVUlog("MFP.%s vf%02d, P", _XYZW_String, _Ft_); }
}
@ -741,8 +741,8 @@ mVUop(mVU_MFP) {
mVUop(mVU_MOVE) {
pass1 { mVUanalyzeMOVE(mVU, _Fs_, _Ft_); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W);
mVU->regAlloc->clearNeeded(Fs);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("MOVE.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); }
}
@ -750,12 +750,12 @@ mVUop(mVU_MOVE) {
mVUop(mVU_MR32) {
pass1 { mVUanalyzeMR32(mVU, _Fs_, _Ft_); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_);
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
if (_XYZW_SS) mVUunpack_xyzw(Ft, Fs, (_X ? 1 : (_Y ? 2 : (_Z ? 3 : 0))));
else xPSHUF.D(Ft, Fs, 0x39);
mVU->regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("MR32.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); }
}
@ -763,10 +763,10 @@ mVUop(mVU_MR32) {
mVUop(mVU_MTIR) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeReg5(_Fs_, _Fsf_, mVUlow.VF_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 1); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
xMOVD(gprT1, Fs);
mVUallocVIb(mVU, gprT1, _It_);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("MTIR vi%02d, vf%02d%s", _Ft_, _Fs_, _Fsf_String); }
}
@ -778,7 +778,7 @@ mVUop(mVU_MTIR) {
mVUop(mVU_ILW) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem + offsetSS);
xAddressVoid ptr(mVU.regs().Mem + offsetSS);
if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_);
xADD(gprT2, _Imm11_);
@ -796,7 +796,7 @@ mVUop(mVU_ILW) {
mVUop(mVU_ILWR) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem + offsetSS);
xAddressVoid ptr(mVU.regs().Mem + offsetSS);
if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_);
mVUaddrFix (mVU, gprT2);
@ -815,7 +815,7 @@ mVUop(mVU_ILWR) {
mVUop(mVU_ISW) {
pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_);
xADD(gprT2, _Imm11_);
@ -836,7 +836,7 @@ mVUop(mVU_ISW) {
mVUop(mVU_ISWR) {
pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_);
mVUaddrFix (mVU, gprT2);
@ -858,7 +858,7 @@ mVUop(mVU_ISWR) {
mVUop(mVU_LQ) {
pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 0); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_);
xADD(gprT2, _Imm11_);
@ -867,9 +867,9 @@ mVUop(mVU_LQ) {
}
else
ptr += getVUmem(_Imm11_);
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
mVUloadReg(Ft, ptr, _X_Y_Z_W);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
pass3 { mVUlog("LQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); }
}
@ -877,7 +877,7 @@ mVUop(mVU_LQ) {
mVUop(mVU_LQD) {
pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_);
xSUB(gprT2b, 1);
@ -886,9 +886,9 @@ mVUop(mVU_LQD) {
ptr += gprT2;
}
if (!mVUlow.noWriteVF) {
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
mVUloadReg(Ft, ptr, _X_Y_Z_W);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
}
pass3 { mVUlog("LQD.%s vf%02d, --vi%02d", _XYZW_String, _Ft_, _Is_); }
@ -897,7 +897,7 @@ mVUop(mVU_LQD) {
mVUop(mVU_LQI) {
pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) {
mVUallocVIa(mVU, gprT1, _Is_);
xMOV(gprT2, gprT1);
@ -907,9 +907,9 @@ mVUop(mVU_LQI) {
ptr += gprT2;
}
if (!mVUlow.noWriteVF) {
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
mVUloadReg(Ft, ptr, _X_Y_Z_W);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
}
pass3 { mVUlog("LQI.%s vf%02d, vi%02d++", _XYZW_String, _Ft_, _Fs_); }
@ -922,7 +922,7 @@ mVUop(mVU_LQI) {
mVUop(mVU_SQ) {
pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 0); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_It_) {
mVUallocVIa(mVU, gprT2, _It_);
xADD(gprT2, _Imm11_);
@ -931,9 +931,9 @@ mVUop(mVU_SQ) {
}
else
ptr += getVUmem(_Imm11_);
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("SQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Fs_, _Ft_, _Imm11_); }
}
@ -941,7 +941,7 @@ mVUop(mVU_SQ) {
mVUop(mVU_SQD) {
pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_It_) {
mVUallocVIa(mVU, gprT2, _It_);
xSUB(gprT2b, 1);
@ -949,9 +949,9 @@ mVUop(mVU_SQD) {
mVUaddrFix (mVU, gprT2);
ptr += gprT2;
}
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("SQD.%s vf%02d, --vi%02d", _XYZW_String, _Fs_, _Ft_); }
}
@ -959,7 +959,7 @@ mVUop(mVU_SQD) {
mVUop(mVU_SQI) {
pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); }
pass2 {
xAddressVoid ptr(mVU->regs().Mem);
xAddressVoid ptr(mVU.regs().Mem);
if (_It_) {
mVUallocVIa(mVU, gprT1, _It_);
xMOV(gprT2, gprT1);
@ -968,9 +968,9 @@ mVUop(mVU_SQI) {
mVUaddrFix (mVU, gprT2);
ptr += gprT2;
}
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("SQI.%s vf%02d, vi%02d++", _XYZW_String, _Fs_, _Ft_); }
}
@ -983,12 +983,12 @@ mVUop(mVU_RINIT) {
pass1 { mVUanalyzeR1(mVU, _Fs_, _Fsf_); }
pass2 {
if (_Fs_ || (_Fsf_ == 3)) {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
xMOVD(gprT1, Fs);
xAND(gprT1, 0x007fffff);
xOR (gprT1, 0x3f800000);
xMOV(ptr32[Rmem], gprT1);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
else xMOV(ptr32[Rmem], 0x3f800000);
}
@ -997,10 +997,10 @@ mVUop(mVU_RINIT) {
static __fi void mVU_RGET_(mV, const x32& Rreg) {
if (!mVUlow.noWriteVF) {
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
xMOVDZX(Ft, Rreg);
if (!_XYZW_SS) mVUunpack_xyzw(Ft, Ft, 0);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
}
}
@ -1038,11 +1038,11 @@ mVUop(mVU_RXOR) {
pass1 { mVUanalyzeR1(mVU, _Fs_, _Fsf_); }
pass2 {
if (_Fs_ || (_Fsf_ == 3)) {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
xMOVD(gprT1, Fs);
xAND(gprT1, 0x7fffff);
xXOR(ptr32[Rmem], gprT1);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
}
pass3 { mVUlog("RXOR R, vf%02d%s", _Fs_, _Fsf_String); }
@ -1069,7 +1069,7 @@ mVUop(mVU_WAITQ) {
mVUop(mVU_XTOP) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); }
pass2 {
xMOVZX(gprT1, ptr16[&mVU->getVifRegs().top]);
xMOVZX(gprT1, ptr16[&mVU.getVifRegs().top]);
mVUallocVIb(mVU, gprT1, _It_);
}
pass3 { mVUlog("XTOP vi%02d", _Ft_); }
@ -1078,7 +1078,7 @@ mVUop(mVU_XTOP) {
mVUop(mVU_XITOP) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); }
pass2 {
xMOVZX(gprT1, ptr16[&mVU->getVifRegs().itop]);
xMOVZX(gprT1, ptr16[&mVU.getVifRegs().itop]);
xAND(gprT1, isVU1 ? 0x3ff : 0xff);
mVUallocVIb(mVU, gprT1, _It_);
}
@ -1153,10 +1153,10 @@ static __fi void mVU_XGKICK_DELAY(mV, bool memVI) {
mVUbackupRegs(mVU);
#if 0 // XGkick Break - ToDo: Change "SomeGifPathValue" to w/e needs to be tested
xTEST (ptr32[&SomeGifPathValue], 1); // If '1', breaks execution
xMOV (ptr32[&mVU->resumePtrXG], (uptr)xGetPtr() + 10 + 6);
xJcc32(Jcc_NotZero, (uptr)mVU->exitFunctXG - ((uptr)xGetPtr()+6));
xMOV (ptr32[&mVU.resumePtrXG], (uptr)xGetPtr() + 10 + 6);
xJcc32(Jcc_NotZero, (uptr)mVU.exitFunctXG - ((uptr)xGetPtr()+6));
#endif
if (memVI) xMOV(gprT2, ptr32[&mVU->VIxgkick]);
if (memVI) xMOV(gprT2, ptr32[&mVU.VIxgkick]);
else mVUallocVIa(mVU, gprT2, _Is_);
xCALL(mVU_XGKICK_);
mVUrestoreRegs(mVU);
@ -1168,7 +1168,7 @@ mVUop(mVU_XGKICK) {
if (!mVU_XGKICK_CYCLES) { mVU_XGKICK_DELAY(mVU, 0); return; }
else if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); mVUinfo.doXGKICK = 0; }
mVUallocVIa(mVU, gprT1, _Is_);
xMOV(ptr32[&mVU->VIxgkick], gprT1);
xMOV(ptr32[&mVU.VIxgkick], gprT1);
}
pass3 { mVUlog("XGKICK vi%02d", _Fs_); }
}
@ -1180,7 +1180,7 @@ mVUop(mVU_XGKICK) {
void setBranchA(mP, int x, int _x_) {
pass1 {
if (_Imm11_ == 1 && !_x_) {
DevCon.WriteLn(Color_Green, "microVU%d: Branch Optimization", mVU->index);
DevCon.WriteLn(Color_Green, "microVU%d: Branch Optimization", mVU.index);
mVUlow.isNOP = 1;
return;
}
@ -1194,21 +1194,21 @@ void setBranchA(mP, int x, int _x_) {
void condEvilBranch(mV, int JMPcc) {
if (mVUlow.badBranch) {
xMOV(ptr32[&mVU->branch], gprT1);
xMOV(ptr32[&mVU->badBranch], branchAddrN);
xMOV(ptr32[&mVU.branch], gprT1);
xMOV(ptr32[&mVU.badBranch], branchAddrN);
xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
incPC(4); // Branch Not Taken
xMOV(ptr32[&mVU->badBranch], xPC);
xMOV(ptr32[&mVU.badBranch], xPC);
incPC(-4);
cJMP.SetTarget();
return;
}
xMOV(ptr32[&mVU->evilBranch], branchAddr);
xMOV(ptr32[&mVU.evilBranch], branchAddr);
xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
xMOV(gprT1, ptr32[&mVU->badBranch]); // Branch Not Taken
xMOV(ptr32[&mVU->evilBranch], gprT1);
xMOV(gprT1, ptr32[&mVU.badBranch]); // Branch Not Taken
xMOV(ptr32[&mVU.evilBranch], gprT1);
cJMP.SetTarget();
}
@ -1216,8 +1216,8 @@ mVUop(mVU_B) {
setBranchA(mX, 1, 0);
pass1 { mVUanalyzeNormBranch(mVU, 0, 0); }
pass2 {
if (mVUlow.badBranch) { xMOV(ptr32[&mVU->badBranch], branchAddrN); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU->evilBranch], branchAddr); }
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); }
}
pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr, branchAddr); }
}
@ -1228,8 +1228,8 @@ mVUop(mVU_BAL) {
pass2 {
xMOV(gprT1, bSaveAddr);
mVUallocVIb(mVU, gprT1, _It_);
if (mVUlow.badBranch) { xMOV(ptr32[&mVU->badBranch], branchAddrN); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU->evilBranch], branchAddr); }
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); }
}
pass3 { mVUlog("BAL vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, branchAddr, branchAddr); }
}
@ -1238,13 +1238,13 @@ mVUop(mVU_IBEQ) {
setBranchA(mX, 3, 0);
pass1 { mVUanalyzeCondBranch2(mVU, _Is_, _It_); }
pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_);
if (mVUlow.memReadIt) xXOR(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIt) xXOR(gprT1, ptr32[&mVU.VIbackup]);
else { mVUallocVIa(mVU, gprT2, _It_); xXOR(gprT1, gprT2); }
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_Equal);
}
pass3 { mVUlog("IBEQ vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); }
@ -1254,9 +1254,9 @@ mVUop(mVU_IBGEZ) {
setBranchA(mX, 4, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_GreaterOrEqual);
}
pass3 { mVUlog("IBGEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1266,9 +1266,9 @@ mVUop(mVU_IBGTZ) {
setBranchA(mX, 5, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_Greater);
}
pass3 { mVUlog("IBGTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1278,9 +1278,9 @@ mVUop(mVU_IBLEZ) {
setBranchA(mX, 6, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_LessOrEqual);
}
pass3 { mVUlog("IBLEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1290,9 +1290,9 @@ mVUop(mVU_IBLTZ) {
setBranchA(mX, 7, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_Less);
}
pass3 { mVUlog("IBLTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1302,13 +1302,13 @@ mVUop(mVU_IBNE) {
setBranchA(mX, 8, 0);
pass1 { mVUanalyzeCondBranch2(mVU, _Is_, _It_); }
pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_);
if (mVUlow.memReadIt) xXOR(gprT1, ptr32[&mVU->VIbackup]);
if (mVUlow.memReadIt) xXOR(gprT1, ptr32[&mVU.VIbackup]);
else { mVUallocVIa(mVU, gprT2, _It_); xXOR(gprT1, gprT2); }
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_NotEqual);
}
pass3 { mVUlog("IBNE vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); }
@ -1318,14 +1318,14 @@ void normJumpPass2(mV) {
if (!mVUlow.constJump.isValid || mVUlow.evilBranch) {
mVUallocVIa(mVU, gprT1, _Is_);
xSHL(gprT1, 3);
xAND(gprT1, mVU->microMemSize - 8);
xMOV(ptr32[&mVU->branch], gprT1);
if (!mVUlow.evilBranch) xMOV(ptr32[&mVU->branch], gprT1);
else xMOV(ptr32[&mVU->evilBranch], gprT1);
xAND(gprT1, mVU.microMemSize - 8);
xMOV(ptr32[&mVU.branch], gprT1);
if (!mVUlow.evilBranch) xMOV(ptr32[&mVU.branch], gprT1);
else xMOV(ptr32[&mVU.evilBranch], gprT1);
if (mVUlow.badBranch) {
xADD(gprT1, 8);
xAND(gprT1, mVU->microMemSize - 8);
xMOV(ptr32[&mVU->badBranch], gprT1);
xAND(gprT1, mVU.microMemSize - 8);
xMOV(ptr32[&mVU.badBranch], gprT1);
}
}
}

View File

@ -70,12 +70,12 @@ void endMacroOp(int mode) {
void recV##f() { \
setupMacroOp(mode, opName); \
if (mode & 4) { \
mVU_##f(&microVU0, 0); \
mVU_##f(microVU0, 0); \
if (!microVU0.prog.IRinfo.info[0].lOp.isNOP) { \
mVU_##f(&microVU0, 1); \
mVU_##f(microVU0, 1); \
} \
} \
else { mVU_##f(&microVU0, 1); } \
else { mVU_##f(microVU0, 1); } \
endMacroOp(mode); \
}

View File

@ -85,43 +85,43 @@ static const uint divD = 0x2080000;
// Helper Macros
//------------------------------------------------------------------
#define _Ft_ ((mVU->code >> 16) & 0x1F) // The ft part of the instruction register
#define _Fs_ ((mVU->code >> 11) & 0x1F) // The fs part of the instruction register
#define _Fd_ ((mVU->code >> 6) & 0x1F) // The fd part of the instruction register
#define _Ft_ ((mVU.code >> 16) & 0x1F) // The ft part of the instruction register
#define _Fs_ ((mVU.code >> 11) & 0x1F) // The fs part of the instruction register
#define _Fd_ ((mVU.code >> 6) & 0x1F) // The fd part of the instruction register
#define _It_ ((mVU->code >> 16) & 0xF) // The it part of the instruction register
#define _Is_ ((mVU->code >> 11) & 0xF) // The is part of the instruction register
#define _Id_ ((mVU->code >> 6) & 0xF) // The id part of the instruction register
#define _It_ ((mVU.code >> 16) & 0xF) // The it part of the instruction register
#define _Is_ ((mVU.code >> 11) & 0xF) // The is part of the instruction register
#define _Id_ ((mVU.code >> 6) & 0xF) // The id part of the instruction register
#define _X ((mVU->code>>24) & 0x1)
#define _Y ((mVU->code>>23) & 0x1)
#define _Z ((mVU->code>>22) & 0x1)
#define _W ((mVU->code>>21) & 0x1)
#define _X ((mVU.code>>24) & 0x1)
#define _Y ((mVU.code>>23) & 0x1)
#define _Z ((mVU.code>>22) & 0x1)
#define _W ((mVU.code>>21) & 0x1)
#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF))
#define _X_Y_Z_W (((mVU.code >> 21 ) & 0xF))
#define _XYZW_SS (_X+_Y+_Z+_W==1)
#define _XYZW_SS2 (_XYZW_SS && (_X_Y_Z_W != 8))
#define _XYZW_PS (_X_Y_Z_W == 0xf)
#define _XYZWss(x) ((x==8) || (x==4) || (x==2) || (x==1))
#define _bc_ (mVU->code & 0x3)
#define _bc_x ((mVU->code & 0x3) == 0)
#define _bc_y ((mVU->code & 0x3) == 1)
#define _bc_z ((mVU->code & 0x3) == 2)
#define _bc_w ((mVU->code & 0x3) == 3)
#define _bc_ (mVU.code & 0x3)
#define _bc_x ((mVU.code & 0x3) == 0)
#define _bc_y ((mVU.code & 0x3) == 1)
#define _bc_z ((mVU.code & 0x3) == 2)
#define _bc_w ((mVU.code & 0x3) == 3)
#define _Fsf_ ((mVU->code >> 21) & 0x03)
#define _Ftf_ ((mVU->code >> 23) & 0x03)
#define _Fsf_ ((mVU.code >> 21) & 0x03)
#define _Ftf_ ((mVU.code >> 23) & 0x03)
#define _Imm5_ (mVU->Imm5())
#define _Imm11_ (mVU->Imm11())
#define _Imm12_ (mVU->Imm12())
#define _Imm15_ (mVU->Imm15())
#define _Imm24_ (mVU->Imm24())
#define _Imm5_ (mVU.Imm5())
#define _Imm11_ (mVU.Imm11())
#define _Imm12_ (mVU.Imm12())
#define _Imm15_ (mVU.Imm15())
#define _Imm24_ (mVU.Imm24())
#define isCOP2 (mVU->cop2 != 0)
#define isVU1 (mVU->index != 0)
#define isVU0 (mVU->index == 0)
#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)))
@ -149,12 +149,12 @@ static const uint divD = 0x2080000;
#define gprF3 edi // Status Flag 3
// Function Params
#define mP microVU* mVU, int recPass
#define mV microVU* mVU
#define mP microVU& mVU, int recPass
#define mV microVU& mVU
#define mF int recPass
#define mX mVU, recPass
typedef void __fastcall Fntype_mVUrecInst( microVU* mVU, int recPass );
typedef void __fastcall Fntype_mVUrecInst(microVU& mVU, int recPass);
typedef Fntype_mVUrecInst* Fnptr_mVUrecInst;
// Function/Template Stuff
@ -192,21 +192,21 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
//------------------------------------------------------------------
// Misc Macros...
#define mVUcurProg mVU->prog.cur[0]
#define mVUblocks mVU->prog.cur->block
#define mVUir mVU->prog.IRinfo
#define mVUbranch mVU->prog.IRinfo.branch
#define mVUcycles mVU->prog.IRinfo.cycles
#define mVUcount mVU->prog.IRinfo.count
#define mVUpBlock mVU->prog.IRinfo.pBlock
#define mVUblock mVU->prog.IRinfo.block
#define mVUregs mVU->prog.IRinfo.block.pState
#define mVUregsTemp mVU->prog.IRinfo.regsTemp
#define iPC mVU->prog.IRinfo.curPC
#define mVUsFlagHack mVU->prog.IRinfo.sFlagHack
#define mVUconstReg mVU->prog.IRinfo.constReg
#define mVUstartPC mVU->prog.IRinfo.startPC
#define mVUinfo mVU->prog.IRinfo.info[iPC / 2]
#define mVUcurProg mVU.prog.cur[0]
#define mVUblocks mVU.prog.cur->block
#define mVUir mVU.prog.IRinfo
#define mVUbranch mVU.prog.IRinfo.branch
#define mVUcycles mVU.prog.IRinfo.cycles
#define mVUcount mVU.prog.IRinfo.count
#define mVUpBlock mVU.prog.IRinfo.pBlock
#define mVUblock mVU.prog.IRinfo.block
#define mVUregs mVU.prog.IRinfo.block.pState
#define mVUregsTemp mVU.prog.IRinfo.regsTemp
#define iPC mVU.prog.IRinfo.curPC
#define mVUsFlagHack mVU.prog.IRinfo.sFlagHack
#define mVUconstReg mVU.prog.IRinfo.constReg
#define mVUstartPC mVU.prog.IRinfo.startPC
#define mVUinfo mVU.prog.IRinfo.info[iPC / 2]
#define mVUstall mVUinfo.stall
#define mVUup mVUinfo.uOp
#define mVUlow mVUinfo.lOp
@ -217,18 +217,18 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define isEvilBlock (mVUpBlock->pState.blockType == 2)
#define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch)
#define xPC ((iPC / 2) * 8)
#define curI ((u32*)mVU->regs().Micro)[iPC] //mVUcurProg.data[iPC]
#define setCode() { mVU->code = curI; }
#define curI ((u32*)mVU.regs().Micro)[iPC] //mVUcurProg.data[iPC]
#define setCode() { mVU.code = curI; }
#define incPC(x) (mVU->advancePC(x))
#define branchAddr mVU->getBranchAddr()
#define branchAddrN mVU->getBranchAddrN()
#define incPC(x) (mVU.advancePC(x))
#define branchAddr mVU.getBranchAddr()
#define branchAddrN mVU.getBranchAddrN()
#define incPC2(x) { iPC = ((iPC + (x)) & mVU->progMemMask); }
#define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8)
#define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04))
#define incPC2(x) { iPC = ((iPC + (x)) & mVU.progMemMask); }
#define bSaveAddr (((xPC + 16) & (mVU.microMemSize-8)) / 8)
#define shufflePQ (((mVU.p) ? 0xb0 : 0xe0) | ((mVU.q) ? 0x01 : 0x04))
#define cmpOffset(x) ((u8*)&(((u8*)x)[it[0].start]))
#define Rmem &mVU->regs().VI[REG_R].UL
#define Rmem &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))))
#define clampE CHECK_VU_EXTRA_OVERFLOW
@ -257,7 +257,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
// Program Logging...
#ifdef mVUlogProg
#define mVUlog ((isVU1) ? __mVULog<1> : __mVULog<0>)
#define mVUdumpProg __mVUdumpProgram<vuIndex>
#define mVUdumpProg __mVUdumpProgram
#else
#define mVUlog(...) if (0) {}
#define mVUdumpProg(...) if (0) {}

View File

@ -214,28 +214,28 @@ void mVUmergeRegs(const xmm& dest, const xmm& src, int xyzw, bool modXYZW)
//------------------------------------------------------------------
// Backup Volatile Regs (EAX, ECX, EDX, MM0~7, XMM0~7, are all volatile according to 32bit Win/Linux ABI)
__fi void mVUbackupRegs(microVU* mVU, bool toMemory = false)
__fi void mVUbackupRegs(microVU& mVU, bool toMemory = false)
{
if (toMemory) {
for(int i = 0; i < 8; i++) {
xMOVAPS(ptr128[&mVU->xmmBackup[i][0]], xmm(i));
xMOVAPS(ptr128[&mVU.xmmBackup[i][0]], xmm(i));
}
}
else {
mVU->regAlloc->flushAll(); // Flush Regalloc
xMOVAPS(ptr128[&mVU->xmmBackup[xmmPQ.Id][0]], xmmPQ);
mVU.regAlloc->flushAll(); // Flush Regalloc
xMOVAPS(ptr128[&mVU.xmmBackup[xmmPQ.Id][0]], xmmPQ);
}
}
// Restore Volatile Regs
__fi void mVUrestoreRegs(microVU* mVU, bool fromMemory = false)
__fi void mVUrestoreRegs(microVU& mVU, bool fromMemory = false)
{
if (fromMemory) {
for(int i = 0; i < 8; i++) {
xMOVAPS(xmm(i), ptr128[&mVU->xmmBackup[i][0]]);
xMOVAPS(xmm(i), ptr128[&mVU.xmmBackup[i][0]]);
}
}
else xMOVAPS(xmmPQ, ptr128[&mVU->xmmBackup[xmmPQ.Id][0]]);
else xMOVAPS(xmmPQ, ptr128[&mVU.xmmBackup[xmmPQ.Id][0]]);
}
// Gets called by mVUaddrFix at execution-time
@ -259,7 +259,7 @@ __fi void mVUaddrFix(mV, const x32& gprReg)
xPUSH(gprT1); // Note: Kernel does it via COP2 to initialize VU1!
xPUSH(gprT2); // So we don't spam console, we'll only check micro-mode...
xPUSH(gprT3);
xMOV (gprT2, mVU->prog.cur->idx);
xMOV (gprT2, mVU.prog.cur->idx);
xMOV (gprT3, xPC);
xCALL(mVUwarningRegAccess);
xPOP (gprT3);
@ -288,10 +288,10 @@ static const __aligned16 SSEMaskPair MIN_MAX =
// Warning: Modifies t1 and t2
void MIN_MAX_PS(microVU* mVU, const xmm& to, const xmm& from, const xmm& t1in, const xmm& t2in, bool min)
void MIN_MAX_PS(microVU& mVU, const xmm& to, const xmm& from, const xmm& t1in, const xmm& t2in, bool min)
{
const xmm& t1 = t1in.IsEmpty() ? mVU->regAlloc->allocReg() : t1in;
const xmm& t2 = t2in.IsEmpty() ? mVU->regAlloc->allocReg() : t2in;
const xmm& t1 = t1in.IsEmpty() ? mVU.regAlloc->allocReg() : t1in;
const xmm& t2 = t2in.IsEmpty() ? mVU.regAlloc->allocReg() : t2in;
// ZW
xPSHUF.D(t1, to, 0xfa);
xPAND (t1, ptr128[MIN_MAX.mask1]);
@ -313,28 +313,28 @@ void MIN_MAX_PS(microVU* mVU, const xmm& to, const xmm& from, const xmm& t1in, c
else xMAX.PD(to, t2);
xSHUF.PS(to, t1, 0x88);
if (t1 != t1in) mVU->regAlloc->clearNeeded(t1);
if (t2 != t2in) mVU->regAlloc->clearNeeded(t2);
if (t1 != t1in) mVU.regAlloc->clearNeeded(t1);
if (t2 != t2in) mVU.regAlloc->clearNeeded(t2);
}
// Warning: Modifies to's upper 3 vectors, and t1
void MIN_MAX_SS(mV, const xmm& to, const xmm& from, const xmm& t1in, bool min)
{
const xmm& t1 = t1in.IsEmpty() ? mVU->regAlloc->allocReg() : t1in;
const xmm& t1 = t1in.IsEmpty() ? mVU.regAlloc->allocReg() : t1in;
xSHUF.PS(to, from, 0);
xPAND (to, ptr128[MIN_MAX.mask1]);
xPOR (to, ptr128[MIN_MAX.mask2]);
xPSHUF.D(t1, to, 0xee);
if (min) xMIN.PD(to, t1);
else xMAX.PD(to, t1);
if (t1 != t1in) mVU->regAlloc->clearNeeded(t1);
if (t1 != t1in) mVU.regAlloc->clearNeeded(t1);
}
// Warning: Modifies all vectors in 'to' and 'from', and Modifies xmmT1 and xmmT2
void ADD_SS(microVU* mVU, const xmm& to, const xmm& from, const xmm& t1in, const xmm& t2in)
void ADD_SS(microVU& mVU, const xmm& to, const xmm& from, const xmm& t1in, const xmm& t2in)
{
const xmm& t1 = t1in.IsEmpty() ? mVU->regAlloc->allocReg() : t1in;
const xmm& t2 = t2in.IsEmpty() ? mVU->regAlloc->allocReg() : t2in;
const xmm& t1 = t1in.IsEmpty() ? mVU.regAlloc->allocReg() : t1in;
const xmm& t2 = t2in.IsEmpty() ? mVU.regAlloc->allocReg() : t2in;
xMOVAPS(t1, to);
xMOVAPS(t2, from);
@ -397,8 +397,8 @@ void ADD_SS(microVU* mVU, const xmm& to, const xmm& from, const xmm& t1in, const
xAND.PS(to, t1); // to contains mask
xAND.PS(from, t2); // from contains mask
xADD.SS(to, from);
if (t1 != t1in) mVU->regAlloc->clearNeeded(t1);
if (t2 != t2in) mVU->regAlloc->clearNeeded(t2);
if (t1 != t1in) mVU.regAlloc->clearNeeded(t1);
if (t2 != t2in) mVU.regAlloc->clearNeeded(t2);
}
#define clampOp(opX, isPS) { \

View File

@ -199,20 +199,20 @@ static const Fnptr_mVUrecInst mVU_UPPER_FD_11_TABLE [32] = {
// Table Functions
//------------------------------------------------------------------
mVUop(mVU_UPPER_FD_00) { mVU_UPPER_FD_00_TABLE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVU_UPPER_FD_01) { mVU_UPPER_FD_01_TABLE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVU_UPPER_FD_10) { mVU_UPPER_FD_10_TABLE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVU_UPPER_FD_11) { mVU_UPPER_FD_11_TABLE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP) { mVULowerOP_OPCODE [ (mVU->code & 0x3f) ](mX); }
mVUop(mVULowerOP_T3_00) { mVULowerOP_T3_00_OPCODE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_01) { mVULowerOP_T3_01_OPCODE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_10) { mVULowerOP_T3_10_OPCODE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_11) { mVULowerOP_T3_11_OPCODE [((mVU->code >> 6) & 0x1f)](mX); }
mVUop(mVUopU) { mVU_UPPER_OPCODE [ (mVU->code & 0x3f) ](mX); } // Gets Upper Opcode
mVUop(mVUopL) { mVULOWER_OPCODE [ (mVU->code >> 25) ](mX); } // Gets Lower Opcode
mVUop(mVU_UPPER_FD_00) { mVU_UPPER_FD_00_TABLE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVU_UPPER_FD_01) { mVU_UPPER_FD_01_TABLE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVU_UPPER_FD_10) { mVU_UPPER_FD_10_TABLE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVU_UPPER_FD_11) { mVU_UPPER_FD_11_TABLE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP) { mVULowerOP_OPCODE [ (mVU.code & 0x3f) ](mX); }
mVUop(mVULowerOP_T3_00) { mVULowerOP_T3_00_OPCODE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_01) { mVULowerOP_T3_01_OPCODE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_10) { mVULowerOP_T3_10_OPCODE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_11) { mVULowerOP_T3_11_OPCODE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVUopU) { mVU_UPPER_OPCODE [ (mVU.code & 0x3f) ](mX); } // Gets Upper Opcode
mVUop(mVUopL) { mVULOWER_OPCODE [ (mVU.code >> 25) ](mX); } // Gets Lower Opcode
mVUop(mVUunknown) {
pass1 { mVUinfo.isBadOp = true; }
pass2 { Console.Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", getIndex, mVU->code, xPC); }
pass3 { mVUlog("Unknown", mVU->code); }
pass2 { Console.Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", getIndex, mVU.code, xPC); }
pass3 { mVUlog("Unknown", mVU.code); }
}

View File

@ -33,13 +33,13 @@ static void mVUupdateFlags(mV, const xmm& reg, const xmm& regT1in = xEmptyReg, c
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
const xmm& regT1 = regT1b ? mVU->regAlloc->allocReg() : regT1in;
const xmm& regT1 = regT1b ? mVU.regAlloc->allocReg() : regT1in;
xmm regT2 = reg;
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) {
regT2 = regT2in;
if (regT2.IsEmpty()) {
regT2 = mVU->regAlloc->allocReg();
regT2 = mVU.regAlloc->allocReg();
regT2b = true;
}
xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw
@ -77,15 +77,15 @@ static void mVUupdateFlags(mV, const xmm& reg, const xmm& regT1in = xEmptyReg, c
xOR (sReg, mReg);
}
}
if (regT1b) mVU->regAlloc->clearNeeded(regT1);
if (regT2b) mVU->regAlloc->clearNeeded(regT2);
if (regT1b) mVU.regAlloc->clearNeeded(regT1);
if (regT2b) mVU.regAlloc->clearNeeded(regT2);
}
//------------------------------------------------------------------
// Helper Macros and Functions
//------------------------------------------------------------------
static void (*const SSE_PS[]) (microVU*, const xmm&, const xmm&, const xmm&, const xmm&) = {
static void (*const SSE_PS[]) (microVU&, const xmm&, const xmm&, const xmm&, const xmm&) = {
SSE_ADDPS, // 0
SSE_SUBPS, // 1
SSE_MULPS, // 2
@ -94,7 +94,7 @@ static void (*const SSE_PS[]) (microVU*, const xmm&, const xmm&, const xmm&, con
SSE_ADD2PS // 5
};
static void (*const SSE_SS[]) (microVU*, const xmm&, const xmm&, const xmm&, const xmm&) = {
static void (*const SSE_SS[]) (microVU&, const xmm&, const xmm&, const xmm&, const xmm&) = {
SSE_ADDSS, // 0
SSE_SUBSS, // 1
SSE_MULSS, // 2
@ -110,7 +110,7 @@ enum clampModes {
};
// Prints Opcode to MicroProgram Logs
static void mVU_printOP(microVU* mVU, int opCase, const char* opName, bool isACC) {
static void mVU_printOP(microVU& mVU, int opCase, const char* opName, bool isACC) {
mVUlog(opName);
opCase1 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogFt(); }
opCase2 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogBC(); }
@ -119,7 +119,7 @@ static void mVU_printOP(microVU* mVU, int opCase, const char* opName, bool isACC
}
// Sets Up Pass1 Info for Normal, BC, I, and Q Cases
static void setupPass1(microVU* mVU, int opCase, bool isACC, bool noFlagUpdate) {
static void setupPass1(microVU& mVU, int opCase, bool isACC, bool noFlagUpdate) {
opCase1 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); }
opCase2 { mVUanalyzeFMAC3(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); }
opCase3 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, 0); }
@ -128,13 +128,13 @@ static void setupPass1(microVU* mVU, int opCase, bool isACC, bool noFlagUpdate)
}
// Safer to force 0 as the result for X minus X than to do actual subtraction
static bool doSafeSub(microVU* mVU, int opCase, int opType, bool isACC) {
static bool doSafeSub(microVU& mVU, int opCase, int opType, bool isACC) {
opCase1 {
if ((opType == 1) && (_Ft_ == _Fs_)) {
const xmm& Fs = mVU->regAlloc->allocReg(-1, isACC ? 32 : _Fd_, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(-1, isACC ? 32 : _Fd_, _X_Y_Z_W);
xPXOR(Fs, Fs); // Set to Positive 0
mVUupdateFlags(mVU, Fs);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
return 1;
}
}
@ -142,28 +142,28 @@ static bool doSafeSub(microVU* mVU, int opCase, int opType, bool isACC) {
}
// Sets Up Ft Reg for Normal, BC, I, and Q Cases
static void setupFtReg(microVU* mVU, xmm& Ft, xmm& tempFt, int opCase) {
static void setupFtReg(microVU& mVU, xmm& Ft, xmm& tempFt, int opCase) {
opCase1 {
if (_XYZW_SS2) { Ft = mVU->regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W); tempFt = Ft; }
else if (clampE) { Ft = mVU->regAlloc->allocReg(_Ft_, 0, 0xf); tempFt = Ft; }
else { Ft = mVU->regAlloc->allocReg(_Ft_); tempFt = xEmptyReg; }
if (_XYZW_SS2) { Ft = mVU.regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W); tempFt = Ft; }
else if (clampE) { Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0xf); tempFt = Ft; }
else { Ft = mVU.regAlloc->allocReg(_Ft_); tempFt = xEmptyReg; }
}
opCase2 {
tempFt = mVU->regAlloc->allocReg(_Ft_);
Ft = mVU->regAlloc->allocReg();
tempFt = mVU.regAlloc->allocReg(_Ft_);
Ft = mVU.regAlloc->allocReg();
mVUunpack_xyzw(Ft, tempFt, _bc_);
mVU->regAlloc->clearNeeded(tempFt);
mVU.regAlloc->clearNeeded(tempFt);
tempFt = Ft;
}
opCase3 { Ft = mVU->regAlloc->allocReg(33, 0, _X_Y_Z_W); tempFt = Ft; }
opCase3 { Ft = mVU.regAlloc->allocReg(33, 0, _X_Y_Z_W); tempFt = Ft; }
opCase4 {
if (!clampE && _XYZW_SS && !mVUinfo.readQ) { Ft = xmmPQ; tempFt = xEmptyReg; }
else { Ft = mVU->regAlloc->allocReg(); tempFt = Ft; getQreg(Ft, mVUinfo.readQ); }
else { Ft = mVU.regAlloc->allocReg(); tempFt = Ft; getQreg(Ft, mVUinfo.readQ); }
}
}
// Normal FMAC Opcodes
static void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool isACC, const char* opName, int clampType) {
static void mVU_FMACa(microVU& mVU, int recPass, int opCase, int opType, bool isACC, const char* opName, int clampType) {
pass1 { setupPass1(mVU, opCase, isACC, ((opType == 3) || (opType == 4))); }
pass2 {
if (doSafeSub(mVU, opCase, opType, isACC)) return;
@ -172,11 +172,11 @@ static void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool is
setupFtReg(mVU, Ft, tempFt, opCase);
if (isACC) {
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU->regAlloc->allocReg((_X_Y_Z_W == 0xf) ? -1 : 32, 32, 0xf, 0);
Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU.regAlloc->allocReg((_X_Y_Z_W == 0xf) ? -1 : 32, 32, 0xf, 0);
if (_XYZW_SS2) xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W));
}
else { Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W); }
else { Fs = mVU.regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W); }
if (clampType & cFt) mVUclamp2(mVU, Ft, xEmptyReg, _X_Y_Z_W);
if (clampType & cFs) mVUclamp2(mVU, Fs, xEmptyReg, _X_Y_Z_W);
@ -189,26 +189,26 @@ static void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool is
else mVUmergeRegs(ACC, Fs, _X_Y_Z_W);
mVUupdateFlags(mVU, ACC, Fs, tempFt);
if (_XYZW_SS2) xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W));
mVU->regAlloc->clearNeeded(ACC);
mVU.regAlloc->clearNeeded(ACC);
}
else mVUupdateFlags(mVU, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU.regAlloc->clearNeeded(Ft);
}
pass3 { mVU_printOP(mVU, opCase, opName, isACC); }
pass4 { if ((opType != 3) && (opType != 4)) mVUregs.needExactMatch |= 8; }
}
// MADDA/MSUBA Opcodes
static void mVU_FMACb(microVU* mVU, int recPass, int opCase, int opType, const char* opName, int clampType) {
static void mVU_FMACb(microVU& mVU, int recPass, int opCase, int opType, const char* opName, int clampType) {
pass1 { setupPass1(mVU, opCase, 1, 0); }
pass2 {
xmm Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU->regAlloc->allocReg(32, 32, 0xf, 0);
Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU.regAlloc->allocReg(32, 32, 0xf, 0);
if (_XYZW_SS2) { xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
@ -225,31 +225,31 @@ static void mVU_FMACb(microVU* mVU, int recPass, int opCase, int opType, const c
if (_XYZW_SS && _X_Y_Z_W != 8) xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W));
}
else {
const xmm& tempACC = mVU->regAlloc->allocReg();
const xmm& tempACC = mVU.regAlloc->allocReg();
xMOVAPS(tempACC, ACC);
SSE_PS[opType](mVU, tempACC, Fs, tempFt, xEmptyReg);
mVUmergeRegs(ACC, tempACC, _X_Y_Z_W);
mVUupdateFlags(mVU, ACC, Fs, tempFt);
mVU->regAlloc->clearNeeded(tempACC);
mVU.regAlloc->clearNeeded(tempACC);
}
mVU->regAlloc->clearNeeded(ACC);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(ACC);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
}
pass3 { mVU_printOP(mVU, opCase, opName, 1); }
pass4 { mVUregs.needExactMatch |= 8; }
}
// MADD Opcodes
static void mVU_FMACc(microVU* mVU, int recPass, int opCase, const char* opName, int clampType) {
static void mVU_FMACc(microVU& mVU, int recPass, int opCase, const char* opName, int clampType) {
pass1 { setupPass1(mVU, opCase, 0, 0); }
pass2 {
xmm Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
ACC = mVU->regAlloc->allocReg(32);
Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W);
ACC = mVU.regAlloc->allocReg(32);
Fs = mVU.regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W);
if (_XYZW_SS2) { xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
@ -264,23 +264,23 @@ static void mVU_FMACc(microVU* mVU, int recPass, int opCase, const char* opName,
mVUupdateFlags(mVU, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(ACC);
mVU.regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU.regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(ACC);
}
pass3 { mVU_printOP(mVU, opCase, opName, 0); }
pass4 { mVUregs.needExactMatch |= 8; }
}
// MSUB Opcodes
static void mVU_FMACd(microVU* mVU, int recPass, int opCase, const char* opName, int clampType) {
static void mVU_FMACd(microVU& mVU, int recPass, int opCase, const char* opName, int clampType) {
pass1 { setupPass1(mVU, opCase, 0, 0); }
pass2 {
xmm Fs, Ft, Fd, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
Fd = mVU->regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
Fd = mVU.regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
if (clampType & cFt) mVUclamp2(mVU, Ft, xEmptyReg, _X_Y_Z_W);
if (clampType & cFs) mVUclamp2(mVU, Fs, xEmptyReg, _X_Y_Z_W);
@ -291,9 +291,9 @@ static void mVU_FMACd(microVU* mVU, int recPass, int opCase, const char* opName,
mVUupdateFlags(mVU, Fd, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fd); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fd); // Always Clear Written Reg First
mVU.regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVU_printOP(mVU, opCase, opName, 0); }
pass4 { mVUregs.needExactMatch |= 8; }
@ -304,9 +304,9 @@ mVUop(mVU_ABS) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 {
if (!_Ft_) return;
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
xAND.PS(Fs, ptr128[mVUglob.absclip]);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("ABS"); mVUlogFtFs(); }
}
@ -315,15 +315,15 @@ mVUop(mVU_ABS) {
mVUop(mVU_OPMULA) {
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); }
pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W);
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 32, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 32, _X_Y_Z_W);
xPSHUF.D(Fs, Fs, 0xC9); // WXZY
xPSHUF.D(Ft, Ft, 0xD2); // WYXZ
SSE_MULPS(mVU, Fs, Ft);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Ft);
mVUupdateFlags(mVU, Fs);
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog("OPMULA"); mVUlogACC(); mVUlogFt(); }
pass4 { mVUregs.needExactMatch |= 8; }
@ -333,18 +333,18 @@ mVUop(mVU_OPMULA) {
mVUop(mVU_OPMSUB) {
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); }
pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, 0xf);
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& ACC = mVU->regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0xf);
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& ACC = mVU.regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
xPSHUF.D(Fs, Fs, 0xC9); // WXZY
xPSHUF.D(Ft, Ft, 0xD2); // WYXZ
SSE_MULPS(mVU, Fs, Ft);
SSE_SUBPS(mVU, ACC, Fs);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
mVUupdateFlags(mVU, ACC);
mVU->regAlloc->clearNeeded(ACC);
mVU.regAlloc->clearNeeded(ACC);
}
pass3 { mVUlog("OPMSUB"); mVUlogFd(); mVUlogFt(); }
@ -356,9 +356,9 @@ static void mVU_FTOIx(mP, const float* addr, const char* opName) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 {
if (!_Ft_) return;
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU.regAlloc->allocReg();
// Note: For help understanding this algorithm see recVUMI_FTOI_Saturate()
xMOVAPS(t1, Fs);
@ -371,9 +371,9 @@ static void mVU_FTOIx(mP, const float* addr, const char* opName) {
xAND.PS(t1, t2);
xPADD.D(Fs, t1);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(t2);
}
pass3 { mVUlog(opName); mVUlogFtFs(); }
}
@ -383,13 +383,13 @@ static void mVU_ITOFx(mP, const float* addr, const char* opName) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 {
if (!_Ft_) return;
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf)));
xCVTDQ2PS(Fs, Fs);
if (addr) { xMUL.PS(Fs, ptr128[addr]); }
//mVUclamp2(Fs, xmmT1, 15); // Clamp (not sure if this is needed)
mVU->regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Fs);
}
pass3 { mVUlog(opName); mVUlogFtFs(); }
}
@ -398,9 +398,9 @@ static void mVU_ITOFx(mP, const float* addr, const char* opName) {
mVUop(mVU_CLIP) {
pass1 { mVUanalyzeFMAC4(mVU, _Fs_, _Ft_); }
pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, 0x1);
const xmm& t1 = mVU->regAlloc->allocReg();
const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0x1);
const xmm& t1 = mVU.regAlloc->allocReg();
mVUunpack_xyzw(Ft, Ft, 0);
mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite);
@ -428,9 +428,9 @@ mVUop(mVU_CLIP) {
xAND(gprT1, 0xffffff);
mVUallocCFLAGb(mVU, gprT1, cFLAG.write);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(t1);
mVU.regAlloc->clearNeeded(Fs);
mVU.regAlloc->clearNeeded(Ft);
mVU.regAlloc->clearNeeded(t1);
}
pass3 { mVUlog("CLIP"); mVUlogCLIP(); }
}