- Fixed up the T/D Bit handling properly this time (or at least much better).
- Moved the interrupt outside of the recompiled code.

VU Interpreter:
-Fixed the T/D Bit handling when the interrupt wasn't enabled.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5587 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction@gmail.com 2013-03-11 21:54:05 +00:00
parent c81eab917e
commit e3fead7f09
9 changed files with 112 additions and 27 deletions

View File

@ -553,7 +553,7 @@ extern void setDmacStat(u32 num);
extern tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write);
extern tDMA_TAG *dmaGetAddr(u32 addr, bool write);
extern void __fastcall hwIntcIrq(int n);
extern void hwIntcIrq(int n);
extern void hwDmacIrq(int n);
extern void FireMFIFOEmpty();

View File

@ -129,8 +129,7 @@ __fi uint dmacInterrupt()
return 0x800;
}
//Fastcall required for VU recompilers. Test Over the Hedge when changing.
void __fastcall hwIntcIrq(int n)
void hwIntcIrq(int n)
{
psHu32(INTC_STAT) |= 1<<n;
if(psHu32(INTC_MASK) & (1<<n))cpuTestINTCInts();

View File

@ -82,7 +82,7 @@ struct REG_VI {
//#define VUFLAG_BREAKONMFLAG 0x00000001
#define VUFLAG_MFLAGSET 0x00000002
#define VUFLAG_INTCINTERRUPT 0x00000004
struct fdivPipe {
int enable;
REG_VI reg;

View File

@ -61,15 +61,17 @@ static void _vu0Exec(VURegs* VU)
if (VU0.VI[REG_FBRST].UL & 0x4) {
VU0.VI[REG_VPU_STAT].UL|= 0x2;
hwIntcIrq(INTC_VU0);
VU->ebit = 1;
}
VU->ebit = 1;
}
if (ptr[1] & 0x08000000) { /* T flag */
if (VU0.VI[REG_FBRST].UL & 0x8) {
VU0.VI[REG_VPU_STAT].UL|= 0x4;
hwIntcIrq(INTC_VU0);
VU->ebit = 1;
}
VU->ebit = 1;
}
VU->code = ptr[1];

View File

@ -59,15 +59,17 @@ static void _vu1Exec(VURegs* VU)
if (VU0.VI[REG_FBRST].UL & 0x400) {
VU0.VI[REG_VPU_STAT].UL|= 0x200;
hwIntcIrq(INTC_VU1);
VU->ebit = 1;
}
VU->ebit = 1;
}
if (ptr[1] & 0x08000000) { /* T flag */
if (VU0.VI[REG_FBRST].UL & 0x800) {
VU0.VI[REG_VPU_STAT].UL|= 0x400;
hwIntcIrq(INTC_VU1);
VU->ebit = 1;
}
VU->ebit = 1;
}
//VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F);

View File

@ -327,6 +327,12 @@ void recMicroVU0::Execute(u32 cycles) {
// woody hangs if too high on sVU (untested on mVU)
// Edit: Need to test this again, if anyone ever has a "Woody" game :p
((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, cycles);
if(microVU0.regs().flags & 0x4)
{
microVU0.regs().flags &= ~0x4;
hwIntcIrq(6);
}
}
void recMicroVU1::Execute(u32 cycles) {
pxAssert(m_Reserved); // please allocate me first! :|
@ -335,6 +341,12 @@ void recMicroVU1::Execute(u32 cycles) {
if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
}
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, cycles);
if(microVU1.regs().flags & 0x4)
{
microVU1.regs().flags &= ~0x4;
hwIntcIrq(7);
}
}
void recMicroVU0::Clear(u32 addr, u32 size) {

View File

@ -28,6 +28,62 @@ __fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isE
void mVU0clearlpStateJIT() { if (!microVU0.prog.cleared) memzero(microVU0.prog.lpState); }
void mVU1clearlpStateJIT() { if (!microVU1.prog.cleared) memzero(microVU1.prog.lpState); }
void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) {
int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit);
int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit);
int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit);
int qInst = 0;
int pInst = 0;
mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P
if (isEbit) {
memzero(mVUinfo);
memzero(mVUregsTemp);
mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
mVUcycles -= 100;
qInst = mVU.q;
pInst = mVU.p;
if (mVUinfo.doDivFlag) {
sFLAG.doFlag = 1;
sFLAG.write = fStatus;
mVUdivSet(mVU);
}
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
if (doEarlyExit(mVU)) {
if (!isVU1) xCALL(mVU0clearlpStateJIT);
else xCALL(mVU1clearlpStateJIT);
}
}
// Save P/Q Regs
if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); }
xMOVSS(ptr32[&mVU.regs().VI[REG_Q].UL], xmmPQ);
if (isVU1) {
xPSHUF.D(xmmPQ, xmmPQ, pInst ? 3 : 2);
xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ);
}
// Save Flag Instances
xMOV(ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus));
mVUallocMFLAGa(mVU, gprT1, fMac);
mVUallocCFLAGa(mVU, gprT2, fClip);
xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1);
xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2);
if (isEbit || isVU1) { // Clear 'is busy' Flags
if (!mVU.index || !THREAD_VU1) {
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
}
}
if (isEbit != 2) { // Save PC, and Jump to Exit Point
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xJMP(mVU.exitFunct);
}
}
void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit);

