From 923802f9367a3ae60cdb1b2c087e9341b7b7b8b0 Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Mon, 6 Apr 2009 07:32:10 +0000 Subject: [PATCH] microVU: more recompiler first-pass implementation stuff... git-svn-id: http://pcsx2.googlecode.com/svn/trunk@915 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/iVU0micro.cpp | 33 +++++++++++++-- pcsx2/x86/iVU1micro.cpp | 28 ++++++++++++- pcsx2/x86/microVU.cpp | 26 ++++++------ pcsx2/x86/microVU_Alloc.h | 1 + pcsx2/x86/microVU_Analyze.inl | 14 +++++++ pcsx2/x86/microVU_Compile.inl | 26 ++++-------- pcsx2/x86/microVU_Lower.inl | 78 ++++++++++++++++++++++++++++++----- pcsx2/x86/microVU_Misc.h | 24 ++++++++--- 8 files changed, 180 insertions(+), 50 deletions(-) diff --git a/pcsx2/x86/iVU0micro.cpp b/pcsx2/x86/iVU0micro.cpp index 4b70381294..2dfaac7669 100644 --- a/pcsx2/x86/iVU0micro.cpp +++ b/pcsx2/x86/iVU0micro.cpp @@ -23,11 +23,12 @@ #include "VUmicro.h" #include "iVUzerorec.h" +#ifndef PCSX2_MICROVU_ namespace VU0micro { - void recAlloc() - { - SuperVUAlloc(0); + void recAlloc() + { + SuperVUAlloc(0); } void __fastcall recClear(u32 Addr, u32 Size) @@ -62,6 +63,32 @@ namespace VU0micro FreezeXMMRegs(0); } } +#else + +extern void initVUrec(VURegs* vuRegs, const int vuIndex); +extern void closeVUrec(const int vuIndex); +extern void resetVUrec(const int vuIndex); +extern void clearVUrec(u32 addr, u32 size, const int vuIndex); +extern void runVUrec(u32 startPC, u32 cycles, const int vuIndex); + +namespace VU0micro +{ + void recAlloc() { initVUrec(&VU0, 0); } + void __fastcall recClear(u32 Addr, u32 Size) { clearVUrec(Addr, Size, 0); } + void recShutdown() { closeVUrec(0); } + static void recReset() { resetVUrec(0); x86FpuState = FPU_STATE; } + static void recStep() {} + static void recExecuteBlock() + { + if((VU0.VI[REG_VPU_STAT].UL & 1) == 0) return; + + FreezeXMMRegs(1); + runVUrec(VU0.VI[REG_TPC].UL & 0xfff, 0xffffffff, 0); + FreezeXMMRegs(0); + } + +} +#endif using namespace VU0micro; diff --git a/pcsx2/x86/iVU1micro.cpp b/pcsx2/x86/iVU1micro.cpp index 2c4cc00bb4..87f3099d7b 100644 --- a/pcsx2/x86/iVU1micro.cpp +++ b/pcsx2/x86/iVU1micro.cpp @@ -29,7 +29,7 @@ #ifdef _DEBUG extern u32 vudump; #endif - +#ifndef PCSX2_MICROVU_ namespace VU1micro { void recAlloc() @@ -121,6 +121,32 @@ namespace VU1micro FreezeXMMRegs(0); } } +#else + +extern void initVUrec(VURegs* vuRegs, const int vuIndex); +extern void closeVUrec(const int vuIndex); +extern void resetVUrec(const int vuIndex); +extern void clearVUrec(u32 addr, u32 size, const int vuIndex); +extern void runVUrec(u32 startPC, u32 cycles, const int vuIndex); + +namespace VU1micro +{ + void recAlloc() { initVUrec(&VU1, 1); } + void __fastcall recClear(u32 Addr, u32 Size) { clearVUrec(Addr, Size, 1); } + void recShutdown() { closeVUrec(1); } + static void recReset() { resetVUrec(1); x86FpuState = FPU_STATE; } + static void recStep() {} + static void recExecuteBlock() { + + if((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return; + assert( (VU1.VI[REG_TPC].UL&7) == 0 ); + + FreezeXMMRegs(1); + runVUrec(VU1.VI[REG_TPC].UL & 0x3fff, 0xffffffff, 1); + FreezeXMMRegs(0); + } +} +#endif using namespace VU1micro; diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 4613a13acb..39e9697f38 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -42,7 +42,7 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr) { mVU->index = vuIndex; mVU->microSize = (vuIndex ? 0x4000 : 0x1000); mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 8; - mVU->cacheAddr = 0xC0000000 + (vuIndex ? mVU->cacheSize : 0); + mVU->cacheAddr = (vuIndex ? 0x1e840000 : 0x0e840000); mVU->cache = NULL; mVUreset(); @@ -55,16 +55,16 @@ microVUt(void) mVUreset() { mVUclose(); // Close // Create Block Managers - for (int i; i <= mVU->prog.max; i++) { - for (u32 j; j < (mVU->progSize / 2); j++) { + for (int i = 0; i <= mVU->prog.max; i++) { + for (u32 j = 0; j < (mVU->progSize / 2); j++) { mVU->prog.prog[i].block[j] = new microBlockManager(); } } // Dynarec Cache - mVU->cache = SysMmapEx(mVU->cacheAddr, mVU->cacheSize, 0x10000000, (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->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)); + // Other Variables memset(&mVU->prog, 0, sizeof(mVU->prog)); mVU->prog.finished = 1; @@ -81,8 +81,8 @@ microVUt(void) mVUclose() { if ( mVU->cache ) { HostSys::Munmap( mVU->cache, mVU->cacheSize ); mVU->cache = NULL; } // Delete Block Managers - for (int i; i <= mVU->prog.max; i++) { - for (u32 j; j < (mVU->progSize / 2); j++) { + for (int i = 0; i <= mVU->prog.max; i++) { + for (u32 j = 0; j < (mVU->progSize / 2); j++) { if (mVU->prog.prog[i].block[j]) delete mVU->prog.prog[i].block[j]; } } @@ -277,27 +277,27 @@ extern "C" { // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ -__forceinline void initVUrec(VURegs* vuRegs, const int vuIndex) { +void initVUrec(VURegs* vuRegs, const int vuIndex) { if (!vuIndex) mVUinit<0>(vuRegs); else mVUinit<1>(vuRegs); } -__forceinline void closeVUrec(const int vuIndex) { +void closeVUrec(const int vuIndex) { if (!vuIndex) mVUclose<0>(); else mVUclose<1>(); } -__forceinline void resetVUrec(const int vuIndex) { +void resetVUrec(const int vuIndex) { if (!vuIndex) mVUreset<0>(); else mVUreset<1>(); } -__forceinline void clearVUrec(u32 addr, u32 size, const int vuIndex) { +void clearVUrec(u32 addr, u32 size, const int vuIndex) { if (!vuIndex) mVUclear<0>(addr, size); else mVUclear<1>(addr, size); } -__forceinline void runVUrec(u32 startPC, u32 cycles, const int vuIndex) { +void runVUrec(u32 startPC, u32 cycles, const int vuIndex) { if (!vuIndex) startVU0(startPC, cycles); else startVU1(startPC, cycles); } diff --git a/pcsx2/x86/microVU_Alloc.h b/pcsx2/x86/microVU_Alloc.h index c539eb1297..f039c0a980 100644 --- a/pcsx2/x86/microVU_Alloc.h +++ b/pcsx2/x86/microVU_Alloc.h @@ -54,6 +54,7 @@ struct microAllocInfo { u8 maxStall; // Helps in computing stalls (stores the max amount of cycles to stall for the current opcodes) u32 cycles; // Cycles for current block u32 curPC; // Current PC + u32 startPC; // Start PC for Cur Block u32 info[pSize]; // bit 00 = Lower Instruction is NOP // bit 01 // bit 02 diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index f35299ab28..a493da8968 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -143,4 +143,18 @@ microVUt(void) mVUanalyzeEFU2(int Fs, u8 xCycles) { analyzePreg(xCycles); } +//------------------------------------------------------------------ +// 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; } + mVUinfo |= _isSflag; + analyzeVIreg2(It, 1); +} + #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 49c517de5e..686e4a6563 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -19,18 +19,6 @@ #pragma once #ifdef PCSX2_MICROVU -#ifdef mVUdebug -#define mVUdebugStuff1() { \ - 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"); } \ - if (curI & _Dbit_) { SysPrintf("microVU: D-bit set!\n"); } \ - if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \ -} -#else -#define mVUdebugStuff1() {} -#endif - #define createBlock(blockEndPtr) { \ block.pipelineState = pipelineState; \ block.x86ptrStart = x86ptrStart; \ @@ -59,19 +47,18 @@ microVUt(void) mVUsetCycles() { microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, u8* x86ptrStart) { microVU* mVU = mVUx; microBlock block; - int branch; iPC = startPC / 4; - + // Searches for Existing Compiled Block (if found, then returns; else, compile) microBlock* pblock = mVUblock[iPC]->search(pipelineState, pState); if (block) { x86SetPtr(pblock->x86ptrEnd); return; } // First Pass setCode(); - branch = 0; - mVUbranch = 0; - mVUcycles = 1; // Skips "M" phase, and starts counting cycles at "T" stage - for (;;) { + mVUbranch = 0; + mVUstartPC = iPC; + mVUcycles = 1; // Skips "M" phase, and starts counting cycles at "T" stage + for (int branch = 0;; ) { startLoop(); mVUopU(); if (curI & _Ebit_) { branch = 1; } @@ -89,6 +76,9 @@ microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, iPC = startPC; setCode(); for (bool x = 1; x; ) { + // + // ToDo: status/mac flag stuff + // if (isEOB) { x = 0; } else if (isBranch) { mVUopU(); incPC(2); } diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 8e7859e033..a7e8438c24 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -23,6 +23,10 @@ // Micro VU Micromode Lower instructions //------------------------------------------------------------------ +//------------------------------------------------------------------ +// DIV/SQRT/RSQRT +//------------------------------------------------------------------ + #define testZero(xmmReg, xmmTemp, gprTemp) { \ SSE_XORPS_XMM_to_XMM(xmmTemp, xmmTemp); /* Clear xmmTemp (make it 0) */ \ SSE_CMPEQPS_XMM_to_XMM(xmmTemp, xmmReg); /* Set all F's if zero */ \ @@ -128,6 +132,10 @@ microVUf(void) mVU_RSQRT() { } } +//------------------------------------------------------------------ +// EATAN/EEXP/ELENG/ERCPR/ERLENG/ERSADD/ERSQRT/ESADD/ESIN/ESQRT/ESUM +//------------------------------------------------------------------ + #define EATANhelper(addr) { \ SSE_MULSS_XMM_to_XMM(xmmT1, xmmFs); \ SSE_MULSS_XMM_to_XMM(xmmT1, xmmFs); \ @@ -401,6 +409,10 @@ microVUf(void) mVU_ESUM() { } } +//------------------------------------------------------------------ +// FCAND/FCEQ/FCGET/FCOR/FCSET +//------------------------------------------------------------------ + microVUf(void) mVU_FCAND() { microVU* mVU = mVUx; if (!recPass) {} @@ -456,6 +468,10 @@ microVUf(void) mVU_FCSET() { } } +//------------------------------------------------------------------ +// FMAND/FMEQ/FMOR +//------------------------------------------------------------------ + microVUf(void) mVU_FMAND() { microVU* mVU = mVUx; if (!recPass) {} @@ -491,9 +507,13 @@ microVUf(void) mVU_FMOR() { } } +//------------------------------------------------------------------ +// FSAND/FSEQ/FSOR/FSSET +//------------------------------------------------------------------ + microVUf(void) mVU_FSAND() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeSflag(_Ft_); } else { mVUallocSFLAGa(gprT1, fvsInstance); AND16ItoR(gprT1, _Imm12_); @@ -503,7 +523,7 @@ microVUf(void) mVU_FSAND() { microVUf(void) mVU_FSEQ() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeSflag(_Ft_); } else { mVUallocSFLAGa(gprT1, fvsInstance); XOR16ItoR(gprT1, _Imm12_); @@ -515,7 +535,7 @@ microVUf(void) mVU_FSEQ() { microVUf(void) mVU_FSOR() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { mVUanalyzeSflag(_Ft_); } else { mVUallocSFLAGa(gprT1, fvsInstance); OR16ItoR(gprT1, _Imm12_); @@ -536,6 +556,10 @@ microVUf(void) mVU_FSSET() { } } +//------------------------------------------------------------------ +// IADD/IADDI/IADDIU/IAND/IOR/ISUB/ISUBIU +//------------------------------------------------------------------ + microVUf(void) mVU_IADD() { microVU* mVU = mVUx; if (!recPass) {} @@ -623,6 +647,10 @@ microVUf(void) mVU_ISUBIU() { } } +//------------------------------------------------------------------ +// MOVE/MFIR/MFP/MTIR/MR32 +//------------------------------------------------------------------ + microVUf(void) mVU_MOVE() { microVU* mVU = mVUx; if (!recPass) { /*If (!_Ft_ || (_Ft_ == _Fs_)) nop();*/ } @@ -672,6 +700,10 @@ microVUf(void) mVU_MR32() { } } +//------------------------------------------------------------------ +// ILW/ILWR +//------------------------------------------------------------------ + microVUf(void) mVU_ILW() { microVU* mVU = mVUx; if (!recPass) { /*If (!_Ft_) nop();*/ } @@ -709,6 +741,10 @@ microVUf(void) mVU_ILWR() { } } +//------------------------------------------------------------------ +// ISW/ISWR +//------------------------------------------------------------------ + microVUf(void) mVU_ISW() { microVU* mVU = mVUx; if (!recPass) {} @@ -757,6 +793,10 @@ microVUf(void) mVU_ISWR() { } } +//------------------------------------------------------------------ +// LQ/LQD/LQI +//------------------------------------------------------------------ + microVUf(void) mVU_LQ() { microVU* mVU = mVUx; if (!recPass) { /*If (!_Ft_) nop();*/ } @@ -818,6 +858,10 @@ microVUf(void) mVU_LQI() { } } +//------------------------------------------------------------------ +// SQ/SQD/SQI +//------------------------------------------------------------------ + microVUf(void) mVU_SQ() { microVU* mVU = mVUx; if (!recPass) {} @@ -875,6 +919,10 @@ microVUf(void) mVU_SQI() { } } +//------------------------------------------------------------------ +// RINIT/RGET/RNEXT/RXOR +//------------------------------------------------------------------ + microVUf(void) mVU_RINIT() { microVU* mVU = mVUx; if (!recPass) {} @@ -938,21 +986,27 @@ microVUf(void) mVU_RXOR() { } } +//------------------------------------------------------------------ +// WaitP/WaitQ +//------------------------------------------------------------------ + microVUf(void) mVU_WAITP() { microVU* mVU = mVUx; - if (!recPass) {} - else {} + if (!recPass) { mVUstall = aMax(mVUstall, ((mVUregs.p) ? (mVUregs.p - 1) : 0)); } } microVUf(void) mVU_WAITQ() { microVU* mVU = mVUx; - if (!recPass) {} - else {} + if (!recPass) { mVUstall = aMax(mVUstall, mVUregs.q); } } +//------------------------------------------------------------------ +// XTOP/XITOP +//------------------------------------------------------------------ + microVUf(void) mVU_XTOP() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { if (!_Ft_) { mVUinfo |= _isNOP; return; } analyzeVIreg2(_Ft_, 1); } else { MOVZX32M16toR( gprT1, (uptr)&mVU->regs->vifRegs->top); mVUallocVIb(gprT1, _Ft_); @@ -961,13 +1015,17 @@ microVUf(void) mVU_XTOP() { microVUf(void) mVU_XITOP() { microVU* mVU = mVUx; - if (!recPass) {} + if (!recPass) { if (!_Ft_) { mVUinfo |= _isNOP; return; } analyzeVIreg2(_Ft_, 1); } else { MOVZX32M16toR( gprT1, (uptr)&mVU->regs->vifRegs->itop ); mVUallocVIb(gprT1, _Ft_); } } +//------------------------------------------------------------------ +// XGkick +//------------------------------------------------------------------ + microVUt(void) __fastcall mVU_XGKICK_(u32 addr) { microVU* mVU = mVUx; u32 *data = (u32*)(mVU->regs->Mem + (addr&0x3fff)); @@ -990,7 +1048,7 @@ microVUf(void) mVU_XGKICK() { } //------------------------------------------------------------------ -// Branches +// Branches/Jumps //------------------------------------------------------------------ microVUf(void) mVU_B() { diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index ce9272f201..90232a5088 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -66,9 +66,9 @@ declareAllVariables //------------------------------------------------------------------ // Helper Macros //------------------------------------------------------------------ -#define _Ft_ ((mVU->code >> 16) & 0x1F) // The rt part of the instruction register -#define _Fs_ ((mVU->code >> 11) & 0x1F) // The rd part of the instruction register -#define _Fd_ ((mVU->code >> 6) & 0x1F) // The sa part of the instruction register +#define _Ft_ ((mVU->code >> 16) & 0x1F) // The ft/it part of the instruction register +#define _Fs_ ((mVU->code >> 11) & 0x1F) // The fs/is part of the instruction register +#define _Fd_ ((mVU->code >> 6) & 0x1F) // The fd/id part of the instruction register #define _X ((mVU->code>>24) & 0x1) #define _Y ((mVU->code>>23) & 0x1) @@ -144,11 +144,12 @@ declareAllVariables #define mVUbranch mVUallocInfo.branch #define mVUcycles mVUallocInfo.cycles #define mVUstall mVUallocInfo.maxStall -#define mVUdivFlag mVUallocInfo.divFlag -#define mVUdivFlagT mVUallocInfo.divFlagTimer +//#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 incCycles(x) { mVUcycles += x; } @@ -157,6 +158,7 @@ declareAllVariables #define _isBranch (1<<1) // Cur Instruction is a Branch #define _isEOB (1<<2) // End of Block #define _isBdelay (1<<3) // Cur Instruction in Branch Delay slot +#define _isSflag (1<<4) // Cur Instruction uses status flag #define _writeQ (1<<5) #define _readQ (1<<6) #define _writeP (1<<7) @@ -177,6 +179,7 @@ declareAllVariables #define isBranch (mVUinfo & (1<<1)) #define isEOB (mVUinfo & (1<<2)) #define isBdelay (mVUinfo & (1<<3)) +#define isSflag (mVUinfo & (1<<4)) #define writeQ ((mVUinfo >> 5) & 1) #define readQ ((mVUinfo >> 6) & 1) #define writeP ((mVUinfo >> 7) & 1) @@ -200,3 +203,14 @@ declareAllVariables #define isMMX(_VIreg_) (_VIreg_ >= 1 && _VIreg_ <=9) #define mmVI(_VIreg_) (_VIreg_ - 1) +#ifdef mVUdebug +#define mVUdebugStuff1() { \ + 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"); } \ + if (curI & _Dbit_) { SysPrintf("microVU: D-bit set!\n"); } \ + if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \ +} +#else +#define mVUdebugStuff1() {} +#endif