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

View File

@ -155,7 +155,7 @@ struct microProgManager {
microProgramQuick quick[mProgSize/2]; // Quick reference to valid microPrograms for current execution microProgramQuick quick[mProgSize/2]; // Quick reference to valid microPrograms for current execution
microProgram* cur; // Pointer to currently running MicroProgram microProgram* cur; // Pointer to currently running MicroProgram
int total; // Total Number of valid MicroPrograms 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) 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 u32 curFrame; // Frame Counter
u8* x86ptr; // Pointer to program's recompilation code u8* x86ptr; // Pointer to program's recompilation code
@ -255,7 +255,7 @@ int mVUdebugNow = 0;
// Main Functions // Main Functions
extern void mVUclear(mV, u32, u32); extern void mVUclear(mV, u32, u32);
extern void mVUreset(microVU& mVU, bool resetReserve); 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); _mVUt extern void* __fastcall mVUcompileJIT(u32 startPC, uptr ptr);
// Prototypes for Linux // 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) __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) __fi void mVUallocMFLAGb(mV, const x32& reg, int fInstance)
{ {
//xAND(reg, 0xffff); //xAND(reg, 0xffff);
if (fInstance < 4) xMOV(ptr32[&mVU->macFlag[fInstance]], reg); // microVU if (fInstance < 4) xMOV(ptr32[&mVU.macFlag[fInstance]], reg); // microVU
else xMOV(ptr32[&mVU->regs().VI[REG_MAC_FLAG].UL], reg); // macroVU else xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], reg); // macroVU
} }
__fi void mVUallocCFLAGa(mV, const x32& reg, int fInstance) __fi void mVUallocCFLAGa(mV, const x32& reg, int fInstance)
{ {
if (fInstance < 4) xMOV(reg, ptr32[&mVU->clipFlag[fInstance]]); // microVU if (fInstance < 4) xMOV(reg, ptr32[&mVU.clipFlag[fInstance]]); // microVU
else xMOV(reg, ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL]); // macroVU else xMOV(reg, ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL]); // macroVU
} }
__fi void mVUallocCFLAGb(mV, const x32& reg, int fInstance) __fi void mVUallocCFLAGb(mV, const x32& reg, int fInstance)
{ {
if (fInstance < 4) xMOV(ptr32[&mVU->clipFlag[fInstance]], reg); // microVU if (fInstance < 4) xMOV(ptr32[&mVU.clipFlag[fInstance]], reg); // microVU
else xMOV(ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL], reg); // macroVU 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); xXOR(GPRreg, GPRreg);
else else
if (signext) if (signext)
xMOVSX(GPRreg, ptr16[&mVU->regs().VI[_reg_].SL]); xMOVSX(GPRreg, ptr16[&mVU.regs().VI[_reg_].SL]);
else 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_) __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) if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch)
xMOVZX(gprT3, ptr16[&mVU->regs().VI[_reg_].UL]); xMOVZX(gprT3, ptr16[&mVU.regs().VI[_reg_].UL]);
xMOV (ptr32[&mVU->VIbackup], gprT3); xMOV (ptr32[&mVU.VIbackup], gprT3);
} }
if (_reg_ == 0) { return; } 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; mVUlow.evilBranch = 1;
mVUregs.blockType = 2; mVUregs.blockType = 2;
mVUregs.needExactMatch |= 7; // This might not be necessary, but w/e... 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; return 1;
} }
incPC(2); incPC(2);
@ -482,7 +482,7 @@ __ri void mVUanalyzeJump(mV, int Is, int It, bool isJALR) {
if (mVUconstReg[Is].isValid && doConstProp) { if (mVUconstReg[Is].isValid && doConstProp) {
mVUlow.constJump.isValid = 1; mVUlow.constJump.isValid = 1;
mVUlow.constJump.regValue = mVUconstReg[Is].regValue; 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]); analyzeVIreg1(Is, mVUlow.VI_read[0]);
if (isJALR) { if (isJALR) {

View File

@ -15,9 +15,9 @@
#pragma once #pragma once
extern bool doEarlyExit (microVU* mVU); extern bool doEarlyExit (microVU& mVU);
extern void mVUincCycles(microVU* mVU, int x); extern void mVUincCycles(microVU& mVU, int x);
extern void* mVUcompile (microVU* mVU, u32 startPC, uptr pState); extern void* mVUcompile (microVU& mVU, u32 startPC, uptr pState);
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); } #define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
#define sI ((mVUpBlock->pState.needExactMatch & 1) ? 3 : ((mVUpBlock->pState.flags >> 0) & 3)) #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 fClip = (isEbit) ? findFlagInst(mFC->xClip, 0x7fffffff) : cI;
int qInst = 0; int qInst = 0;
int pInst = 0; int pInst = 0;
mVU->regAlloc->flushAll(); mVU.regAlloc->flushAll();
if (isEbit) { if (isEbit) {
memzero(mVUinfo); memzero(mVUinfo);
memzero(mVUregsTemp); memzero(mVUregsTemp);
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0) mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
mVUcycles -= 100; mVUcycles -= 100;
qInst = mVU->q; qInst = mVU.q;
pInst = mVU->p; pInst = mVU.p;
if (mVUinfo.doDivFlag) { if (mVUinfo.doDivFlag) {
sFLAG.doFlag = 1; sFLAG.doFlag = 1;
sFLAG.write = fStatus; sFLAG.write = fStatus;
@ -56,46 +56,46 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
// Save P/Q Regs // Save P/Q Regs
if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); } 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) { if (isVU1) {
xPSHUF.D(xmmPQ, xmmPQ, pInst ? 3 : 2); 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 // Save Flag Instances
#if 1 // CHECK_MACROVU0 - Always on now #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 #else
mVUallocSFLAGc(gprT1, gprT2, fStatus); 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 #endif
mVUallocMFLAGa(mVU, gprT1, fMac); mVUallocMFLAGa(mVU, gprT1, fMac);
mVUallocCFLAGa(mVU, gprT2, fClip); mVUallocCFLAGa(mVU, gprT2, fClip);
xMOV(ptr32[&mVU->regs().VI[REG_MAC_FLAG].UL], gprT1); 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_CLIP_FLAG].UL], gprT2);
if (isEbit || isVU1) { // Clear 'is busy' Flags if (isEbit || isVU1) { // Clear 'is busy' Flags
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag 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 if (isEbit != 2) { // Save PC, and Jump to Exit Point
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC); xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU->exitFunct); xJMP(mVU.exitFunct);
} }
} }
// Recompiles Code for Proper Flags and Q/P regs on Block Linkings // Recompiles Code for Proper Flags and Q/P regs on Block Linkings
void mVUsetupBranch(mV, microFlagCycles& mFC) { void mVUsetupBranch(mV, microFlagCycles& mFC) {
mVU->regAlloc->flushAll(); // Flush Allocated Regs mVU.regAlloc->flushAll(); // Flush Allocated Regs
mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances
// Shuffle P/Q regs since every block starts at instance #0 // 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; microBlock* pBlock;
blockCreate(branchPC/8); blockCreate(branchPC/8);
pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs); pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs);
@ -112,12 +112,12 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) {
mVUpBlock->jumpCache = new microJumpCache[mProgSize/2]; mVUpBlock->jumpCache = new microJumpCache[mProgSize/2];
} }
if (isEvilJump) xMOV(gprT2, ptr32[&mVU->evilBranch]); if (isEvilJump) xMOV(gprT2, ptr32[&mVU.evilBranch]);
else xMOV(gprT2, ptr32[&mVU->branch]); else xMOV(gprT2, ptr32[&mVU.branch]);
if (doJumpCaching) xMOV(gprT3, (uptr)mVUpBlock); if (doJumpCaching) xMOV(gprT3, (uptr)mVUpBlock);
else xMOV(gprT3, (uptr)&mVUpBlock->pStateEnd); 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>); else xCALL(mVUcompileJIT<1>);
mVUrestoreRegs(mVU); mVUrestoreRegs(mVU);
@ -136,19 +136,19 @@ void normBranch(mV, microFlagCycles& mFC) {
void condBranch(mV, microFlagCycles& mFC, int JMPcc) { void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
mVUsetupBranch(mVU, mFC); mVUsetupBranch(mVU, mFC);
xCMP(ptr16[&mVU->branch], 0); xCMP(ptr16[&mVU.branch], 0);
incPC(3); incPC(3);
if (mVUup.eBit) { // Conditional Branch With E-Bit Set if (mVUup.eBit) { // Conditional Branch With E-Bit Set
mVUendProgram(mVU, &mFC, 2); mVUendProgram(mVU, &mFC, 2);
xForwardJump8 eJMP((JccComparisonType)JMPcc); xForwardJump8 eJMP((JccComparisonType)JMPcc);
incPC(1); // Set PC to First instruction of Non-Taken Side incPC(1); // Set PC to First instruction of Non-Taken Side
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC); xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU->exitFunct); xJMP(mVU.exitFunct);
eJMP.SetTarget(); eJMP.SetTarget();
incPC(-4); // Go Back to Branch Opcode to get branchAddr incPC(-4); // Go Back to Branch Opcode to get branchAddr
iPC = branchAddr/4; iPC = branchAddr/4;
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC); xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU->exitFunct); xJMP(mVU.exitFunct);
return; return;
} }
else { // Normal Conditional Branch else { // Normal Conditional Branch
@ -182,11 +182,11 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
void normJump(mV, microFlagCycles& mFC) { void normJump(mV, microFlagCycles& mFC) {
if (mVUlow.constJump.isValid) { // Jump Address is Constant if (mVUlow.constJump.isValid) { // Jump Address is Constant
if (mVUup.eBit) { // E-bit Jump if (mVUup.eBit) { // E-bit Jump
iPC = (mVUlow.constJump.regValue*2) & (mVU->progMemMask); iPC = (mVUlow.constJump.regValue*2) & (mVU.progMemMask);
mVUendProgram(mVU, &mFC, 1); mVUendProgram(mVU, &mFC, 1);
return; return;
} }
int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8); int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU.microMemSize-8);
mVUsetupBranch(mVU, mFC); mVUsetupBranch(mVU, mFC);
normBranchCompile(mVU, jumpAddr); normBranchCompile(mVU, jumpAddr);
return; return;
@ -194,9 +194,9 @@ void normJump(mV, microFlagCycles& mFC) {
if (mVUup.eBit) { // E-bit Jump if (mVUup.eBit) { // E-bit Jump
mVUendProgram(mVU, &mFC, 2); mVUendProgram(mVU, &mFC, 2);
xMOV(gprT1, ptr32[&mVU->branch]); xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], gprT1); xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xJMP(mVU->exitFunct); xJMP(mVU.exitFunct);
} }
else normJumpCompile(mVU, mFC, 0); 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. // 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) // 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) // 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 ((!clampE && CHECK_VU_SIGN_OVERFLOW) || (clampE && bClampE && CHECK_VU_SIGN_OVERFLOW)) {
if (x86caps.hasStreamingSIMD4Extensions) { if (x86caps.hasStreamingSIMD4Extensions) {
int i = (xyzw==1||xyzw==2||xyzw==4||xyzw==8) ? 0: 1; 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]]); xPMIN.UD(reg, ptr128[&sse4_minvals[i][0]]);
return; 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; 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) { switch (xyzw) {
case 1: case 2: case 4: case 8: case 1: case 2: case 4: case 8:
xMOVAPS(regT1, reg); xMOVAPS(regT1, reg);
@ -81,14 +81,14 @@ void mVUclamp2(microVU* mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool
xOR.PS (reg, regT1); xOR.PS (reg, regT1);
break; break;
} }
//if (regT1 != regT1in) mVU->regAlloc->clearNeeded(regT1); //if (regT1 != regT1in) mVU.regAlloc->clearNeeded(regT1);
if (regT1 != regT1in) xMOVAPS(regT1, ptr128[mVU->xmmCTemp]); if (regT1 != regT1in) xMOVAPS(regT1, ptr128[mVU.xmmCTemp]);
} }
else mVUclamp1(reg, regT1in, xyzw, bClampE); else mVUclamp1(reg, regT1in, xyzw, bClampE);
} }
// Used for operand clamping on every SSE instruction (add/sub/mul/div) // 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); 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 // Used by mVUsetupRange
static __fi void mVUcheckIsSame(mV) { __fi void mVUcheckIsSame(mV) {
if (mVU->prog.isSame == -1) { if (mVU.prog.isSame == -1) {
mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs().Micro, mVU->microMemSize); mVU.prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU.regs().Micro, mVU.microMemSize);
} }
if (mVU->prog.isSame == 0) { if (mVU.prog.isSame == 0) {
mVUcacheProg(*mVU, *mVU->prog.cur); mVUcacheProg(mVU, *mVU.prog.cur);
mVU->prog.isSame = 1; mVU.prog.isSame = 1;
} }
} }
// Sets up microProgram PC ranges based on whats been recompiled // 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; 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 if (isStartPC) { // Check if startPC is already within a block we've recompiled
deque<microRange>::const_iterator it(ranges->begin()); deque<microRange>::const_iterator it(ranges->begin());
@ -81,13 +81,13 @@ static void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) {
} }
} }
if (mergedRange) { 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()); ranges->erase(ranges->begin());
} }
} }
else { else {
DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange.start, mVUrange.end); DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU.index, mVUrange.start, mVUrange.end);
mVUrange.end = mVU->microMemSize; mVUrange.end = mVU.microMemSize;
microRange mRange = {0, pc}; microRange mRange = {0, pc};
ranges->push_front(mRange); 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 doUpperOp(mV) { mVUopU(mVU, 1); mVUdivSet(mVU); }
__ri void doLowerOp(mV) { incPC(-1); mVUopL(mVU, 1); incPC(1); } __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) { if (mVUup.iBit) {
incPC(-1); incPC(-1);
u32 tempI; u32 tempI;
mVU->regAlloc->clearRegVF(33); mVU.regAlloc->clearRegVF(33);
if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) { 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 tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg
} }
else tempI = curI; else tempI = curI;
xMOV(ptr32[&mVU->getVI(REG_I)], tempI); xMOV(ptr32[&mVU.getVI(REG_I)], tempI);
incPC(1); incPC(1);
} }
} }
static void doSwapOp(mV) { void doSwapOp(mV) {
if (mVUinfo.backupVF && !mVUlow.noWriteVF) { if (mVUinfo.backupVF && !mVUlow.noWriteVF) {
DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC); DevCon.WriteLn(Color_Green, "microVU%d: Backing Up VF Reg [%04x]", getIndex, xPC);
// Allocate t1 first for better chance of reg-alloc // Allocate t1 first for better chance of reg-alloc
const xmm& t1 = mVU->regAlloc->allocReg(mVUlow.VF_write.reg); const xmm& t1 = mVU.regAlloc->allocReg(mVUlow.VF_write.reg);
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
xMOVAPS(t2, t1); // Backup VF reg xMOVAPS(t2, t1); // Backup VF reg
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVUopL(mVU, 1); 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(t2, t3); // Swap new and old values of the register
xXOR.PS(t3, t2); // Uses xor swap trick... xXOR.PS(t3, t2); // Uses xor swap trick...
xXOR.PS(t2, t3); xXOR.PS(t2, t3);
mVU->regAlloc->clearNeeded(t3); mVU.regAlloc->clearNeeded(t3);
incPC(1); incPC(1);
doUpperOp(mVU); 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); xMOVAPS(t4, t2);
mVU->regAlloc->clearNeeded(t4); mVU.regAlloc->clearNeeded(t4);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
else { mVUopL(mVU, 1); incPC(1); flushRegs(mVU); doUpperOp(mVU); } 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); } if (mVUlow.isNOP) { incPC(1); doUpperOp(mVU); flushRegs(mVU); doIbit(mVU); }
elif(!mVUinfo.swapOps) { incPC(1); doUpperOp(mVU); flushRegs(mVU); doLowerOp(mVU); } elif(!mVUinfo.swapOps) { incPC(1); doUpperOp(mVU); flushRegs(mVU); doLowerOp(mVU); }
else doSwapOp(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) // 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) { if (mVUinfo.isBadOp && mVUcount == 0) {
mVUinfo.isEOB = true; mVUinfo.isEOB = true;
Console.Warning("microVU Warning: First Instruction of block contains illegal opcode..."); 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) // 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) { if (mVUinfo.isBadOp && count == 0) {
mVUbackupRegs(mVU, true); mVUbackupRegs(mVU, true);
xMOV(gprT2, mVU->prog.cur->idx); xMOV(gprT2, mVU.prog.cur->idx);
xMOV(gprT3, xPC); xMOV(gprT3, xPC);
if (!isVU1) xCALL(mVUbadOp0); if (!isVU1) xCALL(mVUbadOp0);
else xCALL(mVUbadOp1); 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); incPC(-2);
if (mVUup.eBit && mVUbranch) { if (mVUup.eBit && mVUbranch) {
incPC(2); 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; mVUlow.isNOP = 1;
} }
else incPC(2); 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) { if (mVUregs.blockType != 1) {
branch = 1; branch = 1;
mVUup.eBit = 1; mVUup.eBit = 1;
} }
} }
static __ri void eBitWarning(mV) { __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 == 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); if (mVUpBlock->pState.blockType == 2) Console.Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU.index, xPC);
incPC(2); incPC(2);
if (curI & _Ebit_) { 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; mVUregs.blockType = 1;
} }
incPC(-2); incPC(-2);
@ -218,14 +218,14 @@ static __ri void eBitWarning(mV) {
__fi void optimizeReg(u8& rState) { rState = (rState==1) ? 0 : rState; } __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 calcCycles(u8& reg, u8 x) { reg = ((reg > x) ? (reg - x) : 0); }
__fi void tCycles(u8& dest, u8& src) { dest = aMax(dest, src); } __fi void tCycles(u8& dest, u8& src) { dest = aMax(dest, src); }
__fi void incP(mV) { mVU->p ^= 1; } __fi void incP(mV) { mVU.p ^= 1; }
__fi void incQ(mV) { mVU->q ^= 1; } __fi void incQ(mV) { mVU.q ^= 1; }
// Optimizes the End Pipeline State Removing Unnecessary Info // 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 // 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, // because mVU automatically decrements this number at the start of its loop,
// so essentially '1' will be the same as '0'... // so essentially '1' will be the same as '0'...
static void mVUoptimizePipeState(mV) { void mVUoptimizePipeState(mV) {
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
optimizeReg(mVUregs.VF[i].x); optimizeReg(mVUregs.VF[i].x);
optimizeReg(mVUregs.VF[i].y); optimizeReg(mVUregs.VF[i].y);
@ -312,7 +312,7 @@ void mVUsetCycles(mV) {
} }
// Prints Start/End PC of blocks executed, for debugging... // Prints Start/End PC of blocks executed, for debugging...
static void mVUdebugPrintBlocks(microVU* mVU, bool isEndPC) { void mVUdebugPrintBlocks(microVU& mVU, bool isEndPC) {
if (mVUdebugNow) { if (mVUdebugNow) {
mVUbackupRegs(mVU, true); mVUbackupRegs(mVU, true);
xMOV(gprT2, xPC); 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) // 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; return IsDevBuild || !isVU1;
} }
// Saves Pipeline State for resuming from early exits // Saves Pipeline State for resuming from early exits
static __fi void mVUsavePipelineState(microVU* mVU) { __fi void mVUsavePipelineState(microVU& mVU) {
u32* lpS = (u32*)&mVU->prog.lpState; u32* lpS = (u32*)&mVU.prog.lpState;
for (int i = 0; i < (sizeof(microRegInfo)-4)/4; i++, lpS++) { for (int i = 0; i < (sizeof(microRegInfo)-4)/4; i++, lpS++) {
xMOV(ptr32[lpS], lpS[0]); xMOV(ptr32[lpS], lpS[0]);
} }
} }
// Test cycles to see if we need to exit-early... // Test cycles to see if we need to exit-early...
static void mVUtestCycles(microVU* mVU) { void mVUtestCycles(microVU& mVU) {
iPC = mVUstartPC; iPC = mVUstartPC;
if (doEarlyExit(mVU)) { if (doEarlyExit(mVU)) {
xCMP(ptr32[&mVU->cycles], 0); xCMP(ptr32[&mVU.cycles], 0);
xForwardJG32 skip; xForwardJG32 skip;
if (isVU0) { if (isVU0) {
// TEST32ItoM((uptr)&mVU->regs().flags, VUFLAG_MFLAGSET); // TEST32ItoM((uptr)&mVU.regs().flags, VUFLAG_MFLAGSET);
// xFowardJZ32 vu0jmp; // xFowardJZ32 vu0jmp;
// mVUbackupRegs(mVU, true); // 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 // xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation
// mVUbackupRegs(mVU, true); // mVUbackupRegs(mVU, true);
mVUsavePipelineState(mVU); mVUsavePipelineState(mVU);
@ -354,7 +354,7 @@ static void mVUtestCycles(microVU* mVU) {
} }
else { else {
mVUbackupRegs(mVU, true); mVUbackupRegs(mVU, true);
xMOV(gprT2, mVU->prog.cur->idx); xMOV(gprT2, mVU.prog.cur->idx);
xCALL(mVUwarning1); xCALL(mVUwarning1);
mVUbackupRegs(mVU, true); mVUbackupRegs(mVU, true);
mVUsavePipelineState(mVU); mVUsavePipelineState(mVU);
@ -362,7 +362,7 @@ static void mVUtestCycles(microVU* mVU) {
} }
skip.SetTarget(); 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 // 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 & _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 & _Dbit_) { DevCon.WriteLn (Color_Green, "microVU%d: D-bit set!", getIndex); }
if (curI & _Tbit_) { DevCon.WriteLn (Color_Green, "microVU%d: T-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) // 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++) { for (int i = 0; i < 16; i++) {
mVUconstReg[i].isValid = 0; mVUconstReg[i].isValid = 0;
mVUconstReg[i].regValue = 0; mVUconstReg[i].regValue = 0;
@ -389,18 +389,18 @@ static __fi void mVUinitConstValues(microVU* mVU) {
} }
// Initialize Variables // 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 mVUstartPC = iPC; // Block Start PC
mVUbranch = 0; // Branch Type mVUbranch = 0; // Branch Type
mVUcount = 0; // Number of instructions ran mVUcount = 0; // Number of instructions ran
mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage
mVU->p = 0; // All blocks start at p index #0 mVU.p = 0; // All blocks start at p index #0
mVU->q = 0; // All blocks start at q index #0 mVU.q = 0; // All blocks start at q index #0
if ((uptr)&mVUregs != pState) { // Loads up Pipeline State Info if ((uptr)&mVUregs != pState) { // Loads up Pipeline State Info
memcpy_const((u8*)&mVUregs, (u8*)pState, sizeof(microRegInfo)); memcpy_const((u8*)&mVUregs, (u8*)pState, sizeof(microRegInfo));
} }
if (doEarlyExit(mVU) && ((uptr)&mVU->prog.lpState != pState)) { if (doEarlyExit(mVU) && ((uptr)&mVU.prog.lpState != pState)) {
memcpy_const((u8*)&mVU->prog.lpState, (u8*)pState, sizeof(microRegInfo)); memcpy_const((u8*)&mVU.prog.lpState, (u8*)pState, sizeof(microRegInfo));
} }
mVUblock.x86ptrStart = thisPtr; mVUblock.x86ptrStart = thisPtr;
mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager 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 // Recompiler
//------------------------------------------------------------------ //------------------------------------------------------------------
void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) { void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) {
microFlagCycles mFC; microFlagCycles mFC;
u8* thisPtr = x86Ptr; 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 // First Pass
iPC = startPC / 4; iPC = startPC / 4;
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
mVU->regAlloc->reset(); // Reset regAlloc mVU.regAlloc->reset(); // Reset regAlloc
mVUinitFirstPass(mVU, pState, thisPtr); mVUinitFirstPass(mVU, pState, thisPtr);
for (int branch = 0; mVUcount < endCount; mVUcount++) { for (int branch = 0; mVUcount < endCount; mVUcount++) {
incPC(1); incPC(1);
@ -439,10 +439,10 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; }
else { incPC(-1); mVUopL(mVU, 0); incPC(1); } else { incPC(-1); mVUopL(mVU, 0); incPC(1); }
mVUsetCycles(mVU); mVUsetCycles(mVU);
mVUinfo.readQ = mVU->q; mVUinfo.readQ = mVU.q;
mVUinfo.writeQ = !mVU->q; mVUinfo.writeQ = !mVU.q;
mVUinfo.readP = mVU->p; mVUinfo.readP = mVU.p;
mVUinfo.writeP = !mVU->p; mVUinfo.writeP = !mVU.p;
if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; } if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; }
else if (branch == 1) { branch = 2; } else if (branch == 1) { branch = 2; }
if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; } 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; u32 x = 0;
for (; x < endCount; x++) { for (; x < endCount; x++) {
if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; } 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); mVUexecuteInstruction(mVU);
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } 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 // E-bit End
mVUsetupRange(mVU, xPC-8, 0); 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) // 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); microBlock* pBlock = block->search((microRegInfo*)pState);
if (pBlock) return pBlock->x86ptrStart; 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) // 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 & 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) ); pxAssumeDev( startPC < mVU.microMemSize-8, pxsFmt("microVU%d: invalid startPC=0x%04x", mVU.index, startPC) );
startPC &= mVU->microMemSize-8; startPC &= mVU.microMemSize-8;
blockCreate(startPC/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 // mVUcompileJIT() - Called By JR/JALR during execution

View File

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

View File

@ -23,7 +23,7 @@ __fi void mVUdivSet(mV) {
if (mVUinfo.doDivFlag) { if (mVUinfo.doDivFlag) {
if (!sFLAG.doFlag) { xMOV(getFlagReg(sFLAG.write), getFlagReg(sFLAG.lastWrite)); } if (!sFLAG.doFlag) { xMOV(getFlagReg(sFLAG.write), getFlagReg(sFLAG.lastWrite)); }
xAND(getFlagReg(sFLAG.write), 0xfff3ffff); 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 // Recompiles Code for Proper Flags on Block Linkings
__fi void mVUsetupFlags(mV, microFlagCycles& mFC) { __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 (__Status) {
if (pf) DevCon.WriteLn("mVU%d - Status Flag", mVU.index);
int bStatus[4]; int bStatus[4];
int sortRegs = sortFlag(mFC.xStatus, bStatus, mFC.cycles); int sortRegs = sortFlag(mFC.xStatus, bStatus, mFC.cycles);
// DevCon::Status("sortRegs = %d", params sortRegs); // DevCon::Status("sortRegs = %d", params sortRegs);
@ -205,19 +210,21 @@ __fi void mVUsetupFlags(mV, microFlagCycles& mFC) {
} }
if (__Mac) { if (__Mac) {
if (pf) DevCon.WriteLn("mVU%d - Mac Flag", mVU.index);
int bMac[4]; int bMac[4];
sortFlag(mFC.xMac, bMac, mFC.cycles); sortFlag(mFC.xMac, bMac, mFC.cycles);
xMOVAPS(xmmT1, ptr128[mVU->macFlag]); xMOVAPS(xmmT1, ptr128[mVU.macFlag]);
xSHUF.PS(xmmT1, xmmT1, shuffleMac); xSHUF.PS(xmmT1, xmmT1, shuffleMac);
xMOVAPS(ptr128[mVU->macFlag], xmmT1); xMOVAPS(ptr128[mVU.macFlag], xmmT1);
} }
if (__Clip) { if (__Clip) {
if (pf) DevCon.WriteLn("mVU%d - Clip Flag", mVU.index);
int bClip[4]; int bClip[4];
sortFlag(mFC.xClip, bClip, mFC.cycles); sortFlag(mFC.xClip, bClip, mFC.cycles);
xMOVAPS(xmmT2, ptr128[mVU->clipFlag]); xMOVAPS(xmmT2, ptr128[mVU.clipFlag]);
xSHUF.PS(xmmT2, xmmT2, shuffleClip); 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); } branchType1 { incPC(-1); mVUflagPass(mVU, branchAddr); incPC(1); }
branchType2 { // This case can possibly be turned off via a hack for a small speedup... branchType2 { // This case can possibly be turned off via a hack for a small speedup...
if (!mVUlow.constJump.isValid || !doConstProp) { mVUregs.needExactMatch |= 0x7; } 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 { branchType3 {
incPC(-1); incPC(-1);

View File

@ -17,11 +17,11 @@
#include "Utilities/AsciiFile.h" #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, ...) { _mVUt void __mVULog(const char* fmt, ...) {
microVU* mVU = mVUx; microVU& mVU = mVUx;
if (!mVU->logFile) return; if (!mVU.logFile) return;
char tmp[2024]; char tmp[2024];
va_list list; va_list list;
@ -31,28 +31,27 @@ _mVUt void __mVULog(const char* fmt, ...) {
int length = vsprintf(tmp, fmt, list); int length = vsprintf(tmp, fmt, list);
va_end(list); va_end(list);
mVU->logFile->Write( tmp ); mVU.logFile->Write( tmp );
mVU->logFile->Flush(); mVU.logFile->Flush();
} }
#define commaIf() { if (bitX[6]) { mVUlog(","); bitX[6] = 0; } } #define commaIf() { if (bitX[6]) { mVUlog(","); bitX[6] = 0; } }
#include "AppConfig.h" #include "AppConfig.h"
_mVUt void __mVUdumpProgram(microProgram& prog) { void __mVUdumpProgram(microVU& mVU, microProgram& prog) {
microVU* mVU = mVUx;
bool bitX[7]; bool bitX[7];
int delay = 0; int delay = 0;
int bBranch = mVUbranch; int bBranch = mVUbranch;
int bCode = mVU->code; int bCode = mVU.code;
int bPC = iPC; int bPC = iPC;
mVUbranch = 0; mVUbranch = 0;
const wxString logname(wxsFormat(L"microVU%d prog - %02d.html", vuIndex, prog.idx)); 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"); mVU.logFile = new AsciiFile(Path::Combine(g_Conf->Folders.Logs, logname), L"w");
mVUlog("<html>\n"); 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("<body bgcolor=\"#000000\" LINK=\"#1111ff\" VLINK=\"#1111ff\">\n");
mVUlog("<font face=\"Courier New\" color=\"#ffffff\">\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("*********************\n\n<br><br>", prog.idx);
mVUlog("</font>"); 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 (delay) { delay--; mVUlog("</font>"); if (!delay) mVUlog("<hr/>"); }
if (mVUbranch) { delay = 1; mVUbranch = 0; } if (mVUbranch) { delay = 1; mVUbranch = 0; }
mVU->code = prog.data[i+1]; mVU.code = prog.data[i+1];
bitX[0] = 0; bitX[0] = 0;
bitX[1] = 0; bitX[1] = 0;
@ -76,18 +75,18 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
bitX[5] = 0; bitX[5] = 0;
bitX[6] = 0; bitX[6] = 0;
if (mVU->code & _Ibit_) { bitX[0] = 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 & _Ebit_) { bitX[1] = 1; bitX[5] = 1; delay = 2; }
if (mVU->code & _Mbit_) { bitX[2] = 1; bitX[5] = 1; } if (mVU.code & _Mbit_) { bitX[2] = 1; bitX[5] = 1; }
if (mVU->code & _Dbit_) { bitX[3] = 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 & _Tbit_) { bitX[4] = 1; bitX[5] = 1; }
if (delay == 2) { mVUlog("<font color=\"#FFFF00\">"); } if (delay == 2) { mVUlog("<font color=\"#FFFF00\">"); }
if (delay == 1) { mVUlog("<font color=\"#999999\">"); } if (delay == 1) { mVUlog("<font color=\"#999999\">"); }
iPC = (i+1); iPC = (i+1);
mVUlog("<a name=\"addr%04x\">", i*4); 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); mVUopU(mVU, 2);
if (bitX[5]) { if (bitX[5]) {
@ -101,15 +100,15 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
} }
iPC = i; iPC = i;
mVU->code = prog.data[i]; mVU.code = prog.data[i];
if(bitX[0]) { if(bitX[0]) {
mVUlog("<br>\n<font color=\"#FF7000\">"); 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>"); mVUlog("</font>\n\n<br><br>");
} }
else { else {
mVUlog("<br>\n[%04x] (%08x) ", i*4, mVU->code); mVUlog("<br>\n[%04x] (%08x) ", i*4, mVU.code);
mVUopL(mVU, 2); mVUopL(mVU, 2);
mVUlog("\n\n<br><br>"); mVUlog("\n\n<br><br>");
} }
@ -119,10 +118,10 @@ _mVUt void __mVUdumpProgram(microProgram& prog) {
mVUlog("</html>\n"); mVUlog("</html>\n");
mVUbranch = bBranch; mVUbranch = bBranch;
mVU->code = bCode; mVU.code = bCode;
iPC = bPC; iPC = bPC;
setCode(); 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); xMOVMSKPS(gprTemp, xmmReg);
xTEST(gprTemp, 1); xTEST(gprTemp, 1);
xForwardJZ8 skip; xForwardJZ8 skip;
xMOV(ptr32[&mVU->divFlag], divI); xMOV(ptr32[&mVU.divFlag], divI);
xAND.PS(xmmReg, ptr128[mVUglob.absclip]); xAND.PS(xmmReg, ptr128[mVUglob.absclip]);
skip.SetTarget(); skip.SetTarget();
} }
@ -50,20 +50,20 @@ mVUop(mVU_DIV) {
pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 7); } pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 7); }
pass2 { pass2 {
xmm Ft; xmm Ft;
if (_Ftf_) Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_))); if (_Ftf_) Ft = mVU.regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
else Ft = mVU->regAlloc->allocReg(_Ft_); else Ft = mVU.regAlloc->allocReg(_Ft_);
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_))); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
testZero(Ft, t1, gprT1); // Test if Ft is zero testZero(Ft, t1, gprT1); // Test if Ft is zero
xForwardJZ8 cjmp; // Skip if not zero xForwardJZ8 cjmp; // Skip if not zero
testZero(Fs, t1, gprT1); // Test if Fs is zero testZero(Fs, t1, gprT1); // Test if Fs is zero
xForwardJZ8 ajmp; xForwardJZ8 ajmp;
xMOV(ptr32[&mVU->divFlag], divI); // Set invalid flag (0/0) xMOV(ptr32[&mVU.divFlag], divI); // Set invalid flag (0/0)
xForwardJump8 bjmp; xForwardJump8 bjmp;
ajmp.SetTarget(); 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(); bjmp.SetTarget();
xXOR.PS(Fs, Ft); xXOR.PS(Fs, Ft);
@ -72,16 +72,16 @@ mVUop(mVU_DIV) {
xForwardJump8 djmp; xForwardJump8 djmp;
cjmp.SetTarget(); 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); SSE_DIVSS(mVU, Fs, Ft);
mVUclamp1(Fs, t1, 8, 1); mVUclamp1(Fs, t1, 8, 1);
djmp.SetTarget(); djmp.SetTarget();
writeQreg(Fs, mVUinfo.writeQ); writeQreg(Fs, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
} }
pass3 { mVUlog("DIV Q, vf%02d%s, vf%02d%s", _Fs_, _Fsf_String, _Ft_, _Ftf_String); } 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) { mVUop(mVU_SQRT) {
pass1 { mVUanalyzeFDIV(mVU, 0, 0, _Ft_, _Ftf_, 7); } pass1 { mVUanalyzeFDIV(mVU, 0, 0, _Ft_, _Ftf_, 7); }
pass2 { 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 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) 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); xSQRT.SS(Ft, Ft);
writeQreg(Ft, mVUinfo.writeQ); writeQreg(Ft, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
} }
pass3 { mVUlog("SQRT Q, vf%02d%s", _Ft_, _Ftf_String); } pass3 { mVUlog("SQRT Q, vf%02d%s", _Ft_, _Ftf_String); }
} }
@ -106,11 +106,11 @@ mVUop(mVU_SQRT) {
mVUop(mVU_RSQRT) { mVUop(mVU_RSQRT) {
pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 13); } pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 13); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_))); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_))); const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
const xmm& t1 = mVU->regAlloc->allocReg(); 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 testNeg(mVU, Ft, gprT1); // Check for negative sqrt
xSQRT.SS(Ft, Ft); xSQRT.SS(Ft, Ft);
@ -119,10 +119,10 @@ mVUop(mVU_RSQRT) {
testZero(Fs, t1, gprT1); // Test if Fs is zero testZero(Fs, t1, gprT1); // Test if Fs is zero
xForwardJZ8 bjmp; // Skip if none are 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; xForwardJump8 cjmp;
bjmp.SetTarget(); 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(); cjmp.SetTarget();
xAND.PS(Fs, ptr128[mVUglob.signbit]); xAND.PS(Fs, ptr128[mVUglob.signbit]);
@ -136,9 +136,9 @@ mVUop(mVU_RSQRT) {
writeQreg(Fs, mVUinfo.writeQ); writeQreg(Fs, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
} }
pass3 { mVUlog("RSQRT Q, vf%02d%s, vf%02d%s", _Fs_, _Fsf_String, _Ft_, _Ftf_String); } 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) { mVUop(mVU_EATAN) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 54); } pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 54); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_))); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xSUB.SS(Fs, ptr32[mVUglob.one]); xSUB.SS(Fs, ptr32[mVUglob.one]);
xADD.SS(xmmPQ, ptr32[mVUglob.one]); xADD.SS(xmmPQ, ptr32[mVUglob.one]);
SSE_DIVSS(mVU, Fs, xmmPQ); SSE_DIVSS(mVU, Fs, xmmPQ);
mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2); mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
pass3 { mVUlog("EATAN P"); } pass3 { mVUlog("EATAN P"); }
} }
@ -193,9 +193,9 @@ mVUop(mVU_EATAN) {
mVUop(mVU_EATANxy) { mVUop(mVU_EATANxy) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 54); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 54); }
pass2 { pass2 {
const xmm& t1 = mVU->regAlloc->allocReg(_Fs_, 0, 0xf); const xmm& t1 = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Fs = mVU->regAlloc->allocReg(); const xmm& Fs = mVU.regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(Fs, t1, 0x01); xPSHUF.D(Fs, t1, 0x01);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
@ -203,9 +203,9 @@ mVUop(mVU_EATANxy) {
SSE_ADDSS (mVU, t1, xmmPQ); SSE_ADDSS (mVU, t1, xmmPQ);
SSE_DIVSS (mVU, Fs, t1); SSE_DIVSS (mVU, Fs, t1);
mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2); mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
pass3 { mVUlog("EATANxy P"); } pass3 { mVUlog("EATANxy P"); }
} }
@ -213,9 +213,9 @@ mVUop(mVU_EATANxy) {
mVUop(mVU_EATANxz) { mVUop(mVU_EATANxz) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 54); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 54); }
pass2 { pass2 {
const xmm& t1 = mVU->regAlloc->allocReg(_Fs_, 0, 0xf); const xmm& t1 = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Fs = mVU->regAlloc->allocReg(); const xmm& Fs = mVU.regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(Fs, t1, 0x02); xPSHUF.D(Fs, t1, 0x02);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
@ -223,9 +223,9 @@ mVUop(mVU_EATANxz) {
SSE_ADDSS (mVU, t1, xmmPQ); SSE_ADDSS (mVU, t1, xmmPQ);
SSE_DIVSS (mVU, Fs, t1); SSE_DIVSS (mVU, Fs, t1);
mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2); mVU_EATAN_(mVU, xmmPQ, Fs, t1, t2);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
pass3 { mVUlog("EATANxz P"); } pass3 { mVUlog("EATANxz P"); }
} }
@ -240,9 +240,9 @@ mVUop(mVU_EATANxz) {
mVUop(mVU_EEXP) { mVUop(mVU_EEXP) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 44); } pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 44); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_))); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xMUL.SS (xmmPQ, ptr32[mVUglob.E1]); xMUL.SS (xmmPQ, ptr32[mVUglob.E1]);
@ -264,9 +264,9 @@ mVUop(mVU_EEXP) {
SSE_DIVSS(mVU, t2, xmmPQ); SSE_DIVSS(mVU, t2, xmmPQ);
xMOVSS (xmmPQ, t2); xMOVSS (xmmPQ, t2);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
pass3 { mVUlog("EEXP P"); } pass3 { mVUlog("EEXP P"); }
} }
@ -290,12 +290,12 @@ static __fi void mVU_sumXYZ(mV, const xmm& PQ, const xmm& Fs) {
mVUop(mVU_ELENG) { mVUop(mVU_ELENG) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 18); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 18); }
pass2 { 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 xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs); mVU_sumXYZ(mVU, xmmPQ, Fs);
xSQRT.SS (xmmPQ, xmmPQ); xSQRT.SS (xmmPQ, xmmPQ);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ELENG P"); } pass3 { mVUlog("ELENG P"); }
} }
@ -303,14 +303,14 @@ mVUop(mVU_ELENG) {
mVUop(mVU_ERCPR) { mVUop(mVU_ERCPR) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 12); } pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 12); }
pass2 { 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 xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xMOVSSZX (Fs, ptr32[mVUglob.one]); xMOVSSZX (Fs, ptr32[mVUglob.one]);
SSE_DIVSS(mVU, Fs, xmmPQ); SSE_DIVSS(mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ERCPR P"); } pass3 { mVUlog("ERCPR P"); }
} }
@ -318,7 +318,7 @@ mVUop(mVU_ERCPR) {
mVUop(mVU_ERLENG) { mVUop(mVU_ERLENG) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 24); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 24); }
pass2 { 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 xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs); mVU_sumXYZ(mVU, xmmPQ, Fs);
xSQRT.SS (xmmPQ, xmmPQ); xSQRT.SS (xmmPQ, xmmPQ);
@ -326,7 +326,7 @@ mVUop(mVU_ERLENG) {
SSE_DIVSS (mVU, Fs, xmmPQ); SSE_DIVSS (mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ERLENG P"); } pass3 { mVUlog("ERLENG P"); }
} }
@ -334,14 +334,14 @@ mVUop(mVU_ERLENG) {
mVUop(mVU_ERSADD) { mVUop(mVU_ERSADD) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 18); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 18); }
pass2 { 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 xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs); mVU_sumXYZ(mVU, xmmPQ, Fs);
xMOVSSZX (Fs, ptr32[mVUglob.one]); xMOVSSZX (Fs, ptr32[mVUglob.one]);
SSE_DIVSS (mVU, Fs, xmmPQ); SSE_DIVSS (mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ERSADD P"); } pass3 { mVUlog("ERSADD P"); }
} }
@ -349,7 +349,7 @@ mVUop(mVU_ERSADD) {
mVUop(mVU_ERSQRT) { mVUop(mVU_ERSQRT) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 18); } pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 18); }
pass2 { 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 xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xAND.PS (Fs, ptr128[mVUglob.absclip]); xAND.PS (Fs, ptr128[mVUglob.absclip]);
xSQRT.SS (xmmPQ, Fs); xSQRT.SS (xmmPQ, Fs);
@ -357,7 +357,7 @@ mVUop(mVU_ERSQRT) {
SSE_DIVSS(mVU, Fs, xmmPQ); SSE_DIVSS(mVU, Fs, xmmPQ);
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ERSQRT P"); } pass3 { mVUlog("ERSQRT P"); }
} }
@ -365,11 +365,11 @@ mVUop(mVU_ERSQRT) {
mVUop(mVU_ESADD) { mVUop(mVU_ESADD) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 11); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 11); }
pass2 { 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 xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
mVU_sumXYZ(mVU, xmmPQ, Fs); mVU_sumXYZ(mVU, xmmPQ, Fs);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ESADD P"); } pass3 { mVUlog("ESADD P"); }
} }
@ -384,9 +384,9 @@ mVUop(mVU_ESADD) {
mVUop(mVU_ESIN) { mVUop(mVU_ESIN) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 29); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 29); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_))); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xMOVAPS (t1, Fs); xMOVAPS (t1, Fs);
@ -402,9 +402,9 @@ mVUop(mVU_ESIN) {
xMUL.SS (t2, ptr32[mVUglob.S5]); xMUL.SS (t2, ptr32[mVUglob.S5]);
SSE_ADDSS(mVU, xmmPQ, t2); SSE_ADDSS(mVU, xmmPQ, t2);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
pass3 { mVUlog("ESIN P"); } pass3 { mVUlog("ESIN P"); }
} }
@ -412,12 +412,12 @@ mVUop(mVU_ESIN) {
mVUop(mVU_ESQRT) { mVUop(mVU_ESQRT) {
pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 12); } pass1 { mVUanalyzeEFU1(mVU, _Fs_, _Fsf_, 12); }
pass2 { 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 xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xAND.PS (Fs, ptr128[mVUglob.absclip]); xAND.PS (Fs, ptr128[mVUglob.absclip]);
xSQRT.SS(xmmPQ, Fs); xSQRT.SS(xmmPQ, Fs);
xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ESQRT P"); } pass3 { mVUlog("ESQRT P"); }
} }
@ -425,8 +425,8 @@ mVUop(mVU_ESQRT) {
mVUop(mVU_ESUM) { mVUop(mVU_ESUM) {
pass1 { mVUanalyzeEFU2(mVU, _Fs_, 12); } pass1 { mVUanalyzeEFU2(mVU, _Fs_, 12); }
pass2 { 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);
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
xPSHUF.D (t1, Fs, 0x1b); xPSHUF.D (t1, Fs, 0x1b);
SSE_ADDPS(mVU, Fs, t1); SSE_ADDPS(mVU, Fs, t1);
@ -434,8 +434,8 @@ mVUop(mVU_ESUM) {
SSE_ADDSS(mVU, Fs, t1); SSE_ADDSS(mVU, Fs, t1);
xMOVSS (xmmPQ, Fs); xMOVSS (xmmPQ, Fs);
xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
} }
pass3 { mVUlog("ESUM P"); } pass3 { mVUlog("ESUM P"); }
} }
@ -719,11 +719,11 @@ mVUop(mVU_ISUBIU) {
mVUop(mVU_MFIR) { mVUop(mVU_MFIR) {
pass1 { if (!_Ft_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeReg2(_Ft_, mVUlow.VF_write, 1); } pass1 { if (!_Ft_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeReg2(_Ft_, mVUlow.VF_write, 1); }
pass2 { 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); mVUallocVIa(mVU, gprT1, _Is_, true);
xMOVDZX(Ft, gprT1); xMOVDZX(Ft, gprT1);
if (!_XYZW_SS) { mVUunpack_xyzw(Ft, Ft, 0); } 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_); } pass3 { mVUlog("MFIR.%s vf%02d, vi%02d", _XYZW_String, _Ft_, _Fs_); }
} }
@ -731,9 +731,9 @@ mVUop(mVU_MFIR) {
mVUop(mVU_MFP) { mVUop(mVU_MFP) {
pass1 { mVUanalyzeMFP(mVU, _Ft_); } pass1 { mVUanalyzeMFP(mVU, _Ft_); }
pass2 { 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); getPreg(mVU, Ft);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
} }
pass3 { mVUlog("MFP.%s vf%02d, P", _XYZW_String, _Ft_); } pass3 { mVUlog("MFP.%s vf%02d, P", _XYZW_String, _Ft_); }
} }
@ -741,8 +741,8 @@ mVUop(mVU_MFP) {
mVUop(mVU_MOVE) { mVUop(mVU_MOVE) {
pass1 { mVUanalyzeMOVE(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeMOVE(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("MOVE.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); } pass3 { mVUlog("MOVE.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); }
} }
@ -750,12 +750,12 @@ mVUop(mVU_MOVE) {
mVUop(mVU_MR32) { mVUop(mVU_MR32) {
pass1 { mVUanalyzeMR32(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeMR32(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_);
const xmm& Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W); 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)))); if (_XYZW_SS) mVUunpack_xyzw(Ft, Fs, (_X ? 1 : (_Y ? 2 : (_Z ? 3 : 0))));
else xPSHUF.D(Ft, Fs, 0x39); else xPSHUF.D(Ft, Fs, 0x39);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("MR32.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); } pass3 { mVUlog("MR32.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); }
} }
@ -763,10 +763,10 @@ mVUop(mVU_MR32) {
mVUop(mVU_MTIR) { mVUop(mVU_MTIR) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeReg5(_Fs_, _Fsf_, mVUlow.VF_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 1); } pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeReg5(_Fs_, _Fsf_, mVUlow.VF_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 1); }
pass2 { 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); xMOVD(gprT1, Fs);
mVUallocVIb(mVU, gprT1, _It_); mVUallocVIb(mVU, gprT1, _It_);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("MTIR vi%02d, vf%02d%s", _Ft_, _Fs_, _Fsf_String); } pass3 { mVUlog("MTIR vi%02d, vf%02d%s", _Ft_, _Fs_, _Fsf_String); }
} }
@ -778,7 +778,7 @@ mVUop(mVU_MTIR) {
mVUop(mVU_ILW) { mVUop(mVU_ILW) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); } pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem + offsetSS); xAddressVoid ptr(mVU.regs().Mem + offsetSS);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_); mVUallocVIa(mVU, gprT2, _Is_);
xADD(gprT2, _Imm11_); xADD(gprT2, _Imm11_);
@ -796,7 +796,7 @@ mVUop(mVU_ILW) {
mVUop(mVU_ILWR) { mVUop(mVU_ILWR) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); } pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem + offsetSS); xAddressVoid ptr(mVU.regs().Mem + offsetSS);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_); mVUallocVIa(mVU, gprT2, _Is_);
mVUaddrFix (mVU, gprT2); mVUaddrFix (mVU, gprT2);
@ -815,7 +815,7 @@ mVUop(mVU_ILWR) {
mVUop(mVU_ISW) { mVUop(mVU_ISW) {
pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); } pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_); mVUallocVIa(mVU, gprT2, _Is_);
xADD(gprT2, _Imm11_); xADD(gprT2, _Imm11_);
@ -836,7 +836,7 @@ mVUop(mVU_ISW) {
mVUop(mVU_ISWR) { mVUop(mVU_ISWR) {
pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); } pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_); mVUallocVIa(mVU, gprT2, _Is_);
mVUaddrFix (mVU, gprT2); mVUaddrFix (mVU, gprT2);
@ -858,7 +858,7 @@ mVUop(mVU_ISWR) {
mVUop(mVU_LQ) { mVUop(mVU_LQ) {
pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 0); } pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 0); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_); mVUallocVIa(mVU, gprT2, _Is_);
xADD(gprT2, _Imm11_); xADD(gprT2, _Imm11_);
@ -867,9 +867,9 @@ mVUop(mVU_LQ) {
} }
else else
ptr += getVUmem(_Imm11_); 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); 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_); } pass3 { mVUlog("LQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); }
} }
@ -877,7 +877,7 @@ mVUop(mVU_LQ) {
mVUop(mVU_LQD) { mVUop(mVU_LQD) {
pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); } pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT2, _Is_); mVUallocVIa(mVU, gprT2, _Is_);
xSUB(gprT2b, 1); xSUB(gprT2b, 1);
@ -886,9 +886,9 @@ mVUop(mVU_LQD) {
ptr += gprT2; ptr += gprT2;
} }
if (!mVUlow.noWriteVF) { 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); 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_); } pass3 { mVUlog("LQD.%s vf%02d, --vi%02d", _XYZW_String, _Ft_, _Is_); }
@ -897,7 +897,7 @@ mVUop(mVU_LQD) {
mVUop(mVU_LQI) { mVUop(mVU_LQI) {
pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); } pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_Is_) { if (_Is_) {
mVUallocVIa(mVU, gprT1, _Is_); mVUallocVIa(mVU, gprT1, _Is_);
xMOV(gprT2, gprT1); xMOV(gprT2, gprT1);
@ -907,9 +907,9 @@ mVUop(mVU_LQI) {
ptr += gprT2; ptr += gprT2;
} }
if (!mVUlow.noWriteVF) { 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); 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_); } pass3 { mVUlog("LQI.%s vf%02d, vi%02d++", _XYZW_String, _Ft_, _Fs_); }
@ -922,7 +922,7 @@ mVUop(mVU_LQI) {
mVUop(mVU_SQ) { mVUop(mVU_SQ) {
pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 0); } pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 0); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_It_) { if (_It_) {
mVUallocVIa(mVU, gprT2, _It_); mVUallocVIa(mVU, gprT2, _It_);
xADD(gprT2, _Imm11_); xADD(gprT2, _Imm11_);
@ -931,9 +931,9 @@ mVUop(mVU_SQ) {
} }
else else
ptr += getVUmem(_Imm11_); 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); 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_); } pass3 { mVUlog("SQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Fs_, _Ft_, _Imm11_); }
} }
@ -941,7 +941,7 @@ mVUop(mVU_SQ) {
mVUop(mVU_SQD) { mVUop(mVU_SQD) {
pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); } pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_It_) { if (_It_) {
mVUallocVIa(mVU, gprT2, _It_); mVUallocVIa(mVU, gprT2, _It_);
xSUB(gprT2b, 1); xSUB(gprT2b, 1);
@ -949,9 +949,9 @@ mVUop(mVU_SQD) {
mVUaddrFix (mVU, gprT2); mVUaddrFix (mVU, gprT2);
ptr += 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); 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_); } pass3 { mVUlog("SQD.%s vf%02d, --vi%02d", _XYZW_String, _Fs_, _Ft_); }
} }
@ -959,7 +959,7 @@ mVUop(mVU_SQD) {
mVUop(mVU_SQI) { mVUop(mVU_SQI) {
pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); } pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); }
pass2 { pass2 {
xAddressVoid ptr(mVU->regs().Mem); xAddressVoid ptr(mVU.regs().Mem);
if (_It_) { if (_It_) {
mVUallocVIa(mVU, gprT1, _It_); mVUallocVIa(mVU, gprT1, _It_);
xMOV(gprT2, gprT1); xMOV(gprT2, gprT1);
@ -968,9 +968,9 @@ mVUop(mVU_SQI) {
mVUaddrFix (mVU, gprT2); mVUaddrFix (mVU, gprT2);
ptr += 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); 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_); } pass3 { mVUlog("SQI.%s vf%02d, vi%02d++", _XYZW_String, _Fs_, _Ft_); }
} }
@ -983,12 +983,12 @@ mVUop(mVU_RINIT) {
pass1 { mVUanalyzeR1(mVU, _Fs_, _Fsf_); } pass1 { mVUanalyzeR1(mVU, _Fs_, _Fsf_); }
pass2 { pass2 {
if (_Fs_ || (_Fsf_ == 3)) { 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); xMOVD(gprT1, Fs);
xAND(gprT1, 0x007fffff); xAND(gprT1, 0x007fffff);
xOR (gprT1, 0x3f800000); xOR (gprT1, 0x3f800000);
xMOV(ptr32[Rmem], gprT1); xMOV(ptr32[Rmem], gprT1);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
else xMOV(ptr32[Rmem], 0x3f800000); else xMOV(ptr32[Rmem], 0x3f800000);
} }
@ -997,10 +997,10 @@ mVUop(mVU_RINIT) {
static __fi void mVU_RGET_(mV, const x32& Rreg) { static __fi void mVU_RGET_(mV, const x32& Rreg) {
if (!mVUlow.noWriteVF) { 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); xMOVDZX(Ft, Rreg);
if (!_XYZW_SS) mVUunpack_xyzw(Ft, Ft, 0); 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_); } pass1 { mVUanalyzeR1(mVU, _Fs_, _Fsf_); }
pass2 { pass2 {
if (_Fs_ || (_Fsf_ == 3)) { 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); xMOVD(gprT1, Fs);
xAND(gprT1, 0x7fffff); xAND(gprT1, 0x7fffff);
xXOR(ptr32[Rmem], gprT1); xXOR(ptr32[Rmem], gprT1);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
} }
pass3 { mVUlog("RXOR R, vf%02d%s", _Fs_, _Fsf_String); } pass3 { mVUlog("RXOR R, vf%02d%s", _Fs_, _Fsf_String); }
@ -1069,7 +1069,7 @@ mVUop(mVU_WAITQ) {
mVUop(mVU_XTOP) { mVUop(mVU_XTOP) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); } pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); }
pass2 { pass2 {
xMOVZX(gprT1, ptr16[&mVU->getVifRegs().top]); xMOVZX(gprT1, ptr16[&mVU.getVifRegs().top]);
mVUallocVIb(mVU, gprT1, _It_); mVUallocVIb(mVU, gprT1, _It_);
} }
pass3 { mVUlog("XTOP vi%02d", _Ft_); } pass3 { mVUlog("XTOP vi%02d", _Ft_); }
@ -1078,7 +1078,7 @@ mVUop(mVU_XTOP) {
mVUop(mVU_XITOP) { mVUop(mVU_XITOP) {
pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); } pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); }
pass2 { pass2 {
xMOVZX(gprT1, ptr16[&mVU->getVifRegs().itop]); xMOVZX(gprT1, ptr16[&mVU.getVifRegs().itop]);
xAND(gprT1, isVU1 ? 0x3ff : 0xff); xAND(gprT1, isVU1 ? 0x3ff : 0xff);
mVUallocVIb(mVU, gprT1, _It_); mVUallocVIb(mVU, gprT1, _It_);
} }
@ -1153,10 +1153,10 @@ static __fi void mVU_XGKICK_DELAY(mV, bool memVI) {
mVUbackupRegs(mVU); mVUbackupRegs(mVU);
#if 0 // XGkick Break - ToDo: Change "SomeGifPathValue" to w/e needs to be tested #if 0 // XGkick Break - ToDo: Change "SomeGifPathValue" to w/e needs to be tested
xTEST (ptr32[&SomeGifPathValue], 1); // If '1', breaks execution xTEST (ptr32[&SomeGifPathValue], 1); // If '1', breaks execution
xMOV (ptr32[&mVU->resumePtrXG], (uptr)xGetPtr() + 10 + 6); xMOV (ptr32[&mVU.resumePtrXG], (uptr)xGetPtr() + 10 + 6);
xJcc32(Jcc_NotZero, (uptr)mVU->exitFunctXG - ((uptr)xGetPtr()+6)); xJcc32(Jcc_NotZero, (uptr)mVU.exitFunctXG - ((uptr)xGetPtr()+6));
#endif #endif
if (memVI) xMOV(gprT2, ptr32[&mVU->VIxgkick]); if (memVI) xMOV(gprT2, ptr32[&mVU.VIxgkick]);
else mVUallocVIa(mVU, gprT2, _Is_); else mVUallocVIa(mVU, gprT2, _Is_);
xCALL(mVU_XGKICK_); xCALL(mVU_XGKICK_);
mVUrestoreRegs(mVU); mVUrestoreRegs(mVU);
@ -1168,7 +1168,7 @@ mVUop(mVU_XGKICK) {
if (!mVU_XGKICK_CYCLES) { mVU_XGKICK_DELAY(mVU, 0); return; } if (!mVU_XGKICK_CYCLES) { mVU_XGKICK_DELAY(mVU, 0); return; }
else if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); mVUinfo.doXGKICK = 0; } else if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); mVUinfo.doXGKICK = 0; }
mVUallocVIa(mVU, gprT1, _Is_); mVUallocVIa(mVU, gprT1, _Is_);
xMOV(ptr32[&mVU->VIxgkick], gprT1); xMOV(ptr32[&mVU.VIxgkick], gprT1);
} }
pass3 { mVUlog("XGKICK vi%02d", _Fs_); } pass3 { mVUlog("XGKICK vi%02d", _Fs_); }
} }
@ -1180,7 +1180,7 @@ mVUop(mVU_XGKICK) {
void setBranchA(mP, int x, int _x_) { void setBranchA(mP, int x, int _x_) {
pass1 { pass1 {
if (_Imm11_ == 1 && !_x_) { 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; mVUlow.isNOP = 1;
return; return;
} }
@ -1194,21 +1194,21 @@ void setBranchA(mP, int x, int _x_) {
void condEvilBranch(mV, int JMPcc) { void condEvilBranch(mV, int JMPcc) {
if (mVUlow.badBranch) { if (mVUlow.badBranch) {
xMOV(ptr32[&mVU->branch], gprT1); xMOV(ptr32[&mVU.branch], gprT1);
xMOV(ptr32[&mVU->badBranch], branchAddrN); xMOV(ptr32[&mVU.badBranch], branchAddrN);
xCMP(gprT1b, 0); xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc); xForwardJump8 cJMP((JccComparisonType)JMPcc);
incPC(4); // Branch Not Taken incPC(4); // Branch Not Taken
xMOV(ptr32[&mVU->badBranch], xPC); xMOV(ptr32[&mVU.badBranch], xPC);
incPC(-4); incPC(-4);
cJMP.SetTarget(); cJMP.SetTarget();
return; return;
} }
xMOV(ptr32[&mVU->evilBranch], branchAddr); xMOV(ptr32[&mVU.evilBranch], branchAddr);
xCMP(gprT1b, 0); xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc); xForwardJump8 cJMP((JccComparisonType)JMPcc);
xMOV(gprT1, ptr32[&mVU->badBranch]); // Branch Not Taken xMOV(gprT1, ptr32[&mVU.badBranch]); // Branch Not Taken
xMOV(ptr32[&mVU->evilBranch], gprT1); xMOV(ptr32[&mVU.evilBranch], gprT1);
cJMP.SetTarget(); cJMP.SetTarget();
} }
@ -1216,8 +1216,8 @@ mVUop(mVU_B) {
setBranchA(mX, 1, 0); setBranchA(mX, 1, 0);
pass1 { mVUanalyzeNormBranch(mVU, 0, 0); } pass1 { mVUanalyzeNormBranch(mVU, 0, 0); }
pass2 { pass2 {
if (mVUlow.badBranch) { xMOV(ptr32[&mVU->badBranch], branchAddrN); } if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU->evilBranch], branchAddr); } if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); }
} }
pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr, branchAddr); } pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr, branchAddr); }
} }
@ -1228,8 +1228,8 @@ mVUop(mVU_BAL) {
pass2 { pass2 {
xMOV(gprT1, bSaveAddr); xMOV(gprT1, bSaveAddr);
mVUallocVIb(mVU, gprT1, _It_); mVUallocVIb(mVU, gprT1, _It_);
if (mVUlow.badBranch) { xMOV(ptr32[&mVU->badBranch], branchAddrN); } if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU->evilBranch], branchAddr); } if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); }
} }
pass3 { mVUlog("BAL vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, branchAddr, 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); setBranchA(mX, 3, 0);
pass1 { mVUanalyzeCondBranch2(mVU, _Is_, _It_); } pass1 { mVUanalyzeCondBranch2(mVU, _Is_, _It_); }
pass2 { pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]); if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_); 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); } 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); else condEvilBranch(mVU, Jcc_Equal);
} }
pass3 { mVUlog("IBEQ vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); } 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); setBranchA(mX, 4, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); } pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 { pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]); if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_GreaterOrEqual); else condEvilBranch(mVU, Jcc_GreaterOrEqual);
} }
pass3 { mVUlog("IBGEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } 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); setBranchA(mX, 5, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); } pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 { pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]); if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_Greater); else condEvilBranch(mVU, Jcc_Greater);
} }
pass3 { mVUlog("IBGTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } 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); setBranchA(mX, 6, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); } pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 { pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]); if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_LessOrEqual); else condEvilBranch(mVU, Jcc_LessOrEqual);
} }
pass3 { mVUlog("IBLEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } 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); setBranchA(mX, 7, 0);
pass1 { mVUanalyzeCondBranch1(mVU, _Is_); } pass1 { mVUanalyzeCondBranch1(mVU, _Is_); }
pass2 { pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]); if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!(isBadOrEvil)) xMOV(ptr32[&mVU->branch], gprT1); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1);
else condEvilBranch(mVU, Jcc_Less); else condEvilBranch(mVU, Jcc_Less);
} }
pass3 { mVUlog("IBLTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } 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); setBranchA(mX, 8, 0);
pass1 { mVUanalyzeCondBranch2(mVU, _Is_, _It_); } pass1 { mVUanalyzeCondBranch2(mVU, _Is_, _It_); }
pass2 { pass2 {
if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU->VIbackup]); if (mVUlow.memReadIs) xMOV(gprT1, ptr32[&mVU.VIbackup]);
else mVUallocVIa(mVU, gprT1, _Is_); 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); } 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); else condEvilBranch(mVU, Jcc_NotEqual);
} }
pass3 { mVUlog("IBNE vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); } 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) { if (!mVUlow.constJump.isValid || mVUlow.evilBranch) {
mVUallocVIa(mVU, gprT1, _Is_); mVUallocVIa(mVU, gprT1, _Is_);
xSHL(gprT1, 3); xSHL(gprT1, 3);
xAND(gprT1, mVU->microMemSize - 8); xAND(gprT1, mVU.microMemSize - 8);
xMOV(ptr32[&mVU->branch], gprT1); xMOV(ptr32[&mVU.branch], gprT1);
if (!mVUlow.evilBranch) xMOV(ptr32[&mVU->branch], gprT1); if (!mVUlow.evilBranch) xMOV(ptr32[&mVU.branch], gprT1);
else xMOV(ptr32[&mVU->evilBranch], gprT1); else xMOV(ptr32[&mVU.evilBranch], gprT1);
if (mVUlow.badBranch) { if (mVUlow.badBranch) {
xADD(gprT1, 8); xADD(gprT1, 8);
xAND(gprT1, mVU->microMemSize - 8); xAND(gprT1, mVU.microMemSize - 8);
xMOV(ptr32[&mVU->badBranch], gprT1); xMOV(ptr32[&mVU.badBranch], gprT1);
} }
} }
} }