View File

@ -480,35 +480,37 @@ void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microF
void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
{
incPC(2);
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
xForwardJump32 eJMP(Jcc_Zero);
xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2));
xMOV( gprT2, (isVU1 ? 7 : 6));
xCALL( hwIntcIrq );
mVUendProgram(mVU, mFC, 2);
xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xJMP(mVU.exitFunct);
xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT);
mVUDTendProgram(mVU, mFC, 1);
eJMP.SetTarget();
incPC(-2);
}
void mVUDoTBit(microVU& mVU, microFlagCycles* mFC)
{
incPC(2);
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
xForwardJump32 eJMP(Jcc_Zero);
xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4));
xMOV( gprT2, (isVU1 ? 7 : 6));
xCALL( hwIntcIrq );
mVUendProgram(mVU, mFC, 2);
xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xJMP(mVU.exitFunct);
xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT);
mVUDTendProgram(mVU, mFC, 1);
eJMP.SetTarget();
incPC(-2);
}
void mVUSaveFlags(microVU& mVU,microFlagCycles &mFC, microFlagCycles &mFCBackup)
{
memcpy_fast(&mFCBackup, &mFC, sizeof(microFlagCycles));
mVUsetFlags(mVU, mFCBackup); // Sets Up Flag instances
}
void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) {
microFlagCycles mFC;
microFlagCycles mFCBackup;
u8* thisPtr = x86Ptr;
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU.microMemSize / 8);
@ -525,9 +527,9 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) {
mVUopU(mVU, 0);
mVUcheckBadOp(mVU);
if (curI & _Ebit_) { eBitPass1(mVU, branch); }
if (curI & _Dbit_) { mVUup.dBit = 1; }
if (curI & _Dbit_) { mVUup.dBit = 1; mVUsetFlagInfo(mVU); mVUSaveFlags(mVU, mFC, mFCBackup); }
if (curI & _Mbit_) { mVUup.mBit = 1; }
if (curI & _Tbit_) { mVUup.tBit = 1; branch = 2; }
if (curI & _Tbit_) { mVUup.tBit = 1; mVUsetFlagInfo(mVU); mVUSaveFlags(mVU, mFC, mFCBackup); }
if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; }
else { incPC(-1); mVUopL(mVU, 0); incPC(1); }
mVUsetCycles(mVU);
@ -561,7 +563,10 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) {
if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; }
if (mVUup.mBit) { xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET); }
mVUexecuteInstruction(mVU);
incPC(-1);
if(mVUup.tBit) {mVUDoTBit(mVU, &mFC); }
else if(mVUup.dBit) { mVUDoDBit(mVU, &mFC);}
incPC(1);
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }
else if (!mVUinfo.isBdelay) { incPC(1); }
@ -583,10 +588,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState) {
}
}
if ((x == endCount) && (x!=1)) { Console.Error("microVU%d: Possible infinite compiling loop!", mVU.index); }
incPC(-1);
if(mVUup.tBit) mVUDoTBit(mVU, &mFC);
if(mVUup.dBit) mVUDoDBit(mVU, &mFC);
incPC(1);
// E-bit End
mVUsetupRange(mVU, xPC-8, 0);
mVUendProgram(mVU, &mFC, 1);

View File

@ -259,6 +259,18 @@ public:
}
}
void TDwritebackAll(bool clearState = 0) {
for(int i = 0; i < xmmTotal; i++) {
microMapXMM& mapX = xmmMap[xmm(i).Id];
if ((mapX.VFreg > 0) && mapX.xyzw) { // Reg was modified and not Temp or vf0
if (mapX.VFreg == 33) xMOVSS(ptr32[&getVI(REG_I)], xmm(i));
elif (mapX.VFreg == 32) mVUsaveReg(xmm(i), ptr[&regs().ACC], mapX.xyzw, 1);
else mVUsaveReg(xmm(i), ptr[&getVF(mapX.VFreg)], mapX.xyzw, 1);
}
}
}
void clearReg(const xmm& reg) { clearReg(reg.Id); }
void clearReg(int regId) {
microMapXMM& clear = xmmMap[regId];