From 6775b8a5cc047ac9267d119780273b92d632e9a9 Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Fri, 10 Apr 2009 19:45:27 +0000 Subject: [PATCH] microVU: - added microVU_Execution.inl - dispatcher stuff is now recompiled with pcsx2's emitter instead of using inline asm, its cleaner than inline asm and its more portable since the asm won't have to be ported to GCC. - lots of first-pass implementation for lower opcodes - implemented documented branch behavior (first pass stuff only) Note: theres some undocumented stuff branches do according to Nneeve's tests, but i won't implement those for now since 99% of games shouldn't need it, and according to the tests, the behavior seems kind-of random/erratic. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@948 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/Pcsx2Config.h | 3 +- pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 4 + pcsx2/x86/iVU0micro.cpp | 2 + pcsx2/x86/iVU1micro.cpp | 2 + pcsx2/x86/ix86/ix86_cpudetect.cpp | 1 + pcsx2/x86/microVU.cpp | 101 ++------------------- pcsx2/x86/microVU.h | 29 +++--- pcsx2/x86/microVU_Alloc.inl | 18 ++-- pcsx2/x86/microVU_Analyze.inl | 57 +++++++++++- pcsx2/x86/microVU_Compile.inl | 14 +-- pcsx2/x86/microVU_Lower.inl | 49 +++++++--- pcsx2/x86/microVU_Misc.h | 31 +++++-- 12 files changed, 154 insertions(+), 157 deletions(-) diff --git a/common/include/Pcsx2Config.h b/common/include/Pcsx2Config.h index d99f47debe..2da21f9f11 100644 --- a/common/include/Pcsx2Config.h +++ b/common/include/Pcsx2Config.h @@ -44,7 +44,8 @@ extern SessionOverrideFlags g_Session; ////////////////////////////////////////////////////////////////////////// // Pcsx2 User Configuration Options! -//#define PCSX2_MICROVU // Use Micro VU recs instead of Zero VU Recs +//#define PCSX2_MICROVU // Use Micro VU recs instead of Zero VU Recs +//#define PCSX2_MICROVU_ // Fully enable Micro VU recs (temporary option for now) #define PCSX2_GSMULTITHREAD 1 // uses multi-threaded gs #define PCSX2_EEREC 0x10 #define PCSX2_VU0REC 0x20 diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index b013011d39..ba2df10aca 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2506,6 +2506,10 @@ RelativePath="..\..\x86\microVU_Compile.inl" > + + diff --git a/pcsx2/x86/iVU0micro.cpp b/pcsx2/x86/iVU0micro.cpp index 2dfaac7669..55af7a5c54 100644 --- a/pcsx2/x86/iVU0micro.cpp +++ b/pcsx2/x86/iVU0micro.cpp @@ -83,8 +83,10 @@ namespace VU0micro if((VU0.VI[REG_VPU_STAT].UL & 1) == 0) return; FreezeXMMRegs(1); + FreezeMMXRegs(1); runVUrec(VU0.VI[REG_TPC].UL & 0xfff, 0xffffffff, 0); FreezeXMMRegs(0); + FreezeMMXRegs(0); } } diff --git a/pcsx2/x86/iVU1micro.cpp b/pcsx2/x86/iVU1micro.cpp index 87f3099d7b..7debdcfa8e 100644 --- a/pcsx2/x86/iVU1micro.cpp +++ b/pcsx2/x86/iVU1micro.cpp @@ -142,8 +142,10 @@ namespace VU1micro assert( (VU1.VI[REG_TPC].UL&7) == 0 ); FreezeXMMRegs(1); + FreezeMMXRegs(0); runVUrec(VU1.VI[REG_TPC].UL & 0x3fff, 0xffffffff, 1); FreezeXMMRegs(0); + FreezeMMXRegs(0); } } #endif diff --git a/pcsx2/x86/ix86/ix86_cpudetect.cpp b/pcsx2/x86/ix86/ix86_cpudetect.cpp index 7e3323e4a7..b1fc04a96e 100644 --- a/pcsx2/x86/ix86/ix86_cpudetect.cpp +++ b/pcsx2/x86/ix86/ix86_cpudetect.cpp @@ -398,6 +398,7 @@ void cpudetectInit() cpudetectSSE3(recSSE); HostSys::Munmap( recSSE, 0x1000 ); } + else { Console::Error("Error: Failed to allocate memory for SSE3 State detection."); } ////////////////////////////////////// // Core Counting! diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 0e537472e6..d2aef9b3bd 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -64,7 +64,12 @@ microVUt(void) mVUreset() { // Dynarec Cache mVU->cache = SysMmapEx(mVU->cacheAddr, mVU->cacheSize, 0, (vuIndex ? "Micro VU1" : "Micro VU0")); if ( mVU->cache == NULL ) throw Exception::OutOfMemory(fmt_string( "microVU Error: Failed to allocate recompiler memory! (addr: 0x%x)", params (u32)mVU->cache)); - + mVU->ptr = mVU->cache; + + // Setup Entrance/Exit Points + mVUdispatcherA(); + mVUdispatcherB(); + // Other Variables memset(&mVU->prog, 0, sizeof(mVU->prog)); mVU->prog.finished = 1; @@ -99,33 +104,6 @@ microVUt(void) mVUclear(u32 addr, u32 size) { // that its probably not worth it... } -// Executes for number of cycles -microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) { -/* - Pseudocode: (ToDo: implement # of cycles) - 1) Search for existing program - 2) If program not found, goto 5 - 3) Search for recompiled block - 4) If recompiled block found, goto 6 - 5) Recompile as much blocks as possible - 6) Return start execution address of block -*/ - microVU* mVU = mVUx; - if ( mVUsearchProg(mVU) ) { // Found Program - //microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState); - //if (block) return block->x86ptrStart; // Found Block - } - // Recompile code - return NULL; -} - -void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { - return mVUexecute<0>(startPC, cycles); -} -void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { - return mVUexecute<1>(startPC, cycles); -} - //------------------------------------------------------------------ // Micro VU - Private Functions //------------------------------------------------------------------ @@ -206,73 +184,6 @@ __forceinline void mVUinvalidateBlock(microVU* mVU, u32 addr, u32 size) { } } -//------------------------------------------------------------------ -// Dispatcher Functions -//------------------------------------------------------------------ - -#ifdef _MSC_VER -// Runs VU0 for number of cycles -__declspec(naked) void __fastcall startVU0(u32 startPC, u32 cycles) { - __asm { - // __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left. - call mVUexecuteVU0 - - /*backup cpu state*/ - push ebx; - push ebp; - push esi; - push edi; - - ldmxcsr g_sseVUMXCSR - /* Should set xmmZ? */ - jmp eax - } -} - -// Runs VU1 for number of cycles -__declspec(naked) void __fastcall startVU1(u32 startPC, u32 cycles) { - __asm { - - call mVUexecuteVU1 - - /*backup cpu state*/ - push ebx; - push ebp; - push esi; - push edi; - - ldmxcsr g_sseVUMXCSR - - jmp eax - } -} - -// Exit point -__declspec(naked) void __fastcall endVU0(u32 startPC, u32 cycles) { - __asm { - - //call mVUcleanUpVU0 - - /*restore cpu state*/ - pop edi; - pop esi; - pop ebp; - pop ebx; - - ldmxcsr g_sseMXCSR - emms - - ret - } -} -#else -extern "C" { - extern void __fastcall startVU0(u32 startPC, u32 cycles); - extern void __fastcall startVU1(u32 startPC, u32 cycles); - extern void __fastcall endVU0(u32 startPC, u32 cycles); -} -#endif - //------------------------------------------------------------------ // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 049520d255..41412f70bf 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -125,17 +125,7 @@ struct microVU { u32 iReg; // iReg (only used in recompilation, not execution) u32 clipFlag[4]; // 4 instances of clip flag (used in execution) u32 divFlag; // 1 instance of I/D flags - -/* - uptr x86eax; // Accumulator register. Used in arithmetic operations. - uptr x86ecx; // Counter register. Used in shift/rotate instructions. - uptr x86edx; // Data register. Used in arithmetic operations and I/O operations. - uptr x86ebx; // Base register. Used as a pointer to data (located in DS in segmented mode). - uptr x86esp; // Stack Pointer register. Pointer to the top of the stack. - uptr x86ebp; // Stack Base Pointer register. Used to point to the base of the stack. - uptr x86esi; // Source register. Used as a pointer to a source in stream operations. - uptr x86edi; // Destination register. Used as a pointer to a destination in stream operations. -*/ + u32 VIbackup[2]; // Holds a backup of a VI reg if modified before a branch }; // microVU rec structs @@ -146,14 +136,24 @@ extern PCSX2_ALIGNED16(microVU microVU1); extern void (*mVU_UPPER_OPCODE[64])( VURegs* VU, s32 info ); extern void (*mVU_LOWER_OPCODE[128])( VURegs* VU, s32 info ); +// Main Functions +microVUt(void) mVUinit(VURegs*); +microVUt(void) mVUreset(); +microVUt(void) mVUclose(); +microVUt(void) mVUclear(u32, u32); + +// Private Functions __forceinline void mVUclearProg(microVU* mVU, int progIndex); __forceinline int mVUfindLeastUsedProg(microVU* mVU); __forceinline int mVUsearchProg(microVU* mVU); __forceinline void mVUcacheProg(microVU* mVU, int progIndex); +void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles); +void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles); -#ifdef __LINUX__ -microVUt(void) mVUreset(); -microVUt(void) mVUclose(); +#ifndef __LINUX__ +typedef void (__fastcall *mVUrecCall)(u32, u32); +#else +typedef void (*mVUrecCall)(u32, u32) __attribute__((__fastcall)); // Not sure if this is correct syntax (should be close xD) #endif // Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files) @@ -162,3 +162,4 @@ microVUt(void) mVUclose(); #include "microVU_Alloc.inl" #include "microVU_Tables.inl" #include "microVU_Compile.inl" +#include "microVU_Execute.inl" diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index 3316d7360c..dee76e8f92 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -708,19 +708,7 @@ microVUt(void) mVUallocCFLAGb(int reg, int fInstance) { microVU* mVU = mVUx; MOV32RtoM(mVU->clipFlag[fInstance], reg); } -/* -microVUt(void) mVUallocDFLAGa(int reg) { - microVU* mVU = mVUx; - //if (!mVUdivFlag) { MOV32MtoR(reg, (uptr)&mVU->divFlag[readQ]); AND32ItoR(reg, 0xc00); } - //else if (mVUdivFlag & 1) { XOR32RtoR(reg, reg); } - //else { MOV32ItoR(reg, (u32)((mVUdivFlag << 9) & 0xc00)); } -} -microVUt(void) mVUallocDFLAGb(int reg) { - microVU* mVU = mVUx; - //MOV32RtoM((uptr)&mVU->divFlag[writeQ], reg); -} -*/ //------------------------------------------------------------------ // VI Reg Allocators //------------------------------------------------------------------ @@ -734,6 +722,12 @@ microVUt(void) mVUallocVIa(int GPRreg, int _reg_) { microVUt(void) mVUallocVIb(int GPRreg, int _reg_) { microVU* mVU = mVUx; + if (backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch) + MOV32RtoM((uptr)&mVU->VIbackup[1], GPRreg); + mVUallocVIa(GPRreg, _reg_); + MOV32RtoM((uptr)&mVU->VIbackup[0], GPRreg); + MOV32MtoR(GPRreg, (uptr)&mVU->VIbackup[1]); + } if (_reg_ == 0) { return; } else if (_reg_ < 9) { MOVD32RtoMMX(mmVI(_reg_), GPRreg); } else { MOV16RtoM((uptr)&mVU->regs->VI[_reg_].UL, GPRreg); } diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index dd5918cdf0..6768153aee 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -143,6 +143,32 @@ microVUt(void) mVUanalyzeEFU2(int Fs, u8 xCycles) { analyzePreg(xCycles); } +//------------------------------------------------------------------ +// LQx - LQ/LQD/LQI Opcodes +//------------------------------------------------------------------ + +#define analyzeVIreg1(reg) { if (reg) { mVUstall = aMax(mVUstall, mVUregs.VI[reg]); } } +#define analyzeVIreg2(reg, aCycles) { if (reg) { mVUregsTemp.VIreg = reg; mVUregsTemp.VI = aCycles; mVUinfo |= _writesVI; mVU->VIbackup[0] = reg; } } + +microVUt(void) mVUanalyzeLQ(int Ft, int Is, bool writeIs) { + microVU* mVU = mVUx; + analyzeVIreg1(Is); + analyzeReg2(Ft); + if (!Ft) { mVUinfo |= (writeIs && Is) ? _noWriteVF : _isNOP; } + if (writeIs) { analyzeVIreg2(Is, 1); } +} + +//------------------------------------------------------------------ +// SQx - SQ/SQD/SQI Opcodes +//------------------------------------------------------------------ + +microVUt(void) mVUanalyzeSQ(int Fs, int It, bool writeIt) { + microVU* mVU = mVUx; + analyzeReg1(Fs); + analyzeVIreg1(It); + if (writeIt) { analyzeVIreg2(It, 1); } +} + //------------------------------------------------------------------ // R*** - R Reg Opcodes //------------------------------------------------------------------ @@ -166,9 +192,6 @@ microVUt(void) mVUanalyzeR2(int Ft, bool canBeNOP) { // Sflag - Status Flag Opcodes //------------------------------------------------------------------ -#define analyzeVIreg1(reg) { if (reg) { mVUstall = aMax(mVUstall, mVUregs.VI[reg]); } } -#define analyzeVIreg2(reg, aCycles) { if (reg) { mVUregsTemp.VIreg = reg; mVUregsTemp.VI = aCycles; } } - microVUt(void) mVUanalyzeSflag(int It) { microVU* mVU = mVUx; if (!It) { mVUinfo |= _isNOP; return; } @@ -190,4 +213,32 @@ microVUt(void) mVUanalyzeXGkick(int Fs, int xCycles) { analyzeXGkick2(xCycles); } +//------------------------------------------------------------------ +// Branches - Branch Opcodes +//------------------------------------------------------------------ + +#define analyzeBranchVI(reg, infoVal) { \ + if (reg && (mVUcycles > 1)) { /* Ensures branch is not first opcode in block */ \ + incPC(-2); \ + if (writesVI && (reg == mVU->VIbackup[0])) { /* If prev Op modified VI reg */ \ + mVUinfo |= _backupVI; \ + incPC(2); \ + mVUinfo |= infoVal; \ + } \ + else { incPC(2); } \ + } \ +} + +microVUt(void) mVUanalyzeBranch1(int Is) { + microVU* mVU = mVUx; + if (mVUregs.VI[Is]) { analyzeVIreg1(Is); } + else { analyzeBranchVI(Is, _memReadIs); } +} + +microVUt(void) mVUanalyzeBranch2(int Is, int It) { + microVU* mVU = mVUx; + if (mVUregs.VI[Is] || mVUregs.VI[It]) { analyzeVIreg1(Is); analyzeVIreg1(It); } + else { analyzeBranchVI(Is, _memReadIs); analyzeBranchVI(It, _memReadIt);} +} + #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 554cf2612b..c9a8217641 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -29,11 +29,7 @@ } \ } -#define curI mVUcurProg.data[iPC] -#define setCode() { mVU->code = curI; } -#define startLoop() { mVUdebugStuff1(); mVUstall = 0; memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); } -#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); } -#define incCycles(x) { mVUincCycles(x); } +#define startLoop() { mVUdebug1(); mVUstall = 0; memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); } #define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); } microVUt(void) mVUincCycles(int x) { @@ -115,10 +111,10 @@ microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, if (isEOB) { x = 0; } else if (isBranch) { mVUopU(); incPC(2); } - mVUopU(); - if (isNop) { if (curI & _Ibit_) { incPC(1); mVU->iReg = curI; } else { incPC(1); } } - else { incPC(1); mVUopL(); } - + if (isNop) { mVUopU(); if (curI & _Ibit_) { incPC(1); mVU->iReg = curI; } else { incPC(1); } } + else if (!swapOps) { mVUopU(); incPC(1); mVUopL(); } + else { incPC(1); mVUopL(); incPC(-1); mVUopU(); incPC(1); } + if (!isBdelay) { incPC(1); } else { incPC(-2); // Go back to Branch Opcode diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 5ac22e06e7..18e73ebde7 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -799,7 +799,7 @@ microVUf(void) mVU_ISWR() { microVUf(void) mVU_LQ() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } + if (!recPass) { mVUanalyzeLQ(_Ft_, _Fs_, 0); } else { if (!_Fs_) { mVUloadReg(xmmFt, (uptr)mVU->regs->Mem + getVUmem(_Imm11_), _X_Y_Z_W); @@ -817,9 +817,9 @@ microVUf(void) mVU_LQ() { microVUf(void) mVU_LQD() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeLQ(_Ft_, _Fs_, 1); } else { - if (!_Fs_ && _Ft_ && !noWriteVF) { + if (!_Fs_ && !noWriteVF) { mVUloadReg(xmmFt, (uptr)mVU->regs->Mem, _X_Y_Z_W); mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); } @@ -827,7 +827,7 @@ microVUf(void) mVU_LQD() { mVUallocVIa(gprT1, _Fs_); SUB16ItoR(gprT1, 1); mVUallocVIb(gprT1, _Fs_); // ToDo: Backup to memory check. - if (_Ft_ && !noWriteVF) { + if (!noWriteVF) { mVUaddrFix(gprT1); mVUloadReg2(xmmFt, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); @@ -838,15 +838,15 @@ microVUf(void) mVU_LQD() { microVUf(void) mVU_LQI() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeLQ(_Ft_, _Fs_, 1); } else { - if (!_Fs_ && _Ft_ && !noWriteVF) { + if (!_Fs_ && !noWriteVF) { mVUloadReg(xmmFt, (uptr)mVU->regs->Mem, _X_Y_Z_W); mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); } else { mVUallocVIa((_Ft_) ? gprT1 : gprT2, _Fs_); - if (_Ft_ && !noWriteVF) { + if (!noWriteVF) { MOV32RtoR(gprT2, gprT1); mVUaddrFix(gprT1); mVUloadReg2(xmmFt, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); @@ -864,7 +864,7 @@ microVUf(void) mVU_LQI() { microVUf(void) mVU_SQ() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeSQ(_Fs_, _Ft_, 0); } else { if (!_Ft_) { getReg7(xmmFs, _Fs_); @@ -882,7 +882,7 @@ microVUf(void) mVU_SQ() { microVUf(void) mVU_SQD() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeSQ(_Fs_, _Ft_, 1); } else { if (!_Ft_) { getReg7(xmmFs, _Fs_); @@ -901,7 +901,7 @@ microVUf(void) mVU_SQD() { microVUf(void) mVU_SQI() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeSQ(_Fs_, _Ft_, 1); } else { if (!_Ft_) { getReg7(xmmFs, _Fs_); @@ -1042,8 +1042,10 @@ microVUf(void) mVU_XGKICK() { if (!recPass) { mVUanalyzeXGkick(_Fs_, 4); } else { mVUallocVIa(gprT2, _Fs_); // gprT2 = ECX for __fastcall + PUSH32R(gprR); // gprR = EDX is volatile so backup if (!vuIndex) CALLFunc((uptr)mVU_XGKICK0); else CALLFunc((uptr)mVU_XGKICK1); + POP32R(gprR); // Restore } } @@ -1058,7 +1060,8 @@ microVUf(void) mVU_B() { microVUf(void) mVU_BAL() { microVU* mVU = mVUx; mVUbranch = 1; - if (recPass) { + if (!recPass) { analyzeVIreg2(_Ft_, 1); } + else { MOV32ItoR(gprT1, (xPC + (2 * 8)) & 0xffff); mVUallocVIb(gprT1, _Ft_); } @@ -1066,34 +1069,50 @@ microVUf(void) mVU_BAL() { microVUf(void) mVU_IBEQ() { microVU* mVU = mVUx; mVUbranch = 2; + if (!recPass) { mVUanalyzeBranch2(_Fs_, _Ft_); } + else {} } microVUf(void) mVU_IBGEZ() { microVU* mVU = mVUx; mVUbranch = 2; + if (!recPass) { mVUanalyzeBranch1(_Fs_); } + else {} } microVUf(void) mVU_IBGTZ() { microVU* mVU = mVUx; mVUbranch = 2; -} -microVUf(void) mVU_IBLTZ() { - microVU* mVU = mVUx; - mVUbranch = 2; + if (!recPass) { mVUanalyzeBranch1(_Fs_); } + else {} } microVUf(void) mVU_IBLEZ() { microVU* mVU = mVUx; mVUbranch = 2; + if (!recPass) { mVUanalyzeBranch1(_Fs_); } + else {} +} +microVUf(void) mVU_IBLTZ() { + microVU* mVU = mVUx; + mVUbranch = 2; + if (!recPass) { mVUanalyzeBranch1(_Fs_); } + else {} } microVUf(void) mVU_IBNE() { microVU* mVU = mVUx; mVUbranch = 2; + if (!recPass) { mVUanalyzeBranch2(_Fs_, _Ft_); } + else {} } microVUf(void) mVU_JR() { microVU* mVU = mVUx; mVUbranch = 3; + if (!recPass) { mVUanalyzeBranch1(_Fs_); } + else {} } microVUf(void) mVU_JALR() { microVU* mVU = mVUx; mVUbranch = 3; + if (!recPass) { mVUanalyzeBranch1(_Fs_); analyzeVIreg2(_Ft_, 1); } + else {} } #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index dd52f1b489..5a1267a556 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -144,14 +144,16 @@ declareAllVariables #define mVUbranch mVUallocInfo.branch #define mVUcycles mVUallocInfo.cycles #define mVUstall mVUallocInfo.maxStall -//#define mVUdivFlag mVUallocInfo.divFlag -//#define mVUdivFlagT mVUallocInfo.divFlagTimer #define mVUregs mVUallocInfo.regs #define mVUregsTemp mVUallocInfo.regsTemp #define mVUinfo mVUallocInfo.info[mVUallocInfo.curPC / 2] #define mVUstartPC mVUallocInfo.startPC #define iPC mVUallocInfo.curPC #define xPC ((iPC / 2) * 8) +#define curI mVUcurProg.data[iPC] +#define setCode() { mVU->code = curI; } +#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); } +#define incCycles(x) { mVUincCycles(x); } #define _isNOP (1<<0) // Skip Lower Instruction #define _isBranch (1<<1) // Cur Instruction is a Branch @@ -174,6 +176,11 @@ declareAllVariables #define _fvsInstance (3<<18) #define _fvcInstance (3<<20) #define _noWriteVF (1<<21) // Don't write back the result of a lower op to VF reg if upper op writes to same reg (or if VF = 0) +#define _backupVI (1<<22) // Backup VI reg to memory if modified before branch (branch uses old VI value unless opcode is ILW or ILWR) +#define _memReadIs (1<<23) // Read Is (VI reg) from memory (used by branches) +#define _memReadIt (1<<24) // Read If (VI reg) from memory (used by branches) +#define _writesVI (1<<25) // Current Instruction writes to VI +#define _swapOps (1<<26) // Runs Lower Instruction Before Upper Instruction #define isNOP (mVUinfo & (1<<0)) #define isBranch (mVUinfo & (1<<1)) @@ -196,16 +203,18 @@ declareAllVariables #define fvsInstance ((mVUinfo >> 18) & 3) #define fvcInstance ((mVUinfo >> 20) & 3) #define noWriteVF (mVUinfo & (1<<21)) - -//#define getFs (mVUinfo & (1<<13)) -//#define getFt (mVUinfo & (1<<14)) -//#define fpmInstance (((u8)((mVUinfo & (3<<10)) >> 10) - 1) & 0x3) +#define backupVI (mVUinfo & (1<<22)) +#define memReadIs (mVUinfo & (1<<23)) +#define memReadIt (mVUinfo & (1<<24)) +#define writesVI (mVUinfo & (1<<25)) +#define swapOps (mVUinfo & (1<<26)) #define isMMX(_VIreg_) (_VIreg_ >= 1 && _VIreg_ <=9) #define mmVI(_VIreg_) (_VIreg_ - 1) #ifdef mVUdebug -#define mVUdebugStuff1() { \ +#define mVUlog Console::Notice +#define mVUdebug1() { \ if (curI & _Ibit_) { SysPrintf("microVU: I-bit set!\n"); } \ if (curI & _Ebit_) { SysPrintf("microVU: E-bit set!\n"); } \ if (curI & _Mbit_) { SysPrintf("microVU: M-bit set!\n"); } \ @@ -213,5 +222,11 @@ declareAllVariables if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \ } #else -#define mVUdebugStuff1() {} +#define mVUlog 0&& +#define mVUdebug1() {} #endif + +#define mVUcachCheck(x) { \ + uptr diff = mVU->ptr - mVU->cache; \ + if (diff > x) { Console::Error("microVU Error: Program went over it's cache limit. Size = %x", params diff); } \ +}