View File

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

View File

@ -85,43 +85,43 @@ static const uint divD = 0x2080000;
// Helper Macros // Helper Macros
//------------------------------------------------------------------ //------------------------------------------------------------------
#define _Ft_ ((mVU->code >> 16) & 0x1F) // The ft 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 _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 _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 _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 _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 _Id_ ((mVU.code >> 6) & 0xF) // The id part of the instruction register
#define _X ((mVU->code>>24) & 0x1) #define _X ((mVU.code>>24) & 0x1)
#define _Y ((mVU->code>>23) & 0x1) #define _Y ((mVU.code>>23) & 0x1)
#define _Z ((mVU->code>>22) & 0x1) #define _Z ((mVU.code>>22) & 0x1)
#define _W ((mVU->code>>21) & 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_SS (_X+_Y+_Z+_W==1)
#define _XYZW_SS2 (_XYZW_SS && (_X_Y_Z_W != 8)) #define _XYZW_SS2 (_XYZW_SS && (_X_Y_Z_W != 8))
#define _XYZW_PS (_X_Y_Z_W == 0xf) #define _XYZW_PS (_X_Y_Z_W == 0xf)
#define _XYZWss(x) ((x==8) || (x==4) || (x==2) || (x==1)) #define _XYZWss(x) ((x==8) || (x==4) || (x==2) || (x==1))
#define _bc_ (mVU->code & 0x3) #define _bc_ (mVU.code & 0x3)
#define _bc_x ((mVU->code & 0x3) == 0) #define _bc_x ((mVU.code & 0x3) == 0)
#define _bc_y ((mVU->code & 0x3) == 1) #define _bc_y ((mVU.code & 0x3) == 1)
#define _bc_z ((mVU->code & 0x3) == 2) #define _bc_z ((mVU.code & 0x3) == 2)
#define _bc_w ((mVU->code & 0x3) == 3) #define _bc_w ((mVU.code & 0x3) == 3)
#define _Fsf_ ((mVU->code >> 21) & 0x03) #define _Fsf_ ((mVU.code >> 21) & 0x03)
#define _Ftf_ ((mVU->code >> 23) & 0x03) #define _Ftf_ ((mVU.code >> 23) & 0x03)
#define _Imm5_ (mVU->Imm5()) #define _Imm5_ (mVU.Imm5())
#define _Imm11_ (mVU->Imm11()) #define _Imm11_ (mVU.Imm11())
#define _Imm12_ (mVU->Imm12()) #define _Imm12_ (mVU.Imm12())
#define _Imm15_ (mVU->Imm15()) #define _Imm15_ (mVU.Imm15())
#define _Imm24_ (mVU->Imm24()) #define _Imm24_ (mVU.Imm24())
#define isCOP2 (mVU->cop2 != 0) #define isCOP2 (mVU.cop2 != 0)
#define isVU1 (mVU->index != 0) #define isVU1 (mVU.index != 0)
#define isVU0 (mVU->index == 0) #define isVU0 (mVU.index == 0)
#define getIndex (isVU1 ? 1 : 0) #define getIndex (isVU1 ? 1 : 0)
#define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16) #define getVUmem(x) (((isVU1) ? (x & 0x3ff) : ((x >= 0x400) ? (x & 0x43f) : (x & 0xff))) * 16)
#define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12))) #define offsetSS ((_X) ? (0) : ((_Y) ? (4) : ((_Z) ? 8: 12)))
@ -149,12 +149,12 @@ static const uint divD = 0x2080000;
#define gprF3 edi // Status Flag 3 #define gprF3 edi // Status Flag 3
// Function Params // Function Params
#define mP microVU* mVU, int recPass #define mP microVU& mVU, int recPass
#define mV microVU* mVU #define mV microVU& mVU
#define mF int recPass #define mF int recPass
#define mX mVU, 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; typedef Fntype_mVUrecInst* Fnptr_mVUrecInst;
// Function/Template Stuff // Function/Template Stuff
@ -192,21 +192,21 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
//------------------------------------------------------------------ //------------------------------------------------------------------
// Misc Macros... // Misc Macros...
#define mVUcurProg mVU->prog.cur[0] #define mVUcurProg mVU.prog.cur[0]
#define mVUblocks mVU->prog.cur->block #define mVUblocks mVU.prog.cur->block
#define mVUir mVU->prog.IRinfo #define mVUir mVU.prog.IRinfo
#define mVUbranch mVU->prog.IRinfo.branch #define mVUbranch mVU.prog.IRinfo.branch
#define mVUcycles mVU->prog.IRinfo.cycles #define mVUcycles mVU.prog.IRinfo.cycles
#define mVUcount mVU->prog.IRinfo.count #define mVUcount mVU.prog.IRinfo.count
#define mVUpBlock mVU->prog.IRinfo.pBlock #define mVUpBlock mVU.prog.IRinfo.pBlock
#define mVUblock mVU->prog.IRinfo.block #define mVUblock mVU.prog.IRinfo.block
#define mVUregs mVU->prog.IRinfo.block.pState #define mVUregs mVU.prog.IRinfo.block.pState
#define mVUregsTemp mVU->prog.IRinfo.regsTemp #define mVUregsTemp mVU.prog.IRinfo.regsTemp
#define iPC mVU->prog.IRinfo.curPC #define iPC mVU.prog.IRinfo.curPC
#define mVUsFlagHack mVU->prog.IRinfo.sFlagHack #define mVUsFlagHack mVU.prog.IRinfo.sFlagHack
#define mVUconstReg mVU->prog.IRinfo.constReg #define mVUconstReg mVU.prog.IRinfo.constReg
#define mVUstartPC mVU->prog.IRinfo.startPC #define mVUstartPC mVU.prog.IRinfo.startPC
#define mVUinfo mVU->prog.IRinfo.info[iPC / 2] #define mVUinfo mVU.prog.IRinfo.info[iPC / 2]
#define mVUstall mVUinfo.stall #define mVUstall mVUinfo.stall
#define mVUup mVUinfo.uOp #define mVUup mVUinfo.uOp
#define mVUlow mVUinfo.lOp #define mVUlow mVUinfo.lOp
@ -217,18 +217,18 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define isEvilBlock (mVUpBlock->pState.blockType == 2) #define isEvilBlock (mVUpBlock->pState.blockType == 2)
#define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch) #define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch)
#define xPC ((iPC / 2) * 8) #define xPC ((iPC / 2) * 8)
#define curI ((u32*)mVU->regs().Micro)[iPC] //mVUcurProg.data[iPC] #define curI ((u32*)mVU.regs().Micro)[iPC] //mVUcurProg.data[iPC]
#define setCode() { mVU->code = curI; } #define setCode() { mVU.code = curI; }
#define incPC(x) (mVU->advancePC(x)) #define incPC(x) (mVU.advancePC(x))
#define branchAddr mVU->getBranchAddr() #define branchAddr mVU.getBranchAddr()
#define branchAddrN mVU->getBranchAddrN() #define branchAddrN mVU.getBranchAddrN()
#define incPC2(x) { iPC = ((iPC + (x)) & mVU->progMemMask); } #define incPC2(x) { iPC = ((iPC + (x)) & mVU.progMemMask); }
#define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8) #define bSaveAddr (((xPC + 16) & (mVU.microMemSize-8)) / 8)
#define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) #define shufflePQ (((mVU.p) ? 0xb0 : 0xe0) | ((mVU.q) ? 0x01 : 0x04))
#define cmpOffset(x) ((u8*)&(((u8*)x)[it[0].start])) #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 aWrap(x, m) ((x > m) ? 0 : x)
#define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4)))) #define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))
#define clampE CHECK_VU_EXTRA_OVERFLOW #define clampE CHECK_VU_EXTRA_OVERFLOW
@ -257,7 +257,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
// Program Logging... // Program Logging...
#ifdef mVUlogProg #ifdef mVUlogProg
#define mVUlog ((isVU1) ? __mVULog<1> : __mVULog<0>) #define mVUlog ((isVU1) ? __mVULog<1> : __mVULog<0>)
#define mVUdumpProg __mVUdumpProgram<vuIndex> #define mVUdumpProg __mVUdumpProgram
#else #else
#define mVUlog(...) if (0) {} #define mVUlog(...) if (0) {}
#define mVUdumpProg(...) 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) // 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) { if (toMemory) {
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
xMOVAPS(ptr128[&mVU->xmmBackup[i][0]], xmm(i)); xMOVAPS(ptr128[&mVU.xmmBackup[i][0]], xmm(i));
} }
} }
else { else {
mVU->regAlloc->flushAll(); // Flush Regalloc mVU.regAlloc->flushAll(); // Flush Regalloc
xMOVAPS(ptr128[&mVU->xmmBackup[xmmPQ.Id][0]], xmmPQ); xMOVAPS(ptr128[&mVU.xmmBackup[xmmPQ.Id][0]], xmmPQ);
} }
} }
// Restore Volatile Regs // Restore Volatile Regs
__fi void mVUrestoreRegs(microVU* mVU, bool fromMemory = false) __fi void mVUrestoreRegs(microVU& mVU, bool fromMemory = false)
{ {
if (fromMemory) { if (fromMemory) {
for(int i = 0; i < 8; i++) { 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 // 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(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(gprT2); // So we don't spam console, we'll only check micro-mode...
xPUSH(gprT3); xPUSH(gprT3);
xMOV (gprT2, mVU->prog.cur->idx); xMOV (gprT2, mVU.prog.cur->idx);
xMOV (gprT3, xPC); xMOV (gprT3, xPC);
xCALL(mVUwarningRegAccess); xCALL(mVUwarningRegAccess);
xPOP (gprT3); xPOP (gprT3);
@ -288,10 +288,10 @@ static const __aligned16 SSEMaskPair MIN_MAX =
// Warning: Modifies t1 and t2 // 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& t1 = t1in.IsEmpty() ? mVU.regAlloc->allocReg() : t1in;
const xmm& t2 = t2in.IsEmpty() ? mVU->regAlloc->allocReg() : t2in; const xmm& t2 = t2in.IsEmpty() ? mVU.regAlloc->allocReg() : t2in;
// ZW // ZW
xPSHUF.D(t1, to, 0xfa); xPSHUF.D(t1, to, 0xfa);
xPAND (t1, ptr128[MIN_MAX.mask1]); 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); else xMAX.PD(to, t2);
xSHUF.PS(to, t1, 0x88); xSHUF.PS(to, t1, 0x88);
if (t1 != t1in) mVU->regAlloc->clearNeeded(t1); if (t1 != t1in) mVU.regAlloc->clearNeeded(t1);
if (t2 != t2in) mVU->regAlloc->clearNeeded(t2); if (t2 != t2in) mVU.regAlloc->clearNeeded(t2);
} }
// Warning: Modifies to's upper 3 vectors, and t1 // 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) 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); xSHUF.PS(to, from, 0);
xPAND (to, ptr128[MIN_MAX.mask1]); xPAND (to, ptr128[MIN_MAX.mask1]);
xPOR (to, ptr128[MIN_MAX.mask2]); xPOR (to, ptr128[MIN_MAX.mask2]);
xPSHUF.D(t1, to, 0xee); xPSHUF.D(t1, to, 0xee);
if (min) xMIN.PD(to, t1); if (min) xMIN.PD(to, t1);
else xMAX.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 // 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& t1 = t1in.IsEmpty() ? mVU.regAlloc->allocReg() : t1in;
const xmm& t2 = t2in.IsEmpty() ? mVU->regAlloc->allocReg() : t2in; const xmm& t2 = t2in.IsEmpty() ? mVU.regAlloc->allocReg() : t2in;
xMOVAPS(t1, to); xMOVAPS(t1, to);
xMOVAPS(t2, from); 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(to, t1); // to contains mask
xAND.PS(from, t2); // from contains mask xAND.PS(from, t2); // from contains mask
xADD.SS(to, from); xADD.SS(to, from);
if (t1 != t1in) mVU->regAlloc->clearNeeded(t1); if (t1 != t1in) mVU.regAlloc->clearNeeded(t1);
if (t2 != t2in) mVU->regAlloc->clearNeeded(t2); if (t2 != t2in) mVU.regAlloc->clearNeeded(t2);
} }
#define clampOp(opX, isPS) { \ #define clampOp(opX, isPS) { \

View File

@ -199,20 +199,20 @@ static const Fnptr_mVUrecInst mVU_UPPER_FD_11_TABLE [32] = {
// Table Functions // Table Functions
//------------------------------------------------------------------ //------------------------------------------------------------------
mVUop(mVU_UPPER_FD_00) { mVU_UPPER_FD_00_TABLE [((mVU->code >> 6) & 0x1f)](mX); } 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_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_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(mVU_UPPER_FD_11) { mVU_UPPER_FD_11_TABLE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP) { mVULowerOP_OPCODE [ (mVU->code & 0x3f) ](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_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_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_10) { mVULowerOP_T3_10_OPCODE [((mVU.code >> 6) & 0x1f)](mX); }
mVUop(mVULowerOP_T3_11) { mVULowerOP_T3_11_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(mVUopU) { mVU_UPPER_OPCODE [ (mVU.code & 0x3f) ](mX); } // Gets Upper Opcode
mVUop(mVUopL) { mVULOWER_OPCODE [ (mVU->code >> 25) ](mX); } // Gets Lower Opcode mVUop(mVUopL) { mVULOWER_OPCODE [ (mVU.code >> 25) ](mX); } // Gets Lower Opcode
mVUop(mVUunknown) { mVUop(mVUunknown) {
pass1 { mVUinfo.isBadOp = true; } pass1 { mVUinfo.isBadOp = true; }
pass2 { Console.Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", getIndex, mVU->code, xPC); } pass2 { Console.Error("microVU%d: Unknown Micro VU opcode called (%x) [%04x]\n", getIndex, mVU.code, xPC); }
pass3 { mVUlog("Unknown", mVU->code); } 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); //SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; } 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; xmm regT2 = reg;
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) { if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) {
regT2 = regT2in; regT2 = regT2in;
if (regT2.IsEmpty()) { if (regT2.IsEmpty()) {
regT2 = mVU->regAlloc->allocReg(); regT2 = mVU.regAlloc->allocReg();
regT2b = true; regT2b = true;
} }
xPSHUF.D(regT2, reg, 0x1B); // Flip wzyx to xyzw 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); xOR (sReg, mReg);
} }
} }
if (regT1b) mVU->regAlloc->clearNeeded(regT1); if (regT1b) mVU.regAlloc->clearNeeded(regT1);
if (regT2b) mVU->regAlloc->clearNeeded(regT2); if (regT2b) mVU.regAlloc->clearNeeded(regT2);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// Helper Macros and Functions // 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_ADDPS, // 0
SSE_SUBPS, // 1 SSE_SUBPS, // 1
SSE_MULPS, // 2 SSE_MULPS, // 2
@ -94,7 +94,7 @@ static void (*const SSE_PS[]) (microVU*, const xmm&, const xmm&, const xmm&, con
SSE_ADD2PS // 5 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_ADDSS, // 0
SSE_SUBSS, // 1 SSE_SUBSS, // 1
SSE_MULSS, // 2 SSE_MULSS, // 2
@ -110,7 +110,7 @@ enum clampModes {
}; };
// Prints Opcode to MicroProgram Logs // 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); mVUlog(opName);
opCase1 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogFt(); } opCase1 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogFt(); }
opCase2 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogBC(); } 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 // 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_); } opCase1 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); }
opCase2 { mVUanalyzeFMAC3(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); } opCase2 { mVUanalyzeFMAC3(mVU, ((isACC) ? 0 : _Fd_), _Fs_, _Ft_); }
opCase3 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, 0); } 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 // 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 { opCase1 {
if ((opType == 1) && (_Ft_ == _Fs_)) { 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 xPXOR(Fs, Fs); // Set to Positive 0
mVUupdateFlags(mVU, Fs); mVUupdateFlags(mVU, Fs);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
return 1; 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 // 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 { opCase1 {
if (_XYZW_SS2) { Ft = mVU->regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W); tempFt = Ft; } 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 if (clampE) { Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0xf); tempFt = Ft; }
else { Ft = mVU->regAlloc->allocReg(_Ft_); tempFt = xEmptyReg; } else { Ft = mVU.regAlloc->allocReg(_Ft_); tempFt = xEmptyReg; }
} }
opCase2 { opCase2 {
tempFt = mVU->regAlloc->allocReg(_Ft_); tempFt = mVU.regAlloc->allocReg(_Ft_);
Ft = mVU->regAlloc->allocReg(); Ft = mVU.regAlloc->allocReg();
mVUunpack_xyzw(Ft, tempFt, _bc_); mVUunpack_xyzw(Ft, tempFt, _bc_);
mVU->regAlloc->clearNeeded(tempFt); mVU.regAlloc->clearNeeded(tempFt);
tempFt = Ft; 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 { opCase4 {
if (!clampE && _XYZW_SS && !mVUinfo.readQ) { Ft = xmmPQ; tempFt = xEmptyReg; } 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 // 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))); } pass1 { setupPass1(mVU, opCase, isACC, ((opType == 3) || (opType == 4))); }
pass2 { pass2 {
if (doSafeSub(mVU, opCase, opType, isACC)) return; 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); setupFtReg(mVU, Ft, tempFt, opCase);
if (isACC) { if (isACC) {
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU->regAlloc->allocReg((_X_Y_Z_W == 0xf) ? -1 : 32, 32, 0xf, 0); 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)); 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 & cFt) mVUclamp2(mVU, Ft, xEmptyReg, _X_Y_Z_W);
if (clampType & cFs) mVUclamp2(mVU, Fs, 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); else mVUmergeRegs(ACC, Fs, _X_Y_Z_W);
mVUupdateFlags(mVU, ACC, Fs, tempFt); mVUupdateFlags(mVU, ACC, Fs, tempFt);
if (_XYZW_SS2) xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W)); 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); else mVUupdateFlags(mVU, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First mVU.regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
} }
pass3 { mVU_printOP(mVU, opCase, opName, isACC); } pass3 { mVU_printOP(mVU, opCase, opName, isACC); }
pass4 { if ((opType != 3) && (opType != 4)) mVUregs.needExactMatch |= 8; } pass4 { if ((opType != 3) && (opType != 4)) mVUregs.needExactMatch |= 8; }
} }
// MADDA/MSUBA Opcodes // 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); } pass1 { setupPass1(mVU, opCase, 1, 0); }
pass2 { pass2 {
xmm Fs, Ft, ACC, tempFt; xmm Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase); setupFtReg(mVU, Ft, tempFt, opCase);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU->regAlloc->allocReg(32, 32, 0xf, 0); ACC = mVU.regAlloc->allocReg(32, 32, 0xf, 0);
if (_XYZW_SS2) { xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W)); } 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)); if (_XYZW_SS && _X_Y_Z_W != 8) xPSHUF.D(ACC, ACC, shuffleSS(_X_Y_Z_W));
} }
else { else {
const xmm& tempACC = mVU->regAlloc->allocReg(); const xmm& tempACC = mVU.regAlloc->allocReg();
xMOVAPS(tempACC, ACC); xMOVAPS(tempACC, ACC);
SSE_PS[opType](mVU, tempACC, Fs, tempFt, xEmptyReg); SSE_PS[opType](mVU, tempACC, Fs, tempFt, xEmptyReg);
mVUmergeRegs(ACC, tempACC, _X_Y_Z_W); mVUmergeRegs(ACC, tempACC, _X_Y_Z_W);
mVUupdateFlags(mVU, ACC, Fs, tempFt); mVUupdateFlags(mVU, ACC, Fs, tempFt);
mVU->regAlloc->clearNeeded(tempACC); mVU.regAlloc->clearNeeded(tempACC);
} }
mVU->regAlloc->clearNeeded(ACC); mVU.regAlloc->clearNeeded(ACC);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
} }
pass3 { mVU_printOP(mVU, opCase, opName, 1); } pass3 { mVU_printOP(mVU, opCase, opName, 1); }
pass4 { mVUregs.needExactMatch |= 8; } pass4 { mVUregs.needExactMatch |= 8; }
} }
// MADD Opcodes // 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); } pass1 { setupPass1(mVU, opCase, 0, 0); }
pass2 { pass2 {
xmm Fs, Ft, ACC, tempFt; xmm Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase); setupFtReg(mVU, Ft, tempFt, opCase);
ACC = mVU->regAlloc->allocReg(32); ACC = mVU.regAlloc->allocReg(32);
Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W); Fs = mVU.regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W);
if (_XYZW_SS2) { xPSHUF.D(ACC, ACC, shuffleSS(_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); mVUupdateFlags(mVU, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First mVU.regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(ACC); mVU.regAlloc->clearNeeded(ACC);
} }
pass3 { mVU_printOP(mVU, opCase, opName, 0); } pass3 { mVU_printOP(mVU, opCase, opName, 0); }
pass4 { mVUregs.needExactMatch |= 8; } pass4 { mVUregs.needExactMatch |= 8; }
} }
// MSUB Opcodes // 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); } pass1 { setupPass1(mVU, opCase, 0, 0); }
pass2 { pass2 {
xmm Fs, Ft, Fd, tempFt; xmm Fs, Ft, Fd, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase); setupFtReg(mVU, Ft, tempFt, opCase);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
Fd = mVU->regAlloc->allocReg(32, _Fd_, _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 & cFt) mVUclamp2(mVU, Ft, xEmptyReg, _X_Y_Z_W);
if (clampType & cFs) mVUclamp2(mVU, Fs, 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); mVUupdateFlags(mVU, Fd, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fd); // Always Clear Written Reg First mVU.regAlloc->clearNeeded(Fd); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVU_printOP(mVU, opCase, opName, 0); } pass3 { mVU_printOP(mVU, opCase, opName, 0); }
pass4 { mVUregs.needExactMatch |= 8; } pass4 { mVUregs.needExactMatch |= 8; }
@ -304,9 +304,9 @@ mVUop(mVU_ABS) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
if (!_Ft_) return; 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]); xAND.PS(Fs, ptr128[mVUglob.absclip]);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("ABS"); mVUlogFtFs(); } pass3 { mVUlog("ABS"); mVUlogFtFs(); }
} }
@ -315,15 +315,15 @@ mVUop(mVU_ABS) {
mVUop(mVU_OPMULA) { mVUop(mVU_OPMULA) {
pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC1(mVU, 0, _Fs_, _Ft_); }
pass2 { pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, _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); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 32, _X_Y_Z_W);
xPSHUF.D(Fs, Fs, 0xC9); // WXZY xPSHUF.D(Fs, Fs, 0xC9); // WXZY
xPSHUF.D(Ft, Ft, 0xD2); // WYXZ xPSHUF.D(Ft, Ft, 0xD2); // WYXZ
SSE_MULPS(mVU, Fs, Ft); SSE_MULPS(mVU, Fs, Ft);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVUupdateFlags(mVU, Fs); mVUupdateFlags(mVU, Fs);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog("OPMULA"); mVUlogACC(); mVUlogFt(); } pass3 { mVUlog("OPMULA"); mVUlogACC(); mVUlogFt(); }
pass4 { mVUregs.needExactMatch |= 8; } pass4 { mVUregs.needExactMatch |= 8; }
@ -333,18 +333,18 @@ mVUop(mVU_OPMULA) {
mVUop(mVU_OPMSUB) { mVUop(mVU_OPMSUB) {
pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC1(mVU, _Fd_, _Fs_, _Ft_); }
pass2 { pass2 {
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, 0xf); const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0xf);
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 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& ACC = mVU.regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
xPSHUF.D(Fs, Fs, 0xC9); // WXZY xPSHUF.D(Fs, Fs, 0xC9); // WXZY
xPSHUF.D(Ft, Ft, 0xD2); // WYXZ xPSHUF.D(Ft, Ft, 0xD2); // WYXZ
SSE_MULPS(mVU, Fs, Ft); SSE_MULPS(mVU, Fs, Ft);
SSE_SUBPS(mVU, ACC, Fs); SSE_SUBPS(mVU, ACC, Fs);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVUupdateFlags(mVU, ACC); mVUupdateFlags(mVU, ACC);
mVU->regAlloc->clearNeeded(ACC); mVU.regAlloc->clearNeeded(ACC);
} }
pass3 { mVUlog("OPMSUB"); mVUlogFd(); mVUlogFt(); } 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_); } pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
if (!_Ft_) return; 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)));
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
const xmm& t2 = mVU->regAlloc->allocReg(); const xmm& t2 = mVU.regAlloc->allocReg();
// Note: For help understanding this algorithm see recVUMI_FTOI_Saturate() // Note: For help understanding this algorithm see recVUMI_FTOI_Saturate()
xMOVAPS(t1, Fs); xMOVAPS(t1, Fs);
@ -371,9 +371,9 @@ static void mVU_FTOIx(mP, const float* addr, const char* opName) {
xAND.PS(t1, t2); xAND.PS(t1, t2);
xPADD.D(Fs, t1); xPADD.D(Fs, t1);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
mVU->regAlloc->clearNeeded(t2); mVU.regAlloc->clearNeeded(t2);
} }
pass3 { mVUlog(opName); mVUlogFtFs(); } pass3 { mVUlog(opName); mVUlogFtFs(); }
} }
@ -383,13 +383,13 @@ static void mVU_ITOFx(mP, const float* addr, const char* opName) {
pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
if (!_Ft_) return; 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); xCVTDQ2PS(Fs, Fs);
if (addr) { xMUL.PS(Fs, ptr128[addr]); } if (addr) { xMUL.PS(Fs, ptr128[addr]); }
//mVUclamp2(Fs, xmmT1, 15); // Clamp (not sure if this is needed) //mVUclamp2(Fs, xmmT1, 15); // Clamp (not sure if this is needed)
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
} }
pass3 { mVUlog(opName); mVUlogFtFs(); } pass3 { mVUlog(opName); mVUlogFtFs(); }
} }
@ -398,9 +398,9 @@ static void mVU_ITOFx(mP, const float* addr, const char* opName) {
mVUop(mVU_CLIP) { mVUop(mVU_CLIP) {
pass1 { mVUanalyzeFMAC4(mVU, _Fs_, _Ft_); } pass1 { mVUanalyzeFMAC4(mVU, _Fs_, _Ft_); }
pass2 { pass2 {
const xmm& Fs = mVU->regAlloc->allocReg(_Fs_, 0, 0xf); const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, 0xf);
const xmm& Ft = mVU->regAlloc->allocReg(_Ft_, 0, 0x1); const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, 0x1);
const xmm& t1 = mVU->regAlloc->allocReg(); const xmm& t1 = mVU.regAlloc->allocReg();
mVUunpack_xyzw(Ft, Ft, 0); mVUunpack_xyzw(Ft, Ft, 0);
mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite); mVUallocCFLAGa(mVU, gprT1, cFLAG.lastWrite);
@ -428,9 +428,9 @@ mVUop(mVU_CLIP) {
xAND(gprT1, 0xffffff); xAND(gprT1, 0xffffff);
mVUallocCFLAGb(mVU, gprT1, cFLAG.write); mVUallocCFLAGb(mVU, gprT1, cFLAG.write);
mVU->regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Ft);
mVU->regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t1);
} }
pass3 { mVUlog("CLIP"); mVUlogCLIP(); } pass3 { mVUlog("CLIP"); mVUlogCLIP(); }
} }