diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index c9bbfbe4bd..13113b684d 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -588,8 +588,8 @@ struct INTCregisters u32 _padding2[3]; }; -#define dmacRegs ((DMACregisters*)(eeMem->HW+0xE000)) -#define intcRegs ((INTCregisters*)(eeMem->HW+0xF000)) +#define dmacRegs ((DMACregisters*)(eeHw+0xE000)) +#define intcRegs ((INTCregisters*)(eeHw+0xF000)) static __fi void throwBusError(const char *s) { diff --git a/pcsx2/Dump.cpp b/pcsx2/Dump.cpp index b61ad4925a..9667edc7cb 100644 --- a/pcsx2/Dump.cpp +++ b/pcsx2/Dump.cpp @@ -129,7 +129,7 @@ void iDumpRegisters(u32 startpc, u32 temp) __Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); for(i = 0; i < ArraySize(dmacs); ++i) { - DMACh* p = (DMACh*)(&eeMem->HW[dmacs[i]]); + DMACh* p = (DMACh*)(&eeHw[dmacs[i]]); __Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr); } __Log(L"dmac " + dmacRegs->ctrl.desc() + L" " + dmacRegs->stat.desc() + L" " + dmacRegs->rbsr.desc() + L" " + dmacRegs->rbor.desc()); diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index dc4f0b7582..861abb7977 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -277,7 +277,7 @@ struct GIFregisters u32 padding9[3]; }; -#define gifRegs ((GIFregisters*)(eeMem->HW+0x3000)) +#define gifRegs ((GIFregisters*)(eeHw+0x3000)) extern tGSTransferStatus GSTransferStatus; diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index f7720ae2e9..022df7e377 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -54,8 +54,8 @@ void hwReset() { hwInit(); - memzero_ptr( eeMem->HW ); - //memset(eeMem->HW+0x2000, 0, 0x0000e000); + memzero_ptr( eeHw ); + //memset(eeHw+0x2000, 0, 0x0000e000); psHu32(SBUS_F260) = 0x1D000060; diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h index 2af7c662d1..232067b486 100644 --- a/pcsx2/Hw.h +++ b/pcsx2/Hw.h @@ -20,11 +20,11 @@ ////////////////////////////////////////////////////////////////////////// // Hardware FIFOs (128 bit access only!) // -// VIF0 -- 0x10004000 -- eeMem->HW[0x4000] -// VIF1 -- 0x10005000 -- eeMem->HW[0x5000] -// GIF -- 0x10006000 -- eeMem->HW[0x6000] -// IPUout -- 0x10007000 -- eeMem->HW[0x7000] -// IPUin -- 0x10007010 -- eeMem->HW[0x7010] +// VIF0 -- 0x10004000 -- eeHw[0x4000] +// VIF1 -- 0x10005000 -- eeHw[0x5000] +// GIF -- 0x10006000 -- eeHw[0x6000] +// IPUout -- 0x10007000 -- eeHw[0x7000] +// IPUin -- 0x10007010 -- eeHw[0x7010] void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out); void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out); diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp index 0089c3c625..2160ea2eab 100644 --- a/pcsx2/HwRead.cpp +++ b/pcsx2/HwRead.cpp @@ -270,7 +270,7 @@ mem32_t __fastcall hwRead32_page_00(u32 mem) case 0x830: return (u16)counters[1].hold; } - return *((u32*)&eeMem->HW[mem]); + return *((u32*)&eeHw[mem]); } // Reads hardware registers for page 1 (counters 2 and 3) @@ -288,7 +288,7 @@ mem32_t __fastcall hwRead32_page_01(u32 mem) case 0x1820: return (u16)counters[3].target; } - return *((u32*)&eeMem->HW[mem]); + return *((u32*)&eeHw[mem]); } // Reads hardware registers for page 15 (0x0F). @@ -309,7 +309,7 @@ static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack ) if( mem == ics ) // INTC_STAT { if( intchack ) IntCHackCheck(); - return *((u32*)&eeMem->HW[ics]); + return *((u32*)&eeHw[ics]); } switch( mem ) @@ -355,7 +355,7 @@ static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack ) } return 0; } - return *((u32*)&eeMem->HW[mem]); + return *((u32*)&eeHw[mem]); } mem32_t __fastcall hwRead32_page_0F(u32 mem) @@ -435,7 +435,7 @@ mem32_t __fastcall hwRead32_generic(u32 mem) jNO_DEFAULT; } - return *((u32*)&eeMem->HW[masked_mem]); + return *((u32*)&eeHw[masked_mem]); } ///////////////////////////////////////////////////////////////////////// diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index c400ec4bf7..cb0c49dc4a 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -750,7 +750,7 @@ void __fastcall hwWrite32_page_00( u32 mem, u32 value ) case 0x830: rcntWhold(1, value); return; } - *((u32*)&eeMem->HW[mem]) = value; + *((u32*)&eeHw[mem]) = value; } // Page 1 of HW memory houses registers for Counters 2 and 3 @@ -768,7 +768,7 @@ void __fastcall hwWrite32_page_01( u32 mem, u32 value ) case 0x1820: rcntWtarget(3, value); return; } - *((u32*)&eeMem->HW[mem]) = value; + *((u32*)&eeHw[mem]) = value; } // page 2 is the IPU register space! diff --git a/pcsx2/IPU/IPU.h b/pcsx2/IPU/IPU.h index 6bfb1196fb..638180ca22 100644 --- a/pcsx2/IPU/IPU.h +++ b/pcsx2/IPU/IPU.h @@ -245,7 +245,7 @@ struct IPUregisters { u32 dummy3[2]; }; -#define ipuRegs ((IPUregisters*)(&eeMem->HW[0x2000])) +#define ipuRegs ((IPUregisters*)(&eeHw[0x2000])) struct tIPU_cmd { diff --git a/pcsx2/IopMem.cpp b/pcsx2/IopMem.cpp index c929542afb..9168b639d4 100644 --- a/pcsx2/IopMem.cpp +++ b/pcsx2/IopMem.cpp @@ -468,7 +468,7 @@ void __fastcall iopMemWrite32(u32 mem, u32 value) // wtf? why were we writing to the EE's sif space? Commenting this out doesn't // break any of my games, and should be more correct, but I guess we'll see. --air - //*(u32*)(eeMem->HW+0xf200+(mem&0xf0)) = value; + //*(u32*)(eeHw+0xf200+(mem&0xf0)) = value; return; } else if (t == 0x1000) diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index 12de95d7a9..4448ebb81e 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -602,10 +602,12 @@ protected: void OnPageFaultEvent( const PageFaultInfo& info, bool& handled ); }; -mmap_PageFaultHandler mmap_faultHandler; +static mmap_PageFaultHandler mmap_faultHandler; EEVM_MemoryAllocMess* eeMem = NULL; +__pagealigned u8 eeHw[Ps2MemSize::Hardware]; + void memAlloc() { if( eeMem == NULL ) diff --git a/pcsx2/Memory.h b/pcsx2/Memory.h index 4a0a72659e..a72c772066 100644 --- a/pcsx2/Memory.h +++ b/pcsx2/Memory.h @@ -35,32 +35,32 @@ static __fi void ZeroQWC( void* dest ) } // Various useful locations -#define spr0 ((DMACh*)&eeMem->HW[0xD000]) -#define spr1 ((DMACh*)&eeMem->HW[0xD400]) +#define spr0 ((DMACh*)&eeHw[0xD000]) +#define spr1 ((DMACh*)&eeHw[0xD400]) -#define gif ((DMACh*)&eeMem->HW[0xA000]) +#define gif ((DMACh*)&eeHw[0xA000]) -#define vif0ch ((DMACh*)&eeMem->HW[0x8000]) -#define vif1ch ((DMACh*)&eeMem->HW[0x9000]) +#define vif0ch ((DMACh*)&eeHw[0x8000]) +#define vif1ch ((DMACh*)&eeHw[0x9000]) -#define sif0dma ((DMACh*)&eeMem->HW[0xc000]) -#define sif1dma ((DMACh*)&eeMem->HW[0xc400]) -#define sif2dma ((DMACh*)&eeMem->HW[0xc800]) +#define sif0dma ((DMACh*)&eeHw[0xc000]) +#define sif1dma ((DMACh*)&eeHw[0xc400]) +#define sif2dma ((DMACh*)&eeHw[0xc800]) -#define ipu0dma ((DMACh *)&eeMem->HW[0xb000]) -#define ipu1dma ((DMACh *)&eeMem->HW[0xb400]) +#define ipu0dma ((DMACh *)&eeHw[0xb000]) +#define ipu1dma ((DMACh *)&eeHw[0xb400]) #define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D -#define psHs8(mem) (*(s8 *)&eeMem->HW[(mem) & 0xffff]) -#define psHs16(mem) (*(s16*)&eeMem->HW[(mem) & 0xffff]) -#define psHs32(mem) (*(s32*)&eeMem->HW[(mem) & 0xffff]) -#define psHs64(mem) (*(s64*)&eeMem->HW[(mem) & 0xffff]) -#define psHu8(mem) (*(u8 *)&eeMem->HW[(mem) & 0xffff]) -#define psHu16(mem) (*(u16*)&eeMem->HW[(mem) & 0xffff]) -#define psHu32(mem) (*(u32*)&eeMem->HW[(mem) & 0xffff]) -#define psHu64(mem) (*(u64*)&eeMem->HW[(mem) & 0xffff]) -#define psHu128(mem)(*(u128*)&eeMem->HW[(mem) & 0xffff]) +#define psHs8(mem) (*(s8 *)&eeHw[(mem) & 0xffff]) +#define psHs16(mem) (*(s16*)&eeHw[(mem) & 0xffff]) +#define psHs32(mem) (*(s32*)&eeHw[(mem) & 0xffff]) +#define psHs64(mem) (*(s64*)&eeHw[(mem) & 0xffff]) +#define psHu8(mem) (*(u8 *)&eeHw[(mem) & 0xffff]) +#define psHu16(mem) (*(u16*)&eeHw[(mem) & 0xffff]) +#define psHu32(mem) (*(u32*)&eeHw[(mem) & 0xffff]) +#define psHu64(mem) (*(u64*)&eeHw[(mem) & 0xffff]) +#define psHu128(mem)(*(u128*)&eeHw[(mem) & 0xffff]) #define psMs8(mem) (*(s8 *)&eeMem->Main[(mem) & 0x1ffffff]) #define psMs16(mem) (*(s16*)&eeMem->Main[(mem) & 0x1ffffff]) @@ -114,7 +114,7 @@ static __fi void ZeroQWC( void* dest ) #define psSu64(mem) (*(u64 *)&eeMem->Scratch[(mem) & 0x3fff]) #define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem) & 0x3fff]) -#define psH_DMACh(mem) (*(DMACh*)&eeMem->HW[(mem) & 0xffff]) +#define psH_DMACh(mem) (*(DMACh*)&eeHw[(mem) & 0xffff]) extern void memAlloc(); extern void memReset(); // clears PS2 ram and loads the bios. Throws Exception::FileNotFound on error. diff --git a/pcsx2/MemoryTypes.h b/pcsx2/MemoryTypes.h index 8feba6746a..a591469b1c 100644 --- a/pcsx2/MemoryTypes.h +++ b/pcsx2/MemoryTypes.h @@ -37,15 +37,55 @@ typedef u32 mem32_t; typedef u64 mem64_t; typedef u128 mem128_t; + +// -------------------------------------------------------------------------------------- +// Future-Planned VTLB pagefault scheme! +// -------------------------------------------------------------------------------------- +// When enabled, the VTLB will use a large-area reserved memory range of 512megs for EE +// physical ram/rom access. The base ram will be committed at 0x00000000, and ROMs will be +// at 0x1fc00000, etc. All memory ranges in between will be uncommitted memory -- which +// means that the memory will *not* count against the operating system's physical memory +// pool. +// +// When the VTLB generates memory operations (loads/stores), it will assume that the op +// is addressing either RAM or ROM, and by assuming that it can generate a completely efficient +// direct memory access (one AND and one MOV instruction). If the access is to another area of +// memory, such as hardware registers or scratchpad, the access will generate a page fault, the +// compiled block will be cleared and re-compiled using "full" VTLB translation logic. +// +#define VTLB_UsePageFaulting 0 + +#if VTLB_UsePageFaulting + +// The order of the components in this struct *matter* -- it has been laid out so that the +// full breadth of PS2 RAM and ROM mappings are directly supported. +struct EEVM_MemoryAllocMess +{ + u8 (&Main)[Ps2MemSize::Base]; // Main memory (hard-wired to 32MB) + + u8 _padding1[0x1e000000-Ps2MemSize::Base] + u8 (&ROM1)[Ps2MemSize::Rom1]; // DVD player + + u8 _padding2[0x1e040000-(0x1e000000+Ps2MemSize::Rom1)] + u8 (&EROM)[Ps2MemSize::ERom]; // DVD player extensions + + u8 _padding3[0x1e400000-(0x1e040000+Ps2MemSize::EROM)] + u8 (&ROM2)[Ps2MemSize::Rom2]; // Chinese extensions + + u8 _padding4[0x1fc00000-(0x1e040000+Ps2MemSize::Rom2)]; + u8 (&ROM)[Ps2MemSize::Rom]; // Boot rom (4MB) +}; + +#else + struct EEVM_MemoryAllocMess { u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad! u8 Main[Ps2MemSize::Base]; // Main memory (hard-wired to 32MB) - u8 HW[Ps2MemSize::Hardware]; // Hardware registers u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB) u8 ROM1[Ps2MemSize::Rom1]; // DVD player - u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions (?) - u8 EROM[Ps2MemSize::ERom]; // DVD player extensions (?) + u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions + u8 EROM[Ps2MemSize::ERom]; // DVD player extensions // Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB). // Such accesses are not documented as causing bus errors but as the memory does @@ -56,4 +96,13 @@ struct EEVM_MemoryAllocMess u8 ZeroWrite[_1mb]; }; +#endif + +// EE Hardware registers. +// DevNote: These are done as a static array instead of a pointer in order to allow for simpler +// macros and reference handles to be defined (we can safely use compile-time references to +// registers instead of having to use instance variables). +extern __pagealigned u8 eeHw[Ps2MemSize::Hardware]; + + extern EEVM_MemoryAllocMess* eeMem; diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index 651a1e9029..0630289b42 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -154,7 +154,7 @@ void SaveStateBase::FreezeMainMemory() // --------------------------- FreezeMem(eeMem->Main, Ps2MemSize::Base); // 32 MB main memory FreezeMem(eeMem->Scratch, Ps2MemSize::Scratch); // scratch pad - FreezeMem(eeMem->HW, Ps2MemSize::Hardware); // hardware memory + FreezeMem(eeHw, Ps2MemSize::Hardware); // hardware memory FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory diff --git a/pcsx2/VU.h b/pcsx2/VU.h index b10312dfd2..d0b4243863 100644 --- a/pcsx2/VU.h +++ b/pcsx2/VU.h @@ -119,40 +119,56 @@ struct ialuPipe { struct VURegs { VECTOR VF[32]; // VF and VI need to be first in this struct for proper mapping REG_VI VI[32]; // needs to be 128bit x 32 (cottonvibes) + VECTOR ACC; REG_VI q; REG_VI p; + uint idx; // VU index (0 or 1) + + // flags/cycle are needed by VIF dma code, so they have to be here (for now) + // We may replace these by accessors in the future, if merited. + u32 cycle; + u32 flags; + + // Current opcode being interpreted or recompiled (this var is used by Interps and superVU + // but not microVU. Would like to have it local to their respective classes... someday) + u32 code; + + // branch/branchpc are used by interpreter only, but making them local to the interpreter + // classes requires considerable code refactoring. Maybe later. >_< + u32 branch; + u32 branchpc; + + // MAC/Status flags -- these are used by interpreters and superVU, but are kind of hacky + // and shouldn't be relied on for any useful/valid info. Would like to move them out of + // this struct eventually. u32 macflag; u32 statusflag; u32 clipflag; - u32 cycle; - u32 flags; - - void (*vuExec)(VURegs*); - VIFregisters *vifRegs; - u8 *Mem; u8 *Micro; - u32 code; - u32 maxmem; - u32 maxmicro; - - u16 branch; - u16 ebit; - u32 branchpc; + u32 ebit; fmacPipe fmac[8]; fdivPipe fdiv; efuPipe efu; ialuPipe ialu[8]; - VURegs() : - Mem( NULL ) - , Micro( NULL ) + VURegs() { + Mem = NULL; + Micro = NULL; + } + + bool IsVU1() const; + bool IsVU0() const; + + VIFregisters& GetVifRegs() const + { + return IsVU1() ? vif1RegsRef : vif0RegsRef; } }; @@ -167,23 +183,15 @@ enum VUPipeState VUPIPE_XGKICK }; -struct _VURegsNum { - u8 pipe; // if 0xff, COP2 - u8 VFwrite; - u8 VFwxyzw; - u8 VFr0xyzw; - u8 VFr1xyzw; - u8 VFread0; - u8 VFread1; - u32 VIwrite; - u32 VIread; - int cycles; -}; +extern __aligned16 VURegs vuRegs[2]; -extern VURegs* g_pVU1; -extern __aligned16 VURegs VU0; +// Obsolete(?) -- I think I'd rather use vu0Regs/vu1Regs or actually have these explicit to any +// CPP file that needs them only. --air +static VURegs& VU0 = vuRegs[0]; +static VURegs& VU1 = vuRegs[1]; -#define VU1 (*g_pVU1) +__fi bool VURegs::IsVU1() const { return this == &vuRegs[1]; } +__fi bool VURegs::IsVU0() const { return this == &vuRegs[0]; } extern u32* GET_VU_MEM(VURegs* VU, u32 addr); diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index 89f123f044..9ece6dd2d5 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -44,8 +44,6 @@ using namespace R5900; -__aligned16 VURegs VU0; - void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();} void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();} diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp index 2503b21dfb..8db9707665 100644 --- a/pcsx2/VU0microInterp.cpp +++ b/pcsx2/VU0microInterp.cpp @@ -47,15 +47,6 @@ static void _vu0Exec(VURegs* VU) int vireg; int discard=0; - if(VU0.VI[REG_TPC].UL >= VU0.maxmicro){ -#ifdef CPU_LOG - Console.WriteLn("VU0 memory overflow!!: %x", VU->VI[REG_TPC].UL); -#endif - VU0.VI[REG_VPU_STAT].UL&= ~0x1; - VU->cycle++; - return; - } - ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; VU->VI[REG_TPC].UL+=8; @@ -171,14 +162,8 @@ static void _vu0Exec(VURegs* VU) void vu0Exec(VURegs* VU) { - if (VU->VI[REG_TPC].UL >= VU->maxmicro) { -#ifdef CPU_LOG - Console.Warning("VU0 memory overflow!!: %x", VU->VI[REG_TPC].UL); -#endif - VU0.VI[REG_VPU_STAT].UL&= ~0x1; - } else { - _vu0Exec(VU); - } + VU0.VI[REG_TPC].UL &= VU0_PROGMASK; + _vu0Exec(VU); VU->cycle++; if (VU->VI[0].UL != 0) DbgCon.Error("VI[0] != 0!!!!\n"); diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index 5cc1602a06..d77d8edb78 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -24,8 +24,6 @@ #include "VUmicro.h" -VURegs* g_pVU1; - #ifdef PCSX2_DEBUG u32 vudump = 0; #endif diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index a33ea23405..526b62acca 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -48,13 +48,6 @@ static void _vu1Exec(VURegs* VU) int vireg; int discard=0; - if(VU->VI[REG_TPC].UL >= VU->maxmicro){ - CPU_LOG("VU1 memory overflow!!: %x", VU->VI[REG_TPC].UL); - VU->VI[REG_TPC].UL &= 0x3FFF; - /*VU0.VI[REG_VPU_STAT].UL&= ~0x100; - VU->cycle++; - return;*/ - } ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; VU->VI[REG_TPC].UL+=8; @@ -182,6 +175,7 @@ InterpVU1::InterpVU1() void InterpVU1::Step() { + VU1.VI[REG_TPC].UL &= VU1_PROGMASK; vu1Exec( &VU1 ); } @@ -190,11 +184,11 @@ void InterpVU1::Execute(u32 cycles) for (int i = (int)cycles; i > 0 ; i--) { if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) { if (VU1.branch || VU1.ebit) { - vu1Exec(&VU1); // run branch delay slot? + Step(); // run branch delay slot? } break; } - vu1Exec(&VU1); + Step(); } } diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h index bf1aa1605c..652d9f9afc 100644 --- a/pcsx2/VUmicro.h +++ b/pcsx2/VUmicro.h @@ -18,6 +18,17 @@ #include "VU.h" #include "VUops.h" #include "R5900.h" + +static const uint VU0_MEMSIZE = 0x1000; +static const uint VU0_PROGSIZE = 0x1000; +static const uint VU1_MEMSIZE = 0x4000; +static const uint VU1_PROGSIZE = 0x4000; + +static const uint VU0_MEMMASK = VU0_MEMSIZE-1; +static const uint VU0_PROGMASK = VU0_PROGSIZE-1; +static const uint VU1_MEMMASK = VU1_MEMSIZE-1; +static const uint VU1_PROGMASK = VU1_PROGSIZE-1; + #define vuRunCycles (512*12) // Cycles to run ExecuteBlockJIT() for (called from within recs) #define vu0RunCycles (512*12) // Cycles to run vu0 for whenever ExecuteBlock() is called #define vu1RunCycles (3000000) // mVU1 uses this for inf loop detection on dev builds diff --git a/pcsx2/VUmicroMem.cpp b/pcsx2/VUmicroMem.cpp index b61a024b33..d0aad70822 100644 --- a/pcsx2/VUmicroMem.cpp +++ b/pcsx2/VUmicroMem.cpp @@ -18,10 +18,12 @@ #include "Common.h" #include "VUmicro.h" +__aligned16 VURegs vuRegs[2]; + static u8* m_vuAllMem = NULL; static const uint m_vuMemSize = 0x1000 + // VU0micro memory - 0x4000+0x800 + // VU0 memory and VU1 registers + 0x4000 + // VU0 memory 0x4000 + // VU1 memory 0x4000; @@ -33,12 +35,9 @@ void vuMicroMemAlloc() if( m_vuAllMem == NULL ) throw Exception::OutOfMemory( L"VU0 and VU1 on-chip memory" ); - pxAssume( sizeof( VURegs ) <= 0x800 ); - u8* curpos = m_vuAllMem; VU0.Micro = curpos; curpos += 0x1000; VU0.Mem = curpos; curpos += 0x4000; - g_pVU1 = (VURegs*)curpos; curpos += 0x800; VU1.Micro = curpos; curpos += 0x4000; VU1.Mem = curpos; //curpos += 0x4000; @@ -50,7 +49,6 @@ void vuMicroMemShutdown() vtlb_free( m_vuAllMem, m_vuMemSize ); m_vuAllMem = NULL; - g_pVU1 = NULL; } void vuMicroMemReset() @@ -72,17 +70,6 @@ void vuMicroMemReset() memzero_ptr<4*1024>(VU0.Mem); memzero_ptr<4*1024>(VU0.Micro); - /* this is kinda tricky, maxmem is set to 0x4400 here, - tho it's not 100% accurate, since the mem goes from - 0x0000 - 0x1000 (Mem) and 0x4000 - 0x4400 (VU1 Regs), - i guess it shouldn't be a problem, - at least hope so :) (linuz) - */ - VU0.maxmem = 0x4800-4; //We are allocating 0x800 for vu1 reg's - VU0.maxmicro = 0x1000-4; - VU0.vuExec = vu0Exec; - VU0.vifRegs = vif0Regs; - // === VU1 Initialization === memzero(VU1.ACC); memzero(VU1.VF); @@ -94,13 +81,6 @@ void vuMicroMemReset() VU1.VI[0].UL = 0; memzero_ptr<16*1024>(VU1.Mem); memzero_ptr<16*1024>(VU1.Micro); - - VU1.maxmem = 0x4000-4;//16*1024-4; - VU1.maxmicro = 0x4000-4; -// VU1.VF = (VECTOR*)(VU0.Mem + 0x4000); -// VU1.VI = (REG_VI*)(VU0.Mem + 0x4200); - VU1.vuExec = vu1Exec; - VU1.vifRegs = vif1Regs; } void SaveStateBase::vuMicroFreeze() diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index 590d977299..84f588294e 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -15,12 +15,11 @@ #include "PrecompiledHeader.h" #include "Common.h" - -#include - #include "VUops.h" #include "GS.h" +#include + //Lower/Upper instructions can use that.. #define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register #define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register @@ -1579,9 +1578,9 @@ static __fi void _vuMR32(VURegs * VU) { __fi u32* GET_VU_MEM(VURegs* VU, u32 addr) // non-static, also used by sVU for now. { - if( VU == g_pVU1 ) return (u32*)(VU1.Mem+(addr&0x3fff)); - if( addr >= 0x4000 ) return (u32*)(VU0.Mem+(addr&0x43f0)); // get VF and VI regs (they're mapped to 0x4xx0 in VU0 mem!) - return (u32*)(VU0.Mem+(addr&0x0fff)); // for addr 0x0000 to 0x4000 just wrap around + if( VU == &vuRegs[1] ) return (u32*)(vuRegs[1].Mem+(addr&0x3fff)); + if( addr >= 0x4000 ) return (u32*)(vuRegs[0].Mem+(addr&0x43f0)); // get VF and VI regs (they're mapped to 0x4xx0 in VU0 mem!) + return (u32*)(vuRegs[0].Mem+(addr&0x0fff)); // for addr 0x0000 to 0x4000 just wrap around } static __ri void _vuLQ(VURegs * VU) { @@ -2015,7 +2014,7 @@ static __ri void _vuEEXP(VURegs * VU) { static __ri void _vuXITOP(VURegs * VU) { if (_It_ == 0) return; - VU->VI[_It_].US[0] = VU->vifRegs->itop; + VU->VI[_It_].US[0] = VU->GetVifRegs().itop; } static __ri void _vuXGKICK(VURegs * VU) @@ -2032,7 +2031,7 @@ static __ri void _vuXGKICK(VURegs * VU) static __ri void _vuXTOP(VURegs * VU) { if(_It_ == 0) return; - VU->VI[_It_].US[0] = (u16)VU->vifRegs->top; + VU->VI[_It_].US[0] = (u16)VU->GetVifRegs().top; } #define GET_VF0_FLAG(reg) (((reg)==0)?(1<VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF) +struct _VURegsNum { + u8 pipe; // if 0xff, COP2 + u8 VFwrite; + u8 VFwxyzw; + u8 VFr0xyzw; + u8 VFr1xyzw; + u8 VFread0; + u8 VFread1; + u32 VIwrite; + u32 VIread; + int cycles; +}; + #define __vuRegsCall __fastcall typedef void __vuRegsCall FnType_VuRegsN(_VURegsNum *VUregsn); typedef FnType_VuRegsN* Fnptr_VuRegsN; diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index 654a44969c..0e749a432d 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -15,6 +15,7 @@ #pragma once +#include "MemoryTypes.h" #include "R5900.h" enum vif0_stat_flags @@ -214,8 +215,8 @@ struct VIFregisters { extern VIFregisters *vifRegs; -#define vif0RegsRef ((VIFregisters&)eeMem->HW[0x3800]) -#define vif1RegsRef ((VIFregisters&)eeMem->HW[0x3c00]) +static VIFregisters& vif0RegsRef = (VIFregisters&)eeHw[0x3800]; +static VIFregisters& vif1RegsRef = (VIFregisters&)eeHw[0x3C00]; #define vif0Regs (&vif0RegsRef) #define vif1Regs (&vif1RegsRef) diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 0adc11b3ed..795b6bb425 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -183,7 +183,7 @@ bool _VIF1chain() __fi void vif1SetupTransfer() { tDMA_TAG *ptag; - DMACh& vif1c = (DMACh&)eeMem->HW[0x9000]; + DMACh& vif1c = (DMACh&)eeHw[0x9000]; switch (vif1.dmamode) { diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 6d0d37a783..c2b40d04aa 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -39,32 +39,33 @@ static __fi void vifFlush(int idx) { static __fi void vuExecMicro(int idx, u32 addr) { VURegs* VU = nVif[idx].VU; + VIFregisters& vifRegs = VU->GetVifRegs(); int startcycles = 0; //vifFlush(idx); //if(vifX.vifstalled == true) return; - if (VU->vifRegs->itops > (idx ? 0x3ffu : 0xffu)) { - Console.WriteLn("VIF%d ITOP overrun! %x", idx, VU->vifRegs->itops); - VU->vifRegs->itops &= (idx ? 0x3ffu : 0xffu); + if (vifRegs.itops > (idx ? 0x3ffu : 0xffu)) { + Console.WriteLn("VIF%d ITOP overrun! %x", idx, vifRegs.itops); + vifRegs.itops &= (idx ? 0x3ffu : 0xffu); } - VU->vifRegs->itop = VU->vifRegs->itops; + vifRegs.itop = vifRegs.itops; if (idx) { // in case we're handling a VIF1 execMicro, set the top with the tops value - VU->vifRegs->top = VU->vifRegs->tops & 0x3ff; + vifRegs.top = vifRegs.tops & 0x3ff; // is DBF flag set in VIF_STAT? - if (VU->vifRegs->stat.DBF) { + if (vifRegs.stat.DBF) { // it is, so set tops with base, and clear the stat DBF flag - VU->vifRegs->tops = VU->vifRegs->base; - VU->vifRegs->stat.DBF = false; + vifRegs.tops = vifRegs.base; + vifRegs.stat.DBF = false; } else { // it is not, so set tops with base + offset, and set stat DBF flag - VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst; - VU->vifRegs->stat.DBF = true; + vifRegs.tops = vifRegs.base + vifRegs.ofst; + vifRegs.stat.DBF = true; } } diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index f76dc73072..e30552aa6e 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -639,6 +639,10 @@ RelativePath="..\..\x86\microVU_IR.h" > + + diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 65724dd6a4..a047f1e6fe 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -19,6 +19,22 @@ #include "Common.h" #include "microVU.h" +// Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files) +#include "microVU_Clamp.inl" +#include "microVU_Misc.inl" +#include "microVU_Log.inl" +#include "microVU_Analyze.inl" +#include "microVU_IR.inl" +#include "microVU_Alloc.inl" +#include "microVU_Upper.inl" +#include "microVU_Lower.inl" +#include "microVU_Tables.inl" +#include "microVU_Flags.inl" +#include "microVU_Branch.inl" +#include "microVU_Compile.inl" +#include "microVU_Execute.inl" +#include "microVU_Macro.inl" + //------------------------------------------------------------------ // Micro VU - Global Variables //------------------------------------------------------------------ @@ -70,107 +86,93 @@ static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) } // Only run this once per VU! ;) -static __ri void mVUinit(int vuIndex) { +void microVU::init(uint vuIndex) { if(!x86caps.hasMultimediaExtensions) mVUthrowHardwareDeficiency( L"MMX", vuIndex ); if(!x86caps.hasStreamingSIMDExtensions) mVUthrowHardwareDeficiency( L"SSE", vuIndex ); if(!x86caps.hasStreamingSIMD2Extensions) mVUthrowHardwareDeficiency( L"SSE2", vuIndex ); - microVU* mVU = mVUx; - memzero(mVU->prog); + memzero(prog); - mVU->index = vuIndex; - mVU->cop2 = 0; - mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000); - mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000); - mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4; - mVU->progMemMask = mVU->progSize-1; - mVU->dispCache = NULL; - mVU->cache = NULL; - mVU->cacheSize = mVUcacheSize; - mVU->regAlloc = new microRegAlloc(); + index = vuIndex; + cop2 = 0; + vuMemSize = (index ? 0x4000 : 0x1000); + microMemSize = (index ? 0x4000 : 0x1000); + progSize = (index ? 0x4000 : 0x1000) / 4; + progMemMask = progSize-1; + dispCache = NULL; + cache = NULL; + cacheSize = mVUcacheSize; + regAlloc = new microRegAlloc(this); - for (u32 i = 0; i < (mVU->progSize / 2); i++) { - mVU->prog.prog[i] = new deque(); + for (u32 i = 0; i < (progSize / 2); i++) { + prog.prog[i] = new deque(); } - mVU->dispCache = SysMmapEx(0, mVUdispCacheSize, 0, (mVU->index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher")); - if (!mVU->dispCache) throw Exception::OutOfMemory( mVU->index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" ); - memset(mVU->dispCache, 0xcc, mVUdispCacheSize); + dispCache = SysMmapEx(0, mVUdispCacheSize, 0, (index ? "Micro VU1 Dispatcher" : "Micro VU0 Dispatcher")); + if (!dispCache) throw Exception::OutOfMemory( index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" ); + memset(dispCache, 0xcc, mVUdispCacheSize); // Allocates rec-cache and calls mVUreset() - mVUresizeCache(mVU, mVU->cacheSize + mVUcacheSafeZone); + mVUresizeCache(this, cacheSize + mVUcacheSafeZone); //if (vuIndex) gen_memcpy_vibes(); } // Resets Rec Data -// If vuRegsPtr is NUL, the current regs pointer assigned to the VU compiler is assumed. -static __fi void mVUreset(mV, VURegs* vuRegsPtr) { +void microVU::reset() { - static bool dispatchersGenerated = false; - - if (!vuRegsPtr) vuRegsPtr = mVU->regs; - if (!dispatchersGenerated || (mVU->regs != vuRegsPtr)) - { - // Setup Entrance/Exit Points - // These must be rebuilt whenever the vuRegsPtr has changed. - - dispatchersGenerated = true; - mVU->regs = vuRegsPtr; - - x86SetPtr(mVU->dispCache); - mVUdispatcherA(mVU); - mVUdispatcherB(mVU); - mVUemitSearch(); - } + x86SetPtr(dispCache); + mVUdispatcherA(this); + mVUdispatcherB(this); + mVUemitSearch(); // Clear All Program Data - //memset(&mVU->prog, 0, sizeof(mVU->prog)); - memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); - + //memset(&prog, 0, sizeof(prog)); + memset(&prog.lpState, 0, sizeof(prog.lpState)); + if (IsDevBuild) { // Release builds shouldn't need this - memset(mVU->cache, 0xcc, mVU->cacheSize); + memset(cache, 0xcc, cacheSize); } // Program Variables - mVU->prog.cleared = 1; - mVU->prog.isSame = -1; - mVU->prog.cur = NULL; - mVU->prog.total = 0; - mVU->prog.curFrame = 0; + prog.cleared = 1; + prog.isSame = -1; + prog.cur = NULL; + prog.total = 0; + prog.curFrame = 0; // Setup Dynarec Cache Limits for Each Program - u8* z = mVU->cache; - mVU->prog.x86start = z; - mVU->prog.x86ptr = z; - mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - mVUcacheSafeZone)); // "Safe Zone" + u8* z = cache; + prog.x86start = z; + prog.x86ptr = z; + prog.x86end = (u8*)((uptr)z + (uptr)(cacheSize - mVUcacheSafeZone)); // "Safe Zone" - for (u32 i = 0; i < (mVU->progSize / 2); i++) { - deque::iterator it(mVU->prog.prog[i]->begin()); - for ( ; it != mVU->prog.prog[i]->end(); ++it) { - if (!isVU1) mVUdeleteProg<0>(it[0]); - else mVUdeleteProg<1>(it[0]); + for (u32 i = 0; i < (progSize / 2); i++) { + deque::iterator it(prog.prog[i]->begin()); + for ( ; it != prog.prog[i]->end(); ++it) { + if (index) mVUdeleteProg<1>(it[0]); + else mVUdeleteProg<0>(it[0]); } - mVU->prog.prog[i]->clear(); - mVU->prog.quick[i].block = NULL; - mVU->prog.quick[i].prog = NULL; + prog.prog[i]->clear(); + prog.quick[i].block = NULL; + prog.quick[i].prog = NULL; } } // Free Allocated Resources -static __fi void mVUclose(mV) { +void microVU::close() { - if (mVU->dispCache) { HostSys::Munmap(mVU->dispCache, mVUdispCacheSize); mVU->dispCache = NULL; } - if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; } + if (dispCache) { HostSys::Munmap(dispCache, mVUdispCacheSize); dispCache = NULL; } + if (cache) { HostSys::Munmap(cache, cacheSize); cache = NULL; } // Delete Programs and Block Managers - for (u32 i = 0; i < (mVU->progSize / 2); i++) { - deque::iterator it(mVU->prog.prog[i]->begin()); - for ( ; it != mVU->prog.prog[i]->end(); ++it) { - if (!isVU1) mVUdeleteProg<0>(it[0]); - else mVUdeleteProg<1>(it[0]); + for (u32 i = 0; i < (progSize / 2); i++) { + deque::iterator it(prog.prog[i]->begin()); + for ( ; it != prog.prog[i]->end(); ++it) { + if (index) mVUdeleteProg<1>(it[0]); + else mVUdeleteProg<0>(it[0]); } - safe_delete(mVU->prog.prog[i]); + safe_delete(prog.prog[i]); } } @@ -181,7 +183,7 @@ static void mVUresizeCache(mV, u32 size) { // We can't grow the rec any larger, so just reset it and start over. //(if we don't reset, the rec will eventually crash) Console.WriteLn(Color_Magenta, "microVU%d: Cannot grow cache, size limit reached! [%dmb]. Resetting rec.", mVU->index, mVU->cacheSize/_1mb); - mVUreset(mVU); + mVU->reset(); return; } size = mVUcacheMaxSize; @@ -191,7 +193,7 @@ static void mVUresizeCache(mV, u32 size) { u8* cache = SysMmapEx(0, size, 0, (mVU->index ? "Micro VU1 RecCache" : "Micro VU0 RecCache")); if(!cache && !mVU->cache) throw Exception::OutOfMemory( wxsFormat( L"Micro VU%d recompiled code cache", mVU->index) ); - if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); mVUreset(mVU); return; } + if(!cache) { Console.Error("microVU%d Error - Cache Resize Failed...", mVU->index); mVU->reset(); return; } if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec"); @@ -200,7 +202,7 @@ static void mVUresizeCache(mV, u32 size) { mVU->cache = cache; mVU->cacheSize = size; ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize); - mVUreset(mVU); + mVU->reset(); } // Clears Block Data in specified range @@ -254,8 +256,8 @@ _mVUt __fi microProgram* mVUcreateProg(int startPC) { // Caches Micro Program _mVUt __fi void mVUcacheProg(microProgram& prog) { microVU* mVU = mVUx; - if (!vuIndex) memcpy_const(prog.data, mVU->regs->Micro, 0x1000); - else memcpy_const(prog.data, mVU->regs->Micro, 0x4000); + if (!vuIndex) memcpy_const(prog.data, mVU->regs().Micro, 0x1000); + else memcpy_const(prog.data, mVU->regs().Micro, 0x4000); mVUdumpProg(prog); } @@ -265,17 +267,17 @@ _mVUt __fi bool mVUcmpPartial(microProgram& prog) { deque::const_iterator it(prog.ranges->begin()); for ( ; it != prog.ranges->end(); ++it) { if((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, it[0].start, it[0].end); } - if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs->Micro), ((it[0].end + 8) - it[0].start))) { + if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs().Micro), ((it[0].end + 8) - it[0].start))) { return 0; } } return 1; } -// Compare Cached microProgram to mVU->regs->Micro +// Compare Cached microProgram to mVU->regs().Micro _mVUt __fi bool mVUcmpProg(microProgram& prog, const bool cmpWholeProg) { microVU* mVU = mVUx; - if ((cmpWholeProg && !memcmp_mmx((u8*)prog.data, mVU->regs->Micro, mVU->microMemSize)) + if ((cmpWholeProg && !memcmp_mmx((u8*)prog.data, mVU->regs().Micro, mVU->microMemSize)) || (!cmpWholeProg && mVUcmpPartial(prog))) { mVU->prog.cleared = 0; mVU->prog.cur = &prog; @@ -334,14 +336,14 @@ void recMicroVU0::Allocate() { if(!m_AllocCount) { m_AllocCount++; if (AtomicExchange(mvu0_allocated, 1) == 0) - mVUinit(0); + microVU0.init(0); } } void recMicroVU1::Allocate() { if(!m_AllocCount) { m_AllocCount++; if (AtomicExchange(mvu1_allocated, 1) == 0) - mVUinit(1); + microVU1.init(1); } } @@ -349,24 +351,24 @@ void recMicroVU0::Shutdown() throw() { if (m_AllocCount > 0) { m_AllocCount--; if (AtomicExchange(mvu0_allocated, 0) == 1) - mVUclose(µVU0); + microVU0.close(); } } void recMicroVU1::Shutdown() throw() { if (m_AllocCount > 0) { m_AllocCount--; if (AtomicExchange(mvu1_allocated, 0) == 1) - mVUclose(µVU1); + microVU1.close(); } } void recMicroVU0::Reset() { if(!pxAssertDev(m_AllocCount, "MicroVU0 CPU Provider has not been allocated prior to reset!")) return; - mVUreset(µVU0, &VU0); + microVU0.reset(); } void recMicroVU1::Reset() { if(!pxAssertDev(m_AllocCount, "MicroVU1 CPU Provider has not been allocated prior to reset!")) return; - mVUreset(µVU1, &VU1); + microVU1.reset(); } void recMicroVU0::Execute(u32 cycles) { diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index adfa722ea6..289afa2d44 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -145,7 +145,7 @@ struct microProgManager { microProgramQuick quick[mProgSize/2]; // Quick reference to valid microPrograms for current execution microProgram* cur; // Pointer to currently running MicroProgram int total; // Total Number of valid MicroPrograms - int isSame; // Current cached microProgram is Exact Same program as mVU->regs->Micro (-1 = unknown, 0 = No, 1 = Yes) + int isSame; // Current cached microProgram is Exact Same program as mVU->regs().Micro (-1 = unknown, 0 = No, 1 = Yes) int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one) u32 curFrame; // Frame Counter u8* x86ptr; // Pointer to program's recompilation code @@ -155,10 +155,10 @@ struct microProgManager { }; #define mVUdispCacheSize (0x1000) // Dispatcher Cache Size -#define mVUcacheSize ((mVU->index) ? (_1mb * 17) : (_1mb * 7)) // Initial Size (Excluding Safe-Zone) +#define mVUcacheSize ((index) ? (_1mb * 17) : (_1mb * 7)) // Initial Size (Excluding Safe-Zone) #define mVUcacheMaxSize ((mVU->index) ? (_1mb * 100) : (_1mb * 50)) // Max Size allowed to grow to #define mVUcacheGrowBy ((mVU->index) ? (_1mb * 15) : (_1mb * 10)) // Grows by this amount -#define mVUcacheSafeZone ((mVU->index) ? (_1mb * 3) : (_1mb * 3)) // Safe-Zone for last program +#define mVUcacheSafeZone ((index) ? (_1mb * 3) : (_1mb * 3)) // Safe-Zone for last program struct microVU { @@ -179,7 +179,6 @@ struct microVU { ScopedPtr regAlloc; // Reg Alloc Class ScopedPtr logFile; // Log File Pointer - VURegs* regs; // VU Regs Struct u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to) u8* dispCache; // Dispatchers Cache (where startFunct and exitFunct are written to) u8* startFunct; // Ptr Function to the Start code for recompiled programs @@ -196,6 +195,13 @@ struct microVU { u32 totalCycles; // Total Cycles that mVU is expected to run for u32 cycles; // Cycles Counter + VURegs& regs() const { return ::vuRegs[index]; } + + VIFregisters& getVifRegs() const { return regs().GetVifRegs(); } + __fi REG_VI& getVI(uint reg) const { return regs().VI[reg]; } + __fi VECTOR& getVF(uint reg) const { return regs().VF[reg]; } + + __fi s16 Imm5() const { return ((code & 0x400) ? 0xfff0 : 0) | ((code >> 6) & 0xf); } __fi s32 Imm11() const { return (code & 0x400) ? (0xfffffc00 | (code & 0x3ff)) : (code & 0x3ff); } __fi u32 Imm12() const { return (((code >> 21) & 0x1) << 11) | (code & 0x7ff); } @@ -208,7 +214,7 @@ struct microVU { { prog.IRinfo.curPC += x; prog.IRinfo.curPC &= progMemMask; - code = ((u32*)regs->Micro)[prog.IRinfo.curPC]; + code = ((u32*)regs().Micro)[prog.IRinfo.curPC]; } __ri uint getBranchAddr() const @@ -222,6 +228,16 @@ struct microVU { pxAssumeDev((prog.IRinfo.curPC & 1) == 0, "microVU recompiler: Upper instructions cannot have valid branch addresses."); return (((prog.IRinfo.curPC + 4) + (Imm11() * 2)) & progMemMask) * 4; } + + __ri void loadIreg(const xmm& reg, int xyzw) + { + xMOVSSZX(reg, ptr32[&getVI(REG_I)]); + if (!_XYZWss(xyzw)) xSHUF.PS(reg, reg, 0); + } + + void init(uint vuIndex); + void reset(); + void close(); }; // microVU rec structs @@ -232,9 +248,6 @@ extern __aligned16 microVU microVU1; int mVUdebugNow = 0; // Main Functions -static void mVUinit(int); -static void mVUreset(mV, VURegs* vuRegsPtr = NULL); -static void mVUclose(mV); static void mVUclear(mV, u32, u32); static void mVUresizeCache(mV, u32); static void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState); @@ -257,18 +270,3 @@ extern void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles); // recCall Function Pointer typedef void (__fastcall *mVUrecCall)(u32, u32); - -// Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files) -#include "microVU_Clamp.inl" -#include "microVU_Misc.inl" -#include "microVU_Log.inl" -#include "microVU_Analyze.inl" -#include "microVU_Alloc.inl" -#include "microVU_Upper.inl" -#include "microVU_Lower.inl" -#include "microVU_Tables.inl" -#include "microVU_Flags.inl" -#include "microVU_Branch.inl" -#include "microVU_Compile.inl" -#include "microVU_Execute.inl" -#include "microVU_Macro.inl" diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index 7f01b560e5..8acab8f704 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -110,19 +110,19 @@ __fi void mVUallocMFLAGb(mV, const x32& reg, int fInstance) { //xAND(reg, 0xffff); if (fInstance < 4) xMOV(ptr32[&mVU->macFlag[fInstance]], reg); // microVU - else xMOV(ptr32[&mVU->regs->VI[REG_MAC_FLAG].UL], reg); // macroVU + else xMOV(ptr32[&mVU->regs().VI[REG_MAC_FLAG].UL], reg); // macroVU } __fi void mVUallocCFLAGa(mV, const x32& reg, int fInstance) { if (fInstance < 4) xMOV(reg, ptr32[&mVU->clipFlag[fInstance]]); // microVU - else xMOV(reg, ptr32[&mVU->regs->VI[REG_CLIP_FLAG].UL]); // macroVU + else xMOV(reg, ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL]); // macroVU } __fi void mVUallocCFLAGb(mV, const x32& reg, int fInstance) { if (fInstance < 4) xMOV(ptr32[&mVU->clipFlag[fInstance]], reg); // microVU - else xMOV(ptr32[&mVU->regs->VI[REG_CLIP_FLAG].UL], reg); // macroVU + else xMOV(ptr32[&mVU->regs().VI[REG_CLIP_FLAG].UL], reg); // macroVU } //------------------------------------------------------------------ @@ -135,19 +135,19 @@ __ri void mVUallocVIa(mV, const x32& GPRreg, int _reg_, bool signext = false) xXOR(GPRreg, GPRreg); else if (signext) - xMOVSX(GPRreg, ptr16[&mVU->regs->VI[_reg_].SL]); + xMOVSX(GPRreg, ptr16[&mVU->regs().VI[_reg_].SL]); else - xMOVZX(GPRreg, ptr16[&mVU->regs->VI[_reg_].UL]); + xMOVZX(GPRreg, ptr16[&mVU->regs().VI[_reg_].UL]); } __ri void mVUallocVIb(mV, const x32& GPRreg, int _reg_) { if (mVUlow.backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch) - xMOVZX(gprT3, ptr16[&mVU->regs->VI[_reg_].UL]); + xMOVZX(gprT3, ptr16[&mVU->regs().VI[_reg_].UL]); xMOV (ptr32[&mVU->VIbackup], gprT3); } if (_reg_ == 0) { return; } - else if (_reg_ < 16) { xMOV(ptr16[&mVU->regs->VI[_reg_].UL], xRegister16(GPRreg.Id)); } + else if (_reg_ < 16) { xMOV(ptr16[&mVU->regs().VI[_reg_].UL], xRegister16(GPRreg.Id)); } } //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index ba0d8b6eb7..ad33e339cb 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -56,31 +56,31 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { // Save P/Q Regs if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe5); } - xMOVSS(ptr32[&mVU->regs->VI[REG_Q].UL], xmmPQ); + 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); + xMOVSS(ptr32[&mVU->regs().VI[REG_P].UL], xmmPQ); } // Save Flag Instances #if 1 // CHECK_MACROVU0 - Always on now - xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus)); + xMOV(ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL], getFlagReg(fStatus)); #else mVUallocSFLAGc(gprT1, gprT2, fStatus); - xMOV(ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL], gprT1); + xMOV(ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL], gprT1); #endif 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); + 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 xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag - xAND(ptr32[&mVU->regs->vifRegs->stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif + 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); + xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC); xJMP(mVU->exitFunct); } } @@ -137,12 +137,12 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { mVUendProgram(mVU, &mFC, 2); xForwardJump8 eJMP((JccComparisonType)JMPcc); incPC(1); // Set PC to First instruction of Non-Taken Side - xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], xPC); + xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC); xJMP(mVU->exitFunct); eJMP.SetTarget(); incPC(-4); // Go Back to Branch Opcode to get branchAddr iPC = branchAddr/4; - xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], xPC); + xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], xPC); xJMP(mVU->exitFunct); return; } @@ -190,7 +190,7 @@ void normJump(mV, microFlagCycles& mFC) { if (mVUup.eBit) { // E-bit Jump mVUendProgram(mVU, &mFC, 2); xMOV(gprT1, ptr32[&mVU->branch]); - xMOV(ptr32[&mVU->regs->VI[REG_TPC].UL], gprT1); + xMOV(ptr32[&mVU->regs().VI[REG_TPC].UL], gprT1); xJMP(mVU->exitFunct); } else normJumpCompile(mVU, mFC, 0); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index cf3d0510e4..8516e3628c 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -45,7 +45,7 @@ static void __fastcall mVUprintPC2(u32 PC) { Console.WriteLn("Block End PC = 0 // Used by mVUsetupRange static __fi void mVUcheckIsSame(mV) { if (mVU->prog.isSame == -1) { - mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs->Micro, mVU->microMemSize); + mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs().Micro, mVU->microMemSize); } if (mVU->prog.isSame == 0) { if (!isVU1) mVUcacheProg<0>(*mVU->prog.cur); @@ -126,7 +126,7 @@ static void doIbit(mV) { } else tempI = curI; - xMOV(ptr32[&mVU->regs->VI[REG_I].UL], tempI); + xMOV(ptr32[&mVU->regs().VI[REG_I].UL], tempI); incPC(1); } } @@ -328,7 +328,7 @@ static void mVUtestCycles(microVU* mVU) { xCMP(ptr32[&mVU->cycles], 0); xForwardJG32 skip; if (isVU0) { - // TEST32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); + // TEST32ItoM((uptr)&mVU->regs().flags, VUFLAG_MFLAGSET); // xFowardJZ32 vu0jmp; // xMOV(gprT2, (uptr)mVU); // xCALL(mVUwarning0); // VU0 is allowed early exit for COP2 Interlock Simulation @@ -394,7 +394,7 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) { // First Pass iPC = startPC / 4; mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range - mVU->regAlloc->reset(mVU->regs); // Reset regAlloc + mVU->regAlloc->reset(); // Reset regAlloc mVUinitFirstPass(mVU, pState, thisPtr); for (int branch = 0; mVUcount < endCount; mVUcount++) { incPC(1); @@ -433,7 +433,7 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) { u32 x = 0; for (; x < endCount; x++) { if (mVUinfo.isEOB) { handleBadOp(mVU, x); x = 0xffff; } - if (mVUup.mBit) { xOR(ptr32[&mVU->regs->flags], VUFLAG_MFLAGSET); } + if (mVUup.mBit) { xOR(ptr32[&mVU->regs().flags], VUFLAG_MFLAGSET); } if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(mVU); } else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); } else { doSwapOp(mVU); } diff --git a/pcsx2/x86/microVU_Execute.inl b/pcsx2/x86/microVU_Execute.inl index 610ca5b095..198ab530da 100644 --- a/pcsx2/x86/microVU_Execute.inl +++ b/pcsx2/x86/microVU_Execute.inl @@ -43,24 +43,24 @@ void mVUdispatcherA(mV) { // Load Regs #if 1 // CHECK_MACROVU0 - Always on now - xMOV(gprF0, ptr32[&mVU->regs->VI[REG_STATUS_FLAG].UL]); + xMOV(gprF0, ptr32[&mVU->regs().VI[REG_STATUS_FLAG].UL]); xMOV(gprF1, gprF0); xMOV(gprF2, gprF0); xMOV(gprF3, gprF0); #else - mVUallocSFLAGd((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, 1); + mVUallocSFLAGd((uptr)&mVU->regs().VI[REG_STATUS_FLAG].UL, 1); #endif - xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_MAC_FLAG].UL]); + xMOVAPS(xmmT1, ptr128[&mVU->regs().VI[REG_MAC_FLAG].UL]); xSHUF.PS(xmmT1, xmmT1, 0); xMOVAPS(ptr128[mVU->macFlag], xmmT1); - xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_CLIP_FLAG].UL]); + xMOVAPS(xmmT1, ptr128[&mVU->regs().VI[REG_CLIP_FLAG].UL]); xSHUF.PS(xmmT1, xmmT1, 0); xMOVAPS(ptr128[mVU->clipFlag], xmmT1); - xMOVAPS(xmmT1, ptr128[&mVU->regs->VI[REG_P].UL]); - xMOVAPS(xmmPQ, ptr128[&mVU->regs->VI[REG_Q].UL]); + xMOVAPS(xmmT1, ptr128[&mVU->regs().VI[REG_P].UL]); + xMOVAPS(xmmPQ, ptr128[&mVU->regs().VI[REG_Q].UL]); xSHUF.PS(xmmPQ, xmmT1, 0); // wzyx = PPQQ // Jump to Recompiled Code Block @@ -119,12 +119,12 @@ _mVUt void* __fastcall mVUexecute(u32 startPC, u32 cycles) { _mVUt void mVUcleanUp() { microVU* mVU = mVUx; //mVUprint("microVU: Program exited successfully!"); - //mVUprint("microVU: VF0 = {%x,%x,%x,%x}", mVU->regs->VF[0].UL[0], mVU->regs->VF[0].UL[1], mVU->regs->VF[0].UL[2], mVU->regs->VF[0].UL[3]); - //mVUprint("microVU: VI0 = %x", mVU->regs->VI[0].UL); + //mVUprint("microVU: VF0 = {%x,%x,%x,%x}", mVU->regs().VF[0].UL[0], mVU->regs().VF[0].UL[1], mVU->regs().VF[0].UL[2], mVU->regs().VF[0].UL[3]); + //mVUprint("microVU: VI0 = %x", mVU->regs().VI[0].UL); mVU->prog.x86ptr = x86Ptr; mVUcacheCheck(x86Ptr, mVU->prog.x86start, (uptr)(mVU->prog.x86end - mVU->prog.x86start)); mVU->cycles = mVU->totalCycles - mVU->cycles; - mVU->regs->cycle += mVU->cycles; + mVU->regs().cycle += mVU->cycles; cpuRegs.cycle += ((mVU->cycles < 3000) ? mVU->cycles : 3000) * EmuConfig.Speedhacks.VUCycleSteal; //static int ax = 0; ax++; //if (!(ax % 100000)) { diff --git a/pcsx2/x86/microVU_IR.h b/pcsx2/x86/microVU_IR.h index cbaed67c37..c56f53bc4f 100644 --- a/pcsx2/x86/microVU_IR.h +++ b/pcsx2/x86/microVU_IR.h @@ -172,36 +172,18 @@ struct microMapXMM { #define xmmTotal 7 // Don't allocate PQ? class microRegAlloc { -private: +protected: microMapXMM xmmMap[xmmTotal]; - VURegs* vuRegs; int counter; - int findFreeRegRec(int startIdx) { - for (int i = startIdx; i < xmmTotal; i++) { - if (!xmmMap[i].isNeeded) { - int x = findFreeRegRec(i+1); - if (x == -1) return i; - return ((xmmMap[i].count < xmmMap[x].count) ? i : x); - } - } - return -1; - } - int findFreeReg() { - for (int i = 0; i < xmmTotal; i++) { - if (!xmmMap[i].isNeeded && (xmmMap[i].VFreg < 0)) { - return i; // Reg is not needed and was a temp reg - } - } - int x = findFreeRegRec(0); - pxAssumeDev( x >= 0, "microVU register allocation failure!" ); - return x; - } + microVU* mVU; + + int findFreeRegRec(int startIdx); + int findFreeReg(); public: - microRegAlloc() { } - - void reset(VURegs* vuRegsPtr) { - vuRegs = vuRegsPtr; + microRegAlloc(microVU* _mVU); + + void reset() { for (int i = 0; i < xmmTotal; i++) { clearReg(i); } @@ -213,132 +195,14 @@ public: if (clearState) clearReg(i); } } + void clearReg(int regId); void clearReg(const xmm& reg) { clearReg(reg.Id); } - void clearReg(int regId) { - microMapXMM& clear( xmmMap[regId] ); - clear.VFreg = -1; - clear.count = 0; - clear.xyzw = 0; - clear.isNeeded = 0; - } void clearRegVF(int VFreg) { for (int i = 0; i < xmmTotal; i++) { if (xmmMap[i].VFreg == VFreg) clearReg(i); } } - void writeBackReg(const xmm& reg, bool invalidateRegs = 1) { - microMapXMM& write( xmmMap[reg.Id] ); - - if ((write.VFreg > 0) && write.xyzw) { // Reg was modified and not Temp or vf0 - if (write.VFreg == 33) xMOVSS(ptr32[&vuRegs->VI[REG_I].UL], reg); - else if (write.VFreg == 32) mVUsaveReg(reg, ptr[&vuRegs->ACC.UL[0]], write.xyzw, 1); - else mVUsaveReg(reg, ptr[&vuRegs->VF[write.VFreg].UL[0]], write.xyzw, 1); - if (invalidateRegs) { - for (int i = 0; i < xmmTotal; i++) { - microMapXMM& imap (xmmMap[i]); - if ((i == reg.Id) || imap.isNeeded) continue; - if (imap.VFreg == write.VFreg) { - if (imap.xyzw && imap.xyzw < 0xf) DevCon.Error("microVU Error: writeBackReg() [%d]", imap.VFreg); - clearReg(i); // Invalidate any Cached Regs of same vf Reg - } - } - } - if (write.xyzw == 0xf) { // Make Cached Reg if All Vectors were Modified - write.count = counter; - write.xyzw = 0; - write.isNeeded = 0; - return; - } - } - clearReg(reg); // Clear Reg - } - void clearNeeded(const xmm& reg) - { - if ((reg.Id < 0) || (reg.Id >= xmmTotal)) return; - - microMapXMM& clear (xmmMap[reg.Id]); - clear.isNeeded = 0; - if (clear.xyzw) { // Reg was modified - if (clear.VFreg > 0) { - int mergeRegs = 0; - if (clear.xyzw < 0xf) { mergeRegs = 1; } // Try to merge partial writes - for (int i = 0; i < xmmTotal; i++) { // Invalidate any other read-only regs of same vfReg - if (i == reg.Id) continue; - microMapXMM& imap (xmmMap[i]); - if (imap.VFreg == clear.VFreg) { - if (imap.xyzw && imap.xyzw < 0xf) DevCon.Error("microVU Error: clearNeeded() [%d]", imap.VFreg); - if (mergeRegs == 1) { - mVUmergeRegs(xmm(i), reg, clear.xyzw, 1); - imap.xyzw = 0xf; - imap.count = counter; - mergeRegs = 2; - } - else clearReg(i); - } - } - if (mergeRegs == 2) clearReg(reg); // Clear Current Reg if Merged - else if (mergeRegs) writeBackReg(reg); // Write Back Partial Writes if couldn't merge - } - else clearReg(reg); // If Reg was temp or vf0, then invalidate itself - } - } - const xmm& allocReg(int vfLoadReg = -1, int vfWriteReg = -1, int xyzw = 0, bool cloneWrite = 1) { - counter++; - if (vfLoadReg >= 0) { // Search For Cached Regs - for (int i = 0; i < xmmTotal; i++) { - const xmm& xmmi(xmm::GetInstance(i)); - microMapXMM& imap (xmmMap[i]); - if ((imap.VFreg == vfLoadReg) && (!imap.xyzw // Reg Was Not Modified - || (imap.VFreg && (imap.xyzw==0xf)))) { // Reg Had All Vectors Modified and != VF0 - int z = i; - if (vfWriteReg >= 0) { // Reg will be modified - if (cloneWrite) { // Clone Reg so as not to use the same Cached Reg - z = findFreeReg(); - const xmm& xmmz(xmm::GetInstance(z)); - writeBackReg(xmmz); - if (z!=i && xyzw==8) xMOVAPS (xmmz, xmmi); - else if (xyzw == 4) xPSHUF.D(xmmz, xmmi, 1); - else if (xyzw == 2) xPSHUF.D(xmmz, xmmi, 2); - else if (xyzw == 1) xPSHUF.D(xmmz, xmmi, 3); - else if (z != i) xMOVAPS (xmmz, xmmi); - imap.count = counter; // Reg i was used, so update counter - } - else { // Don't clone reg, but shuffle to adjust for SS ops - if ((vfLoadReg != vfWriteReg) || (xyzw != 0xf)) { writeBackReg(xmmi); } - if (xyzw == 4) xPSHUF.D(xmmi, xmmi, 1); - else if (xyzw == 2) xPSHUF.D(xmmi, xmmi, 2); - else if (xyzw == 1) xPSHUF.D(xmmi, xmmi, 3); - } - xmmMap[z].VFreg = vfWriteReg; - xmmMap[z].xyzw = xyzw; - } - xmmMap[z].count = counter; - xmmMap[z].isNeeded = 1; - return xmm::GetInstance(z); - } - } - } - int x = findFreeReg(); - const xmm& xmmx = xmm::GetInstance(x); - writeBackReg(xmmx); - - if (vfWriteReg >= 0) { // Reg Will Be Modified (allow partial reg loading) - if ((vfLoadReg == 0) && !(xyzw & 1)) { xPXOR(xmmx, xmmx); } - else if (vfLoadReg == 33) mVUloadIreg(xmmx, xyzw, vuRegs); - else if (vfLoadReg == 32) mVUloadReg (xmmx, ptr[&vuRegs->ACC.UL[0]], xyzw); - else if (vfLoadReg >= 0) mVUloadReg (xmmx, ptr[&vuRegs->VF[vfLoadReg].UL[0]], xyzw); - xmmMap[x].VFreg = vfWriteReg; - xmmMap[x].xyzw = xyzw; - } - else { // Reg Will Not Be Modified (always load full reg for caching) - if (vfLoadReg == 33) mVUloadIreg(xmmx, 0xf, vuRegs); - else if (vfLoadReg == 32) xMOVAPS(xmmx, ptr128[&vuRegs->ACC.UL[0]]); - else if (vfLoadReg >= 0) xMOVAPS(xmmx, ptr128[&vuRegs->VF[vfLoadReg].UL[0]]); - xmmMap[x].VFreg = vfLoadReg; - xmmMap[x].xyzw = 0; - } - xmmMap[x].count = counter; - xmmMap[x].isNeeded = 1; - return xmmx; - } + void writeBackReg(const xmm& reg, bool invalidateRegs = 1); + void clearNeeded(const xmm& reg); + const xmm& allocReg(int vfLoadReg = -1, int vfWriteReg = -1, int xyzw = 0, bool cloneWrite = 1); }; diff --git a/pcsx2/x86/microVU_IR.inl b/pcsx2/x86/microVU_IR.inl new file mode 100644 index 0000000000..f5613df531 --- /dev/null +++ b/pcsx2/x86/microVU_IR.inl @@ -0,0 +1,165 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + + +int microRegAlloc::findFreeRegRec(int startIdx) { + for (int i = startIdx; i < xmmTotal; i++) { + if (!xmmMap[i].isNeeded) { + int x = findFreeRegRec(i+1); + if (x == -1) return i; + return ((xmmMap[i].count < xmmMap[x].count) ? i : x); + } + } + return -1; +} +int microRegAlloc::findFreeReg() { + for (int i = 0; i < xmmTotal; i++) { + if (!xmmMap[i].isNeeded && (xmmMap[i].VFreg < 0)) { + return i; // Reg is not needed and was a temp reg + } + } + int x = findFreeRegRec(0); + pxAssumeDev( x >= 0, "microVU register allocation failure!" ); + return x; +} + +microRegAlloc::microRegAlloc(microVU* _mVU) { + mVU = _mVU; +} + +void microRegAlloc::clearReg(int regId) { + microMapXMM& clear( xmmMap[regId] ); + clear.VFreg = -1; + clear.count = 0; + clear.xyzw = 0; + clear.isNeeded = 0; +} +void microRegAlloc::writeBackReg(const xmm& reg, bool invalidateRegs) { + microMapXMM& write( xmmMap[reg.Id] ); + + if ((write.VFreg > 0) && write.xyzw) { // Reg was modified and not Temp or vf0 + if (write.VFreg == 33) xMOVSS(ptr32[&mVU->getVI(REG_I)], reg); + else if (write.VFreg == 32) mVUsaveReg(reg, ptr[&mVU->regs().ACC], write.xyzw, 1); + else mVUsaveReg(reg, ptr[&mVU->getVF(write.VFreg)], write.xyzw, 1); + if (invalidateRegs) { + for (int i = 0; i < xmmTotal; i++) { + microMapXMM& imap (xmmMap[i]); + if ((i == reg.Id) || imap.isNeeded) continue; + if (imap.VFreg == write.VFreg) { + if (imap.xyzw && imap.xyzw < 0xf) DevCon.Error("microVU Error: writeBackReg() [%d]", imap.VFreg); + clearReg(i); // Invalidate any Cached Regs of same vf Reg + } + } + } + if (write.xyzw == 0xf) { // Make Cached Reg if All Vectors were Modified + write.count = counter; + write.xyzw = 0; + write.isNeeded = 0; + return; + } + } + clearReg(reg); // Clear Reg +} +void microRegAlloc::clearNeeded(const xmm& reg) +{ + if ((reg.Id < 0) || (reg.Id >= xmmTotal)) return; + + microMapXMM& clear (xmmMap[reg.Id]); + clear.isNeeded = 0; + if (clear.xyzw) { // Reg was modified + if (clear.VFreg > 0) { + int mergeRegs = 0; + if (clear.xyzw < 0xf) { mergeRegs = 1; } // Try to merge partial writes + for (int i = 0; i < xmmTotal; i++) { // Invalidate any other read-only regs of same vfReg + if (i == reg.Id) continue; + microMapXMM& imap (xmmMap[i]); + if (imap.VFreg == clear.VFreg) { + if (imap.xyzw && imap.xyzw < 0xf) DevCon.Error("microVU Error: clearNeeded() [%d]", imap.VFreg); + if (mergeRegs == 1) { + mVUmergeRegs(xmm(i), reg, clear.xyzw, 1); + imap.xyzw = 0xf; + imap.count = counter; + mergeRegs = 2; + } + else clearReg(i); + } + } + if (mergeRegs == 2) clearReg(reg); // Clear Current Reg if Merged + else if (mergeRegs) writeBackReg(reg); // Write Back Partial Writes if couldn't merge + } + else clearReg(reg); // If Reg was temp or vf0, then invalidate itself + } +} +const xmm& microRegAlloc::allocReg(int vfLoadReg, int vfWriteReg, int xyzw, bool cloneWrite) { + counter++; + if (vfLoadReg >= 0) { // Search For Cached Regs + for (int i = 0; i < xmmTotal; i++) { + const xmm& xmmi(xmm::GetInstance(i)); + microMapXMM& imap (xmmMap[i]); + if ((imap.VFreg == vfLoadReg) && (!imap.xyzw // Reg Was Not Modified + || (imap.VFreg && (imap.xyzw==0xf)))) { // Reg Had All Vectors Modified and != VF0 + int z = i; + if (vfWriteReg >= 0) { // Reg will be modified + if (cloneWrite) { // Clone Reg so as not to use the same Cached Reg + z = findFreeReg(); + const xmm& xmmz(xmm::GetInstance(z)); + writeBackReg(xmmz); + if (z!=i && xyzw==8) xMOVAPS (xmmz, xmmi); + else if (xyzw == 4) xPSHUF.D(xmmz, xmmi, 1); + else if (xyzw == 2) xPSHUF.D(xmmz, xmmi, 2); + else if (xyzw == 1) xPSHUF.D(xmmz, xmmi, 3); + else if (z != i) xMOVAPS (xmmz, xmmi); + imap.count = counter; // Reg i was used, so update counter + } + else { // Don't clone reg, but shuffle to adjust for SS ops + if ((vfLoadReg != vfWriteReg) || (xyzw != 0xf)) { writeBackReg(xmmi); } + if (xyzw == 4) xPSHUF.D(xmmi, xmmi, 1); + else if (xyzw == 2) xPSHUF.D(xmmi, xmmi, 2); + else if (xyzw == 1) xPSHUF.D(xmmi, xmmi, 3); + } + xmmMap[z].VFreg = vfWriteReg; + xmmMap[z].xyzw = xyzw; + } + xmmMap[z].count = counter; + xmmMap[z].isNeeded = 1; + return xmm::GetInstance(z); + } + } + } + int x = findFreeReg(); + const xmm& xmmx = xmm::GetInstance(x); + writeBackReg(xmmx); + + if (vfWriteReg >= 0) { // Reg Will Be Modified (allow partial reg loading) + if ((vfLoadReg == 0) && !(xyzw & 1)) { xPXOR(xmmx, xmmx); } + else if (vfLoadReg == 33) mVU->loadIreg(xmmx, xyzw); + else if (vfLoadReg == 32) mVUloadReg (xmmx, ptr[&mVU->regs().ACC], xyzw); + else if (vfLoadReg >= 0) mVUloadReg (xmmx, ptr[&mVU->getVF(vfLoadReg)], xyzw); + xmmMap[x].VFreg = vfWriteReg; + xmmMap[x].xyzw = xyzw; + } + else { // Reg Will Not Be Modified (always load full reg for caching) + if (vfLoadReg == 33) mVU->loadIreg(xmmx, 0xf); + else if (vfLoadReg == 32) xMOVAPS(xmmx, ptr128[&mVU->regs().ACC]); + else if (vfLoadReg >= 0) xMOVAPS(xmmx, ptr128[&mVU->getVF(vfLoadReg)]); + xmmMap[x].VFreg = vfLoadReg; + xmmMap[x].xyzw = 0; + } + xmmMap[x].count = counter; + xmmMap[x].isNeeded = 1; + return xmmx; +} diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 3fcd9b9d84..51777c337e 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -778,7 +778,7 @@ mVUop(mVU_MTIR) { mVUop(mVU_ILW) { pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); } pass2 { - xAddressVoid ptr(mVU->regs->Mem + offsetSS); + xAddressVoid ptr(mVU->regs().Mem + offsetSS); if (_Is_) { mVUallocVIa(mVU, gprT2, _Is_); xADD(gprT2, _Imm11_); @@ -796,7 +796,7 @@ mVUop(mVU_ILW) { mVUop(mVU_ILWR) { pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg2(_It_, mVUlow.VI_write, 4); } pass2 { - xAddressVoid ptr(mVU->regs->Mem + offsetSS); + xAddressVoid ptr(mVU->regs().Mem + offsetSS); if (_Is_) { mVUallocVIa(mVU, gprT2, _Is_); mVUaddrFix (mVU, gprT2); @@ -815,7 +815,7 @@ mVUop(mVU_ILWR) { mVUop(mVU_ISW) { pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_Is_) { mVUallocVIa(mVU, gprT2, _Is_); xADD(gprT2, _Imm11_); @@ -836,7 +836,7 @@ mVUop(mVU_ISW) { mVUop(mVU_ISWR) { pass1 { analyzeVIreg1(_Is_, mVUlow.VI_read[0]); analyzeVIreg1(_It_, mVUlow.VI_read[1]); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_Is_) { mVUallocVIa(mVU, gprT2, _Is_); mVUaddrFix (mVU, gprT2); @@ -858,7 +858,7 @@ mVUop(mVU_ISWR) { mVUop(mVU_LQ) { pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 0); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_Is_) { mVUallocVIa(mVU, gprT2, _Is_); xADD(gprT2, _Imm11_); @@ -877,7 +877,7 @@ mVUop(mVU_LQ) { mVUop(mVU_LQD) { pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_Is_) { mVUallocVIa(mVU, gprT2, _Is_); xSUB(gprT2b, 1); @@ -897,7 +897,7 @@ mVUop(mVU_LQD) { mVUop(mVU_LQI) { pass1 { mVUanalyzeLQ(mVU, _Ft_, _Is_, 1); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_Is_) { mVUallocVIa(mVU, gprT1, _Is_); xMOV(gprT2, gprT1); @@ -922,7 +922,7 @@ mVUop(mVU_LQI) { mVUop(mVU_SQ) { pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 0); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_It_) { mVUallocVIa(mVU, gprT2, _It_); xADD(gprT2, _Imm11_); @@ -941,7 +941,7 @@ mVUop(mVU_SQ) { mVUop(mVU_SQD) { pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_It_) { mVUallocVIa(mVU, gprT2, _It_); xSUB(gprT2b, 1); @@ -959,7 +959,7 @@ mVUop(mVU_SQD) { mVUop(mVU_SQI) { pass1 { mVUanalyzeSQ(mVU, _Fs_, _It_, 1); } pass2 { - xAddressVoid ptr(mVU->regs->Mem); + xAddressVoid ptr(mVU->regs().Mem); if (_It_) { mVUallocVIa(mVU, gprT1, _It_); xMOV(gprT2, gprT1); @@ -1069,7 +1069,7 @@ mVUop(mVU_WAITQ) { mVUop(mVU_XTOP) { pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); } pass2 { - xMOVZX(gprT1, ptr16[&mVU->regs->vifRegs->top]); + xMOVZX(gprT1, ptr16[&mVU->getVifRegs().top]); mVUallocVIb(mVU, gprT1, _It_); } pass3 { mVUlog("XTOP vi%02d", _Ft_); } @@ -1078,7 +1078,7 @@ mVUop(mVU_XTOP) { mVUop(mVU_XITOP) { pass1 { if (!_It_) { mVUlow.isNOP = 1; } analyzeVIreg2(_It_, mVUlow.VI_write, 1); } pass2 { - xMOVZX(gprT1, ptr16[&mVU->regs->vifRegs->itop]); + xMOVZX(gprT1, ptr16[&mVU->getVifRegs().itop]); xAND(gprT1, isVU1 ? 0x3ff : 0xff); mVUallocVIb(mVU, gprT1, _It_); } @@ -1094,7 +1094,7 @@ extern bool SIGNAL_IMR_Pending; void __fastcall mVU_XGKICK_(u32 addr) { addr &= 0x3ff; - u8* data = microVU1.regs->Mem + (addr*16); + u8* data = vuRegs[1].Mem + (addr*16); u32 diff = 0x400 - addr; u32 size; @@ -1128,11 +1128,11 @@ void __fastcall mVU_XGKICK_(u32 addr) { if (size > diff) { //DevCon.Status("XGkick Wrap!"); - memcpy_qwc(pDest, microVU1.regs->Mem + (addr*16), diff); - memcpy_qwc(pDest+(diff*16), microVU1.regs->Mem, size-diff); + memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), diff); + memcpy_qwc(pDest+(diff*16), vuRegs[1].Mem, size-diff); } else { - memcpy_qwc(pDest, microVU1.regs->Mem + (addr*16), size); + memcpy_qwc(pDest, vuRegs[1].Mem + (addr*16), size); } //if(!gifRegs->stat.P1Q) CPU_INT(28, 128); gifRegs->stat.P1Q = true; diff --git a/pcsx2/x86/microVU_Macro.inl b/pcsx2/x86/microVU_Macro.inl index a266c6019b..ee2ae5c7ab 100644 --- a/pcsx2/x86/microVU_Macro.inl +++ b/pcsx2/x86/microVU_Macro.inl @@ -18,6 +18,8 @@ extern void _vu0WaitMicro(); extern void _vu0FinishMicro(); +static VURegs& vu0Regs = vuRegs[0]; + //------------------------------------------------------------------ // Macro VU - Helper Macros / Functions //------------------------------------------------------------------ @@ -34,9 +36,9 @@ void setupMacroOp(int mode, const char* opName) { microVU0.code = cpuRegs.code; memset(µVU0.prog.IRinfo.info[0], 0, sizeof(microVU0.prog.IRinfo.info[0])); iFlushCall(FLUSH_EVERYTHING); - microVU0.regAlloc->reset(microVU0.regs); + microVU0.regAlloc->reset(); if (mode & 0x01) { // Q-Reg will be Read - xMOVSSZX(xmmPQ, ptr32[µVU0.regs->VI[REG_Q].UL]); + xMOVSSZX(xmmPQ, ptr32[&vu0Regs.VI[REG_Q].UL]); } if (mode & 0x08) { // Clip Instruction microVU0.prog.IRinfo.info[0].cFlag.write = 0xff; @@ -49,16 +51,16 @@ void setupMacroOp(int mode, const char* opName) { microVU0.prog.IRinfo.info[0].sFlag.lastWrite = 0; microVU0.prog.IRinfo.info[0].mFlag.doFlag = 1; microVU0.prog.IRinfo.info[0].mFlag.write = 0xff; - xMOV(gprF0, ptr32[µVU0.regs->VI[REG_STATUS_FLAG].UL]); + xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); } } void endMacroOp(int mode) { if (mode & 0x02) { // Q-Reg was Written To - xMOVSS(ptr32[µVU0.regs->VI[REG_Q].UL], xmmPQ); + xMOVSS(ptr32[&vu0Regs.VI[REG_Q].UL], xmmPQ); } if (mode & 0x10) { // Status/Mac Flags were Updated - xMOV(ptr32[µVU0.regs->VI[REG_STATUS_FLAG].UL], gprF0); + xMOV(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], gprF0); } microVU0.regAlloc->flushAll(); microVU0.cop2 = 0; @@ -267,10 +269,10 @@ static void recCFC2() { iFlushCall(FLUSH_EVERYTHING); if (_Rd_ == REG_STATUS_FLAG) { // Normalize Status Flag - xMOV(gprF0, ptr32[µVU0.regs->VI[REG_STATUS_FLAG].UL]); + xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); mVUallocSFLAGc(eax, gprF0, 0); } - else xMOV(eax, ptr32[µVU0.regs->VI[_Rd_].UL]); + else xMOV(eax, ptr32[&vu0Regs.VI[_Rd_].UL]); // FixMe: Should R-Reg have upper 9 bits 0? xMOV(ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]], eax); @@ -298,14 +300,14 @@ static void recCTC2() { case REG_R: xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); xOR (eax, 0x3f800000); - xMOV(ptr32[µVU0.regs->VI[REG_R].UL], eax); + xMOV(ptr32[&vu0Regs.VI[REG_R].UL], eax); break; case REG_STATUS_FLAG: if (_Rt_) { // Denormalizes flag into gprF1 mVUallocSFLAGd(&cpuRegs.GPR.r[_Rt_].UL[0], 0); - xMOV(ptr32[µVU0.regs->VI[_Rd_].UL], gprF1); + xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], gprF1); } - else xMOV(ptr32[µVU0.regs->VI[_Rd_].UL], 0); + else xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], 0); break; case REG_CMSAR1: // Execute VU1 Micro SubRoutine if (_Rt_) { @@ -316,7 +318,7 @@ static void recCTC2() { break; case REG_FBRST: if (!_Rt_) { - xMOV(ptr32[µVU0.regs->VI[REG_FBRST].UL], 0); + xMOV(ptr32[&vu0Regs.VI[REG_FBRST].UL], 0); return; } else xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); @@ -325,12 +327,12 @@ static void recCTC2() { TEST_FBRST_RESET(vu1ResetRegs, 1); xAND(eax, 0x0C0C); - xMOV(ptr32[µVU0.regs->VI[REG_FBRST].UL], eax); + xMOV(ptr32[&vu0Regs.VI[REG_FBRST].UL], eax); break; default: // Executing vu0 block here fixes the intro of Ratchet and Clank // sVU's COP2 has a comment that "Donald Duck" needs this too... - if (_Rd_) _eeMoveGPRtoM((uptr)µVU0.regs->VI[_Rd_].UL, _Rt_); + if (_Rd_) _eeMoveGPRtoM((uptr)&vu0Regs.VI[_Rd_].UL, _Rt_); xMOV(ecx, (uptr)CpuVU0); xCALL(BaseVUmicroCPU::ExecuteBlockJIT); break; @@ -347,7 +349,7 @@ static void recQMFC2() { // FixMe: For some reason this line is needed or else games break: _eeOnWriteReg(_Rt_, 0); - xMOVAPS(xmmT1, ptr128[µVU0.regs->VF[_Rd_]]); + xMOVAPS(xmmT1, ptr128[&vu0Regs.VF[_Rd_]]); xMOVAPS(ptr128[&cpuRegs.GPR.r[_Rt_]], xmmT1); } @@ -359,7 +361,7 @@ static void recQMTC2() { iFlushCall(FLUSH_EVERYTHING); xMOVAPS(xmmT1, ptr128[&cpuRegs.GPR.r[_Rt_]]); - xMOVAPS(ptr128[µVU0.regs->VF[_Rd_]], xmmT1); + xMOVAPS(ptr128[&vu0Regs.VF[_Rd_]], xmmT1); } //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index d80ae2856b..f66ff3d71d 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -205,7 +205,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #define isEvilBlock (mVUpBlock->pState.blockType == 2) #define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch) #define xPC ((iPC / 2) * 8) -#define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC] +#define curI ((u32*)mVU->regs().Micro)[iPC] //mVUcurProg.data[iPC] #define setCode() { mVU->code = curI; } #if 0 @@ -222,7 +222,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8) #define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) #define cmpOffset(x) ((u8*)&(((u8*)x)[it[0].start])) -#define Rmem &mVU->regs->VI[REG_R].UL +#define Rmem &mVU->regs().VI[REG_R].UL #define aWrap(x, m) ((x > m) ? 0 : x) #define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4)))) #define clampE CHECK_VU_EXTRA_OVERFLOW @@ -325,4 +325,3 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); extern void mVUmergeRegs(const xmm& dest, const xmm& src, int xyzw, bool modXYZW=false); extern void mVUsaveReg(const xmm& reg, xAddressVoid ptr, int xyzw, bool modXYZW); extern void mVUloadReg(const xmm& reg, xAddressVoid ptr, int xyzw); -extern void mVUloadIreg(const xmm& reg, int xyzw, VURegs* vuRegs); \ No newline at end of file diff --git a/pcsx2/x86/sVU_Lower.cpp b/pcsx2/x86/sVU_Lower.cpp index 2ea05d0986..42c67069c0 100644 --- a/pcsx2/x86/sVU_Lower.cpp +++ b/pcsx2/x86/sVU_Lower.cpp @@ -1948,7 +1948,7 @@ void recVUMI_XITOP( VURegs *VU, int info ) if (_It_ == 0) return; //Console.WriteLn("recVUMI_XITOP"); itreg = ALLOCVI(_It_, MODE_WRITE); - MOVZX32M16toR( itreg, (uptr)&VU->vifRegs->itop ); + MOVZX32M16toR( itreg, (uptr)&VU->GetVifRegs().itop ); } //------------------------------------------------------------------ @@ -1962,7 +1962,7 @@ void recVUMI_XTOP( VURegs *VU, int info ) if ( _It_ == 0 ) return; //Console.WriteLn("recVUMI_XTOP"); itreg = ALLOCVI(_It_, MODE_WRITE); - MOVZX32M16toR( itreg, (uptr)&VU->vifRegs->top ); + MOVZX32M16toR( itreg, (uptr)&VU->GetVifRegs().top ); } //------------------------------------------------------------------ diff --git a/pcsx2/x86/sVU_Micro.h b/pcsx2/x86/sVU_Micro.h index 6b0cb2b740..0b78827d98 100644 --- a/pcsx2/x86/sVU_Micro.h +++ b/pcsx2/x86/sVU_Micro.h @@ -19,9 +19,6 @@ extern u32 vudump; -#define VU0_MEMSIZE 0x1000 -#define VU1_MEMSIZE 0x4000 - u32 GetVIAddr(VURegs * VU, int reg, int read, int info); // returns the correct VI addr void recUpdateFlags(VURegs * VU, int reg, int info); diff --git a/pcsx2/x86/sVU_zerorec.cpp b/pcsx2/x86/sVU_zerorec.cpp index 173c612bd4..5cb0c98c08 100644 --- a/pcsx2/x86/sVU_zerorec.cpp +++ b/pcsx2/x86/sVU_zerorec.cpp @@ -2750,7 +2750,7 @@ static void SuperVURecompile() pxAssert(pchild->blocks.size() == 0); AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag - AND32ItoM((uptr)&VU->vifRegs->stat, ~VIF1_STAT_VEW); + AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW); MOV32ItoM((uptr)&VU->VI[REG_TPC], pchild->endpc); JMP32((uptr)SuperVUEndProgram - ((uptr)x86Ptr + 5)); @@ -3023,7 +3023,7 @@ void VuBaseBlock::Recompile() _freeXMMregs(); _freeX86regs(); AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag - AND32ItoM((uptr)&VU->vifRegs->stat, ~VIF1_STAT_VEW); + AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW); if (!branch) MOV32ItoM((uptr)&VU->VI[REG_TPC], endpc); @@ -4680,12 +4680,8 @@ void recSuperVU1::Execute(u32 cycles) // [TODO] Debugging pre- and post- hooks? - if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { - Console.Error("VU1 memory overflow!!: %x", VU1.VI[REG_TPC].UL); - } - do { // while loop needed since not always will return finished - SuperVUExecuteProgram(VU1.VI[REG_TPC].UL & 0x3fff, 1); + SuperVUExecuteProgram(VU1.VI[REG_TPC].UL & VU1_PROGMASK, 1); } while( VU0.VI[REG_VPU_STAT].UL&0x100 ); }