microVU: more recompiler first-pass implementation stuff...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@915 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-04-06 07:32:10 +00:00
parent 014b5c6671
commit 923802f936
8 changed files with 180 additions and 50 deletions

View File

@ -23,6 +23,7 @@
#include "VUmicro.h"
#include "iVUzerorec.h"
#ifndef PCSX2_MICROVU_
namespace VU0micro
{
void recAlloc()
@ -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;

View File

@ -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;

View File

@ -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<vuIndex>();
@ -55,15 +55,15 @@ microVUt(void) mVUreset() {
mVUclose<vuIndex>(); // 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));
@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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,7 +47,6 @@ 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)
@ -68,10 +55,10 @@ microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState,
// First Pass
setCode();
branch = 0;
mVUbranch = 0;
mVUstartPC = iPC;
mVUcycles = 1; // Skips "M" phase, and starts counting cycles at "T" stage
for (;;) {
for (int branch = 0;; ) {
startLoop();
mVUopU<vuIndex, 0>();
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<vuIndex, 1>(); incPC(2); }

View File

@ -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<vuIndex>(_Ft_); }
else {
mVUallocSFLAGa<vuIndex>(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<vuIndex>(_Ft_); }
else {
mVUallocSFLAGa<vuIndex>(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<vuIndex>(_Ft_); }
else {
mVUallocSFLAGa<vuIndex>(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<vuIndex>(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<vuIndex>(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() {

View File

@ -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