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); } \ +}