mirror of https://github.com/PCSX2/pcsx2.git
microVU:
- reverted to r1299 git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1302 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
28f52a3f12
commit
a336e6b277
|
@ -98,7 +98,6 @@ struct microProgManager {
|
|||
#define mVUcacheSize (0x2000000 / ((vuIndex) ? 1 : 4))
|
||||
struct microVU {
|
||||
|
||||
PCSX2_ALIGNED16(u32 statusFlag[4]); // 4 instances of status flag (used in execution)
|
||||
PCSX2_ALIGNED16(u32 macFlag[4]); // 4 instances of mac flag (used in execution)
|
||||
PCSX2_ALIGNED16(u32 clipFlag[4]); // 4 instances of clip flag (used in execution)
|
||||
PCSX2_ALIGNED16(u32 xmmPQb[4]); // Backup for xmmPQ
|
||||
|
|
|
@ -634,13 +634,28 @@ microVUt(void) mVUallocFMAC26b(mV, int& ACCw, int& ACCr) {
|
|||
// Flag Allocators
|
||||
//------------------------------------------------------------------
|
||||
|
||||
microVUt(void) mVUallocSFLAGa(mV, int reg, int fInstance) {
|
||||
MOVZX32M16toR(reg, (uptr)&mVU->statusFlag[fInstance]);
|
||||
#define getFlagReg(regX, fInst) { \
|
||||
switch (fInst) { \
|
||||
case 0: regX = gprF0; break; \
|
||||
case 1: regX = gprF1; break; \
|
||||
case 2: regX = gprF2; break; \
|
||||
case 3: regX = gprF3; break; \
|
||||
default: \
|
||||
Console::Error("microVU: Flag Instance Error (fInst = %d)", params fInst); \
|
||||
regX = gprF0; \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocSFLAGb(mV, int reg, int fInstance) {
|
||||
microVUt(void) mVUallocSFLAGa(int reg, int fInstance) {
|
||||
getFlagReg(fInstance, fInstance);
|
||||
MOVZX32R16toR(reg, fInstance);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocSFLAGb(int reg, int fInstance) {
|
||||
getFlagReg(fInstance, fInstance);
|
||||
//AND32ItoR(reg, 0xffff);
|
||||
MOV32RtoM((uptr)&mVU->statusFlag[fInstance], reg);
|
||||
MOV32RtoR(fInstance, reg);
|
||||
}
|
||||
|
||||
microVUt(void) mVUallocMFLAGa(mV, int reg, int fInstance) {
|
||||
|
|
|
@ -62,8 +62,7 @@
|
|||
}
|
||||
|
||||
microVUt(void) mVUanalyzeFMAC1(mV, int Fd, int Fs, int Ft) {
|
||||
mVUup.doFlags = 1;
|
||||
sFLAG.doSticky = 1;
|
||||
sFLAG.doFlag = 1;
|
||||
analyzeReg1(Fs);
|
||||
analyzeReg1(Ft);
|
||||
analyzeReg2(Fd, 0);
|
||||
|
@ -92,8 +91,7 @@ microVUt(void) mVUanalyzeFMAC2(mV, int Fs, int Ft) {
|
|||
}
|
||||
|
||||
microVUt(void) mVUanalyzeFMAC3(mV, int Fd, int Fs, int Ft) {
|
||||
mVUup.doFlags = 1;
|
||||
sFLAG.doSticky = 1;
|
||||
sFLAG.doFlag = 1;
|
||||
analyzeReg1(Fs);
|
||||
analyzeReg3(Ft);
|
||||
analyzeReg2(Fd, 0);
|
||||
|
@ -271,15 +269,6 @@ microVUt(void) mVUanalyzeR2(mV, int Ft, bool canBeNOP) {
|
|||
// Sflag - Status Flag Opcodes
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define setFlagInst(xDoFlag) { \
|
||||
int curPC = iPC; \
|
||||
for (int i = mVUcount, j = 0; i > 0; i--, j++) { \
|
||||
incPC2(-2); \
|
||||
if (mVUup.doFlags) { xDoFlag = 1; if (j >= 3) { break; } } \
|
||||
} \
|
||||
iPC = curPC; \
|
||||
}
|
||||
|
||||
microVUt(void) mVUanalyzeSflag(mV, int It) {
|
||||
if (!It) { mVUlow.isNOP = 1; }
|
||||
else {
|
||||
|
@ -290,15 +279,17 @@ microVUt(void) mVUanalyzeSflag(mV, int It) {
|
|||
// Note: useSflag is used for status flag optimizations when a FSSET instruction is called.
|
||||
// Do to stalls, it can only be set one instruction prior to the status flag read instruction
|
||||
// if we were guaranteed no-stalls were to happen, it could be set 4 instruction prior.
|
||||
setFlagInst(sFLAG.doFlag);
|
||||
}
|
||||
analyzeVIreg3(It, 1);
|
||||
}
|
||||
|
||||
microVUt(void) mVUanalyzeFSSET(mV) {
|
||||
mVUinfo.swapOps = 1;
|
||||
mVUlow.isFSSET = 1;
|
||||
sFLAG.doSticky = 0;
|
||||
// mVUinfo &= ~_doStatus;
|
||||
// Note: I'm not entirely sure if the non-sticky flags
|
||||
// should be taken from the current upper instruction
|
||||
// or if they should be taken from the previous instruction
|
||||
// Uncomment the above line if the latter-case is true
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -310,7 +301,12 @@ microVUt(void) mVUanalyzeMflag(mV, int Is, int It) {
|
|||
else { // Need set _doMac for 4 previous Ops (need to do all 4 because stalls could change the result needed)
|
||||
mVUinfo.swapOps = 1;
|
||||
if (mVUcount < 4) { mVUpBlock->pState.needExactMatch |= 0xf << (/*mVUcount +*/ 4); }
|
||||
setFlagInst(mFLAG.doFlag);
|
||||
int curPC = iPC;
|
||||
for (int i = mVUcount, j = 0; i > 0; i--, j++) {
|
||||
incPC2(-2);
|
||||
if (sFLAG.doFlag) { mFLAG.doFlag = 1; if (j >= 3) { break; } }
|
||||
}
|
||||
iPC = curPC;
|
||||
}
|
||||
analyzeVIreg1(Is);
|
||||
analyzeVIreg3(It, 1);
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#define tCycles(dest, src) { dest = aMax(dest, src); }
|
||||
#define incP() { mVU->p = (mVU->p+1) & 1; }
|
||||
#define incQ() { mVU->q = (mVU->q+1) & 1; }
|
||||
#define doUpperOp() { mVUopU(mVU, 1); mVUdivSet(mVU); }
|
||||
#define doLowerOp() { incPC(-1); mVUopL(mVU, 1); incPC(1); }
|
||||
#define doIbit() { if (mVUup.iBit) { incPC(-1); MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, curI); incPC(1); } }
|
||||
|
||||
|
@ -168,7 +169,8 @@ microVUt(void) mVUendProgram(mV, int qInst, int pInst, int fStatus, int fMac, in
|
|||
|
||||
// Save Flag Instances
|
||||
if (!mVUflagHack) {
|
||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, gprST);
|
||||
getFlagReg(fStatus, fStatus);
|
||||
MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, fStatus);
|
||||
}
|
||||
mVUallocMFLAGa(mVU, gprT1, fMac);
|
||||
mVUallocCFLAGa(mVU, gprT2, fClip);
|
||||
|
@ -198,6 +200,7 @@ microVUt(void) mVUtestCycles(mV) {
|
|||
MOV32ItoR(gprT2, xPC);
|
||||
if (!isVU1) CALLFunc((uptr)mVUwarning0);
|
||||
else CALLFunc((uptr)mVUwarning1);
|
||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
||||
mVUendProgram(mVU, 0, 0, sI, 0, cI);
|
||||
x86SetJ8(jmp8);
|
||||
}
|
||||
|
@ -274,11 +277,10 @@ microVUf(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
|
|||
mVUbranch = 0;
|
||||
int x;
|
||||
for (x = 0; x < (vuIndex ? (0x3fff/8) : (0xfff/8)); x++) {
|
||||
mVUdivSet(mVU);
|
||||
if (mVUinfo.isEOB) { x = 0xffff; }
|
||||
if (mVUlow.isNOP) { incPC(1); mVUopU(mVU, 1); doIbit(); }
|
||||
else if (!mVUinfo.swapOps) { incPC(1); mVUopU(mVU, 1); doLowerOp(); }
|
||||
else { mVUopL(mVU, 1); incPC(1); mVUopU(mVU, 1); }
|
||||
if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(); }
|
||||
else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); }
|
||||
else { mVUopL(mVU, 1); incPC(1); doUpperOp(); }
|
||||
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
|
||||
|
||||
if (!mVUinfo.isBdelay) { incPC(1); }
|
||||
|
@ -320,7 +322,7 @@ microVUf(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
|
|||
|
||||
mVUbackupRegs(mVU);
|
||||
MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX first argument for __fastcall)
|
||||
MOV32ItoR(gprT3, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall)
|
||||
MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall)
|
||||
|
||||
if (!isVU1) CALLFunc((uptr)mVUcompileVU0); //(u32 startPC, uptr pState)
|
||||
else CALLFunc((uptr)mVUcompileVU1);
|
||||
|
@ -374,8 +376,10 @@ eBitTemination:
|
|||
incCycles(100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
|
||||
mVUcycles -= 100;
|
||||
if (mVUinfo.doDivFlag) {
|
||||
AND32ItoR(gprST, 0xfcf);
|
||||
OR32MtoR (gprST, (uptr)&mVU->divFlag);
|
||||
int flagReg;
|
||||
getFlagReg(flagReg, lStatus);
|
||||
AND32ItoR (flagReg, 0x0fcf);
|
||||
OR32MtoR (flagReg, (uptr)&mVU->divFlag);
|
||||
}
|
||||
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
|
||||
|
||||
|
|
|
@ -41,8 +41,11 @@ microVUt(void) mVUdispatcherA(mV) {
|
|||
|
||||
// Load Regs
|
||||
MOV32ItoR(gprR, Roffset); // Load VI Reg Offset
|
||||
MOV32MtoR(gprST, (uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL);
|
||||
AND32ItoR(gprST, 0xffff);
|
||||
MOV32MtoR(gprF0, (uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL);
|
||||
AND32ItoR(gprF0, 0xffff);
|
||||
MOV32RtoR(gprF1, gprF0);
|
||||
MOV32RtoR(gprF2, gprF0);
|
||||
MOV32RtoR(gprF3, gprF0);
|
||||
|
||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_MAC_FLAG].UL);
|
||||
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, 0);
|
||||
|
|
|
@ -20,9 +20,12 @@
|
|||
|
||||
// Sets FDIV Flags at the proper time
|
||||
microVUt(void) mVUdivSet(mV) {
|
||||
int flagReg1, flagReg2;
|
||||
if (mVUinfo.doDivFlag) {
|
||||
AND32ItoR(gprST, 0xfcf); // Clear D/I bits
|
||||
OR32MtoR (gprST, (uptr)&mVU->divFlag); // Set DS/IS/D/I bits
|
||||
getFlagReg(flagReg1, sFLAG.write);
|
||||
if (!sFLAG.doFlag) { getFlagReg(flagReg2, sFLAG.lastWrite); MOV32RtoR(flagReg1, flagReg2); }
|
||||
AND32ItoR(flagReg1, 0x0fcf);
|
||||
OR32MtoR (flagReg1, (uptr)&mVU->divFlag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,19 +34,18 @@ microVUt(void) mVUstatusFlagOp(mV) {
|
|||
int curPC = iPC;
|
||||
int i = mVUcount;
|
||||
bool runLoop = 1;
|
||||
if (mVUup.doFlags) { mVUlow.useSflag = 1; }
|
||||
if (sFLAG.doFlag) { mVUlow.useSflag = 1; }
|
||||
else {
|
||||
for (; i > 0; i--) {
|
||||
incPC2(-2);
|
||||
if (mVUlow.useSflag) { runLoop = 0; break; }
|
||||
if (mVUup.doFlags) { mVUlow.useSflag = 1; break; }
|
||||
if (sFLAG.doFlag) { mVUlow.useSflag = 1; break; }
|
||||
}
|
||||
}
|
||||
if (runLoop) {
|
||||
for (; i > 0; i--) {
|
||||
incPC2(-2);
|
||||
if (mVUlow.useSflag) break;
|
||||
sFLAG.doSticky = 0;
|
||||
sFLAG.doFlag = 0;
|
||||
}
|
||||
}
|
||||
|
@ -77,11 +79,7 @@ microVUt(int) mVUsetFlags(mV, int* xStatus, int* xMac, int* xClip) {
|
|||
|
||||
// Ensure last ~4+ instructions update mac flags (if next block's first 4 instructions will read them)
|
||||
for (int i = mVUcount; i > 0; i--, aCount++) {
|
||||
if (mVUup.doFlags) {
|
||||
if (__Status) { sFLAG.doFlag = 1; }
|
||||
if (__Mac) { mFLAG.doFlag = 1; }
|
||||
if (aCount >= 4) { break; }
|
||||
}
|
||||
if (sFLAG.doFlag) { if (__Mac) { mFLAG.doFlag = 1; } if (aCount >= 4) { break; } }
|
||||
incPC2(-2);
|
||||
}
|
||||
|
||||
|
@ -144,13 +142,13 @@ microVUt(int) mVUsetFlags(mV, int* xStatus, int* xMac, int* xClip) {
|
|||
incPC2(2);
|
||||
}
|
||||
|
||||
mVUregs.flags = ((__Clip) ? 0 : (xC << 2)) /*| ((__Status) ? 0 : xS)*/;
|
||||
mVUregs.flags = ((__Clip) ? 0 : (xC << 2)) | ((__Status) ? 0 : xS);
|
||||
return cycles;
|
||||
}
|
||||
|
||||
#define shuffleStatus ((bStatus[3]<<6)|(bStatus[2]<<4)|(bStatus[1]<<2)|bStatus[0])
|
||||
#define getFlagReg1(x) ((x == 3) ? gprF3 : ((x == 2) ? gprF2 : ((x == 1) ? gprF1 : gprF0)))
|
||||
#define shuffleMac ((bMac [3]<<6)|(bMac [2]<<4)|(bMac [1]<<2)|bMac [0])
|
||||
#define shuffleClip ((bClip [3]<<6)|(bClip [2]<<4)|(bClip [1]<<2)|bClip [0])
|
||||
#define shuffleClip ((bClip[3]<<6)|(bClip[2]<<4)|(bClip[1]<<2)|bClip[0])
|
||||
|
||||
// Recompiles Code for Proper Flags on Block Linkings
|
||||
microVUt(void) mVUsetupFlags(mV, int* xStatus, int* xMac, int* xClip, int cycles) {
|
||||
|
@ -158,9 +156,14 @@ microVUt(void) mVUsetupFlags(mV, int* xStatus, int* xMac, int* xClip, int cycles
|
|||
if (__Status && !mVUflagHack) {
|
||||
int bStatus[4];
|
||||
sortFlag(xStatus, bStatus, cycles);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)mVU->statusFlag);
|
||||
SSE_SHUFPS_XMM_to_XMM (xmmT1, xmmT1, shuffleStatus);
|
||||
SSE_MOVAPS_XMM_to_M128((uptr)mVU->statusFlag, xmmT1);
|
||||
MOV32RtoR(gprT1, getFlagReg1(bStatus[0]));
|
||||
MOV32RtoR(gprT2, getFlagReg1(bStatus[1]));
|
||||
MOV32RtoR(gprR, getFlagReg1(bStatus[2]));
|
||||
MOV32RtoR(gprF3, getFlagReg1(bStatus[3]));
|
||||
MOV32RtoR(gprF0, gprT1);
|
||||
MOV32RtoR(gprF1, gprT2);
|
||||
MOV32RtoR(gprF2, gprR);
|
||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
||||
}
|
||||
|
||||
if (__Mac) {
|
||||
|
|
|
@ -68,7 +68,6 @@ struct microBlock {
|
|||
struct microUpperOp {
|
||||
bool eBit; // Has E-bit set
|
||||
bool iBit; // Has I-bit set
|
||||
bool doFlags; // This instruction updates Status/Mac Flags
|
||||
};
|
||||
|
||||
struct microLowerOp {
|
||||
|
@ -84,8 +83,7 @@ struct microLowerOp {
|
|||
};
|
||||
|
||||
struct microFlagInst {
|
||||
bool doSticky; // Update Sticky Flags (Status Flag Only)
|
||||
bool doFlag; // Update Flag on this Instruction (For Status Flag, this means non-sticky bits)
|
||||
bool doFlag; // Update Flag on this Instruction
|
||||
u8 write; // Points to the instance that should be written to (s-stage write)
|
||||
u8 lastWrite; // Points to the instance that was last written to (most up-to-date flag)
|
||||
u8 read; // Points to the instance that should be read by a lower instruction (t-stage read)
|
||||
|
|
|
@ -522,7 +522,7 @@ mVUop(mVU_FMOR) {
|
|||
mVUop(mVU_FSAND) {
|
||||
pass1 { mVUanalyzeSflag(mVU, _It_); }
|
||||
pass2 {
|
||||
mVUallocSFLAGa(mVU, gprT1, sFLAG.read);
|
||||
mVUallocSFLAGa(gprT1, sFLAG.read);
|
||||
AND16ItoR(gprT1, _Imm12_);
|
||||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ mVUop(mVU_FSAND) {
|
|||
mVUop(mVU_FSEQ) {
|
||||
pass1 { mVUanalyzeSflag(mVU, _It_); }
|
||||
pass2 {
|
||||
mVUallocSFLAGa(mVU, gprT1, sFLAG.read);
|
||||
mVUallocSFLAGa(gprT1, sFLAG.read);
|
||||
XOR16ItoR(gprT1, _Imm12_);
|
||||
SUB16ItoR(gprT1, 1);
|
||||
SHR16ItoR(gprT1, 15);
|
||||
|
@ -546,7 +546,7 @@ mVUop(mVU_FSEQ) {
|
|||
mVUop(mVU_FSOR) {
|
||||
pass1 { mVUanalyzeSflag(mVU, _It_); }
|
||||
pass2 {
|
||||
mVUallocSFLAGa(mVU, gprT1, sFLAG.read);
|
||||
mVUallocSFLAGa(gprT1, sFLAG.read);
|
||||
OR16ItoR(gprT1, _Imm12_);
|
||||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
|
@ -557,9 +557,11 @@ mVUop(mVU_FSOR) {
|
|||
mVUop(mVU_FSSET) {
|
||||
pass1 { mVUanalyzeFSSET(mVU); }
|
||||
pass2 {
|
||||
int imm = _Imm12_ & 0xfc0;
|
||||
AND32ItoR(gprST, 0x3ff);
|
||||
if (imm) OR32ItoR(gprST, imm);
|
||||
int flagReg1, flagReg2;
|
||||
getFlagReg(flagReg1, sFLAG.write);
|
||||
if (!(sFLAG.doFlag||mVUinfo.doDivFlag)) { getFlagReg(flagReg2, sFLAG.lastWrite); MOV32RtoR(flagReg1, flagReg2); } // Get status result from last status setting instruction
|
||||
AND32ItoR(flagReg1, 0x03f);
|
||||
OR32ItoR (flagReg1, (_Imm12_ & 0xfc0));
|
||||
}
|
||||
pass3 { mVUlog("FSSET $%x", _Imm12_); }
|
||||
pass4 { mVUsFlagHack = 0; }
|
||||
|
@ -964,22 +966,23 @@ mVUop(mVU_RNEXT) {
|
|||
pass1 { mVUanalyzeR2(mVU, _Ft_, 0); }
|
||||
pass2 {
|
||||
// algorithm from www.project-fao.org
|
||||
MOV32MtoR(gprT3, Rmem);
|
||||
MOV32RtoR(gprT1, gprT3);
|
||||
MOV32MtoR(gprR, Rmem);
|
||||
MOV32RtoR(gprT1, gprR);
|
||||
SHR32ItoR(gprT1, 4);
|
||||
AND32ItoR(gprT1, 1);
|
||||
|
||||
MOV32RtoR(gprT2, gprT3);
|
||||
MOV32RtoR(gprT2, gprR);
|
||||
SHR32ItoR(gprT2, 22);
|
||||
AND32ItoR(gprT2, 1);
|
||||
|
||||
SHL32ItoR(gprT3, 1);
|
||||
SHL32ItoR(gprR, 1);
|
||||
XOR32RtoR(gprT1, gprT2);
|
||||
XOR32RtoR(gprT3, gprT1);
|
||||
AND32ItoR(gprT3, 0x007fffff);
|
||||
OR32ItoR (gprT3, 0x3f800000);
|
||||
MOV32RtoM(Rmem, gprT3);
|
||||
mVU_RGET_(mVU, gprT3);
|
||||
XOR32RtoR(gprR, gprT1);
|
||||
AND32ItoR(gprR, 0x007fffff);
|
||||
OR32ItoR (gprR, 0x3f800000);
|
||||
MOV32RtoM(Rmem, gprR);
|
||||
mVU_RGET_(mVU, gprR);
|
||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
||||
}
|
||||
pass3 { mVUlog("RNEXT.%s vf%02d, R", _XYZW_String, _Ft_); }
|
||||
}
|
||||
|
|
|
@ -131,12 +131,12 @@ declareAllVariables
|
|||
|
||||
#define gprT1 0 // Temp Reg
|
||||
#define gprT2 1 // Temp Reg
|
||||
#define gprT3 2 // Temp Reg
|
||||
#define gprR 2 // VI Reg Offset
|
||||
#define gprF0 3 // Status Flag 0
|
||||
#define gprESP 4 // Don't use?
|
||||
#define gprT4 5 // Temp?
|
||||
#define gprT5 6 // Temp?
|
||||
#define gprR 7 // VI Reg Offset
|
||||
#define gprST 3 // Status Sticky Flag
|
||||
#define gprF1 5 // Status Flag 1
|
||||
#define gprF2 6 // Status Flag 2
|
||||
#define gprF3 7 // Status Flag 3
|
||||
|
||||
// Function Params
|
||||
#define mP microVU* mVU, int recPass
|
||||
|
@ -172,13 +172,15 @@ declareAllVariables
|
|||
#define mVUregsTemp mVUallocInfo.regsTemp
|
||||
#define iPC mVUallocInfo.curPC
|
||||
#define mVUsFlagHack mVUallocInfo.sFlagHack
|
||||
#define mVUinfo mVUallocInfo.info[iPC/2] // IR info for current 64bit instruction
|
||||
#define mVUstall mVUinfo.stall // Stall info for current instruction
|
||||
#define mVUup mVUinfo.uOp // Upper Instruction Info
|
||||
#define mVUlow mVUinfo.lOp // Lower Instruction Info
|
||||
#define sFLAG mVUinfo.sFlag // Status Flag info for cur instruction
|
||||
#define mFLAG mVUinfo.mFlag // Mac Flag info for cur instruction
|
||||
#define cFLAG mVUinfo.cFlag // Clip Flag info for cur instruction
|
||||
|
||||
#define mVUinfo mVUallocInfo.info[iPC / 2]
|
||||
#define mVUstall mVUinfo.stall
|
||||
#define mVUup mVUinfo.uOp
|
||||
#define mVUlow mVUinfo.lOp
|
||||
#define sFLAG mVUinfo.sFlag
|
||||
#define mFLAG mVUinfo.mFlag
|
||||
#define cFLAG mVUinfo.cFlag
|
||||
|
||||
#define mVUstartPC mVUallocInfo.startPC
|
||||
#define mVUflagInfo mVUregs.needExactMatch
|
||||
#define mVUflagHack (mVUcurProg.sFlagHack)
|
||||
|
@ -266,5 +268,6 @@ declareAllVariables
|
|||
MOV32ItoR(gprT2, xPC); \
|
||||
if (isEndPC) { CALLFunc((uptr)mVUprintPC2); } \
|
||||
else { CALLFunc((uptr)mVUprintPC1); } \
|
||||
MOV32ItoR(gprR, Roffset); \
|
||||
} \
|
||||
}
|
||||
|
|
|
@ -292,6 +292,7 @@ microVUt(void) mVUrestoreRegs(mV) {
|
|||
SSE_MOVAPS_M128_to_XMM(xmmPQ, (uptr)&mVU->xmmPQb[0]);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmMax, (uptr)mVU_maxvals);
|
||||
SSE_MOVAPS_M128_to_XMM(xmmMin, (uptr)mVU_minvals);
|
||||
MOV32ItoR(gprR, Roffset); // Restore gprR
|
||||
}
|
||||
|
||||
// Reads entire microProgram and finds out if Status Flag is Used
|
||||
|
|
|
@ -28,15 +28,21 @@
|
|||
|
||||
// Note: If modXYZW is true, then it adjusts XYZW for Single Scalar operations
|
||||
microVUt(void) mVUupdateFlags(mV, int reg, int regT1, int regT2, int xyzw, bool modXYZW) {
|
||||
int /*sReg = gprT3,*/ mReg = gprT1;
|
||||
int sReg, mReg = gprT1;
|
||||
static u8 *pjmp, *pjmp2;
|
||||
static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
|
||||
|
||||
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
|
||||
if (mVUsFlagHack) { sFLAG.doSticky = 0; sFLAG.doFlag = 0; }
|
||||
if (!mVUup.doFlags || (!sFLAG.doSticky && !sFLAG.doFlag && !mFLAG.doFlag)) { return; }
|
||||
if (mVUsFlagHack) { sFLAG.doFlag = 0; }
|
||||
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
|
||||
if (!mFLAG.doFlag || (_XYZW_SS && modXYZW)) { regT1 = reg; }
|
||||
else { SSE2_PSHUFD_XMM_to_XMM(regT1, reg, 0x1B); } // Flip wzyx to xyzw
|
||||
if (sFLAG.doFlag) {
|
||||
getFlagReg(sReg, sFLAG.write); // Set sReg to valid GPR by Cur Flag Instance
|
||||
mVUallocSFLAGa(sReg, sFLAG.lastWrite); // Get Prev Status Flag
|
||||
AND32ItoR(sReg, 0xff0); // Keep Sticky and D/I flags
|
||||
}
|
||||
|
||||
//-------------------------Check for Signed flags------------------------------
|
||||
|
||||
// The following code makes sure the Signed Bit isn't set with Negative Zero
|
||||
|
@ -48,28 +54,25 @@ microVUt(void) mVUupdateFlags(mV, int reg, int regT1, int regT2, int xyzw, bool
|
|||
SSE_MOVMSKPS_XMM_to_R32(mReg, regT2); // Move the sign bits of the t1reg
|
||||
|
||||
AND32ItoR(mReg, AND_XYZW); // Grab "Is Signed" bits from the previous calculation
|
||||
if (sFLAG.doSticky||sFLAG.doFlag) pjmp = JZ8(0); // Skip if none are
|
||||
if (sFLAG.doFlag) pjmp = JZ8(0); // Skip if none are
|
||||
if (mFLAG.doFlag) SHL32ItoR(mReg, 4 + ADD_XYZW);
|
||||
if (sFLAG.doSticky) OR32ItoR (gprST, 0x82); // SS, S flags
|
||||
else if (sFLAG.doFlag) OR32ItoR (gprST, 0x02); // S flag
|
||||
if ((sFLAG.doSticky||sFLAG.doFlag) && _XYZW_SS) pjmp2 = JMP8(0); // If negative and not Zero, we can skip the Zero Flag checking
|
||||
if (sFLAG.doSticky||sFLAG.doFlag) x86SetJ8(pjmp);
|
||||
if (sFLAG.doFlag) OR32ItoR(sReg, 0x82); // SS, S flags
|
||||
if (sFLAG.doFlag && _XYZW_SS) pjmp2 = JMP8(0); // If negative and not Zero, we can skip the Zero Flag checking
|
||||
if (sFLAG.doFlag) x86SetJ8(pjmp);
|
||||
|
||||
//-------------------------Check for Zero flags------------------------------
|
||||
|
||||
AND32ItoR(gprT2, AND_XYZW); // Grab "Is Zero" bits from the previous calculation
|
||||
if (sFLAG.doSticky||sFLAG.doFlag) pjmp = JZ8(0); // Skip if none are
|
||||
if (sFLAG.doFlag) pjmp = JZ8(0); // Skip if none are
|
||||
if (mFLAG.doFlag) { SHIFT_XYZW(gprT2); OR32RtoR(mReg, gprT2); }
|
||||
if (sFLAG.doSticky) { OR32ItoR(gprST, 0x41); } // ZS, Z flags
|
||||
else if (sFLAG.doFlag) { OR32ItoR(gprST, 0x01); } // Z flag
|
||||
if (sFLAG.doSticky||sFLAG.doFlag) x86SetJ8(pjmp);
|
||||
if (sFLAG.doFlag) { OR32ItoR(sReg, 0x41); } // ZS, Z flags
|
||||
if (sFLAG.doFlag) x86SetJ8(pjmp);
|
||||
|
||||
//-------------------------Write back flags------------------------------
|
||||
|
||||
if ((sFLAG.doSticky||sFLAG.doFlag) && _XYZW_SS) x86SetJ8(pjmp2); // If we skipped the Zero Flag Checking, return here
|
||||
if (sFLAG.doFlag && _XYZW_SS) x86SetJ8(pjmp2); // If we skipped the Zero Flag Checking, return here
|
||||
|
||||
if (mFLAG.doFlag) mVUallocMFLAGb(mVU, mReg, mFLAG.write); // Set Mac Flag
|
||||
if (sFLAG.doFlag) mVUallocSFLAGb(mVU, gprST, mFLAG.write); // Set Status Flag
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -435,9 +438,9 @@ microVUt(void) mVUupdateFlags(mV, int reg, int regT1, int regT2, int xyzw, bool
|
|||
}
|
||||
|
||||
// FMAC27~29 - MAX/MINI FMAC Opcodes
|
||||
#define mVU_FMAC27(operation, OPname) { mVU_FMAC1 (operation, OPname); pass1 { mVUup.doFlags = 0; } }
|
||||
#define mVU_FMAC28(operation, OPname) { mVU_FMAC6 (operation, OPname); pass1 { mVUup.doFlags = 0; } }
|
||||
#define mVU_FMAC29(operation, OPname) { mVU_FMAC3 (operation, OPname); pass1 { mVUup.doFlags = 0; } }
|
||||
#define mVU_FMAC27(operation, OPname) { mVU_FMAC1 (operation, OPname); pass1 { sFLAG.doFlag = 0; } }
|
||||
#define mVU_FMAC28(operation, OPname) { mVU_FMAC6 (operation, OPname); pass1 { sFLAG.doFlag = 0; } }
|
||||
#define mVU_FMAC29(operation, OPname) { mVU_FMAC3 (operation, OPname); pass1 { sFLAG.doFlag = 0; } }
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Micro VU Micromode Upper instructions
|
||||
|
|
Loading…
Reference in New Issue