mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
9afb0d9edf
commit
69896ce034
|
@ -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))) {
|
||||||
|
@ -262,8 +262,8 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
|
||||||
// If cleared and program not found, make a new program instance
|
// If cleared and program not found, make a new program instance
|
||||||
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(µVU0); }
|
void recMicroVU0::Vsync() throw() { mVUvsyncUpdate(microVU0); }
|
||||||
void recMicroVU1::Vsync() throw() { mVUvsyncUpdate(µVU1); }
|
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(µVU0, 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(µVU1, addr, size);
|
mVUclear(microVU1, addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint recMicroVU0::GetCacheReserve() const {
|
uint recMicroVU0::GetCacheReserve() const {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(µVU0, 0); \
|
mVU_##f(microVU0, 0); \
|
||||||
if (!microVU0.prog.IRinfo.info[0].lOp.isNOP) { \
|
if (!microVU0.prog.IRinfo.info[0].lOp.isNOP) { \
|
||||||
mVU_##f(µVU0, 1); \
|
mVU_##f(microVU0, 1); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
else { mVU_##f(µVU0, 1); } \
|
else { mVU_##f(microVU0, 1); } \
|
||||||
endMacroOp(mode); \
|
endMacroOp(mode); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
|
@ -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) { \
|
||||||
|
|
|
@ -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); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(); }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue