mirror of https://github.com/PCSX2/pcsx2.git
microVU:
- 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:
parent
c81eab917e
commit
e3fead7f09
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[®s().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];
|
||||
|
|
Loading…
Reference in New Issue