diff --git a/common/build/Utilities/Utilities.cbp b/common/build/Utilities/Utilities.cbp
index 585bc4c499..cfb00c78c8 100644
--- a/common/build/Utilities/Utilities.cbp
+++ b/common/build/Utilities/Utilities.cbp
@@ -155,6 +155,8 @@
+
+
@@ -200,6 +202,7 @@
+
diff --git a/common/build/Utilities/utilities.vcproj b/common/build/Utilities/utilities.vcproj
index 6d7bf5ee1f..f14e0f9ff9 100644
--- a/common/build/Utilities/utilities.vcproj
+++ b/common/build/Utilities/utilities.vcproj
@@ -291,6 +291,10 @@
RelativePath="..\..\src\Utilities\StringHelpers.cpp"
>
+
+
@@ -417,6 +421,10 @@
RelativePath="..\..\include\Utilities\MemcpyFast.h"
>
+
+
diff --git a/common/include/Utilities/Dependencies.h b/common/include/Utilities/Dependencies.h
index 98b3e7e8a9..69018be958 100644
--- a/common/include/Utilities/Dependencies.h
+++ b/common/include/Utilities/Dependencies.h
@@ -160,7 +160,7 @@ public:
~ScopedBool() throw()
{
- m_boolme = false;
+ *m_boolme = false;
}
};
@@ -177,6 +177,19 @@ public:
#include "Pcsx2Defs.h"
+static const sptr _64kb = 0x10000;
+static const sptr _16kb = _64kb / 4;
+static const sptr _128kb = _64kb * 2;
+static const sptr _256kb = _128kb * 2;
+
+static const s64 _1mb = 0x100000;
+static const s64 _8mb = _1mb * 8;
+static const s64 _16mb = _1mb * 16;
+static const s64 _64mb = _1mb * 64;
+static const s64 _256mb = _1mb * 256;
+static const s64 _1gb = _256mb * 4;
+
+
// ===========================================================================================
// i18n/Translation Feature Set!
// ===========================================================================================
diff --git a/common/include/Utilities/MemsetFast.inl b/common/include/Utilities/MemsetFast.inl
new file mode 100644
index 0000000000..64b4a91266
--- /dev/null
+++ b/common/include/Utilities/MemsetFast.inl
@@ -0,0 +1,85 @@
+/* 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
+
+#include
+
+#define StoreDestIdx(idx) case idx: _mm_store_ps(&destxmm[idx-1][0], srcreg)
+
+ template< u8 data >
+__noinline void memset_sse_a( void* dest, const size_t size )
+{
+ const uint MZFqwc = size / 16;
+
+ pxAssert( (size & 0xf) == 0 );
+
+ __m128 srcreg;
+
+ if (data != 0)
+ {
+ static __aligned16 const u8 loadval[8] = { data,data,data,data,data,data,data,data };
+ srcreg = _mm_loadh_pi( _mm_load_ps( (float*)loadval ), (__m64*)loadval );
+ }
+ else
+ srcreg = _mm_setzero_ps();
+
+ float (*destxmm)[4] = (float(*)[4])dest;
+
+ switch( MZFqwc & 0x07 )
+ {
+ StoreDestIdx(0x07);
+ StoreDestIdx(0x06);
+ StoreDestIdx(0x05);
+ StoreDestIdx(0x04);
+ StoreDestIdx(0x03);
+ StoreDestIdx(0x02);
+ StoreDestIdx(0x01);
+ }
+
+ destxmm += (MZFqwc & 0x07);
+ for( uint i=0; i( dest, size );
+}
+
+#undef StoreDestIdx
+
+template< u8 data, typename T >
+__noinline void memset_sse_a( T& dest )
+{
+ C_ASSERT( (sizeof(dest) & 0xf) == 0 );
+ memset_sse_a( &dest, sizeof(dest) );
+}
+
+template< typename T >
+void memzero_sse_a( T& dest )
+{
+ C_ASSERT( (sizeof(dest) & 0xf) == 0 );
+ memset_sse_a<0>( &dest, sizeof(dest) );
+}
diff --git a/pcsx2/System/PageFaultSource.h b/common/include/Utilities/PageFaultSource.h
similarity index 66%
rename from pcsx2/System/PageFaultSource.h
rename to common/include/Utilities/PageFaultSource.h
index 94cc9a0bd8..bf64331fe2 100644
--- a/pcsx2/System/PageFaultSource.h
+++ b/common/include/Utilities/PageFaultSource.h
@@ -13,6 +13,8 @@
* If not, see .
*/
+// [TODO] Rename this file to VirtualMemory.h !!
+
#pragma once
// =====================================================================================================
@@ -20,8 +22,9 @@
// =====================================================================================================
// Win32 platforms use the SEH model: __try {} __except {}
// Linux platforms use the POSIX Signals model: sigaction()
+// [TODO] OS-X (Darwin) platforms should use the Mach exception model (not implemented)
-#include "Utilities/EventSource.h"
+#include "EventSource.h"
struct PageFaultInfo
{
@@ -125,9 +128,11 @@ public:
Free();
}
- void* Reserve( uint size, uptr base = 0, uptr upper_bounds = 0 );
- void Reset();
- void Free();
+ virtual void* Reserve( uint size, uptr base = 0, uptr upper_bounds = 0 );
+ virtual void Reset();
+ virtual void Free();
+
+ bool IsOk() const { return m_baseptr != NULL; }
uptr GetReserveSizeInBytes() const { return m_reserved * __pagesize; }
uptr GetReserveSizeInPages() const { return m_reserved; }
@@ -155,16 +160,58 @@ protected:
};
// --------------------------------------------------------------------------------------
-// RecompiledCodeReserve
+// SpatialArrayReserve
// --------------------------------------------------------------------------------------
-class RecompiledCodeReserve : public BaseVirtualMemoryReserve
+// A spatial array is one where large areas of the memory reserve will remain unused during
+// process execution. Only areas put to use will be committed to virtual memory.
+//
+// Spatial array efficiency depends heavily on selecting the right parameters for the array's
+// primary intended use. Memory in a spatial array is arranged by blocks, with each block
+// containing some number of pages (pages are 4096 bytes each on most platforms). When the
+// array is accessed, the entire block containing the addressed memory will be committed at
+// once. Blocks can be a single page in size (4096 bytes), though this is highly discouraged
+// due to overhead and fragmentation penalties.
+//
+// Balancing block sizes:
+// Larger blocks are good for reducing memory fragmentation and block-tracking overhead, but
+// can also result in a lot of otherwise unused memory being committed to memory. Smaller
+// blocks are good for arrays that will tend toward more sequential behavior, as they reduce
+// the amount of unused memory being committed. However, since every block requires a
+// tracking entry, assigning small blocks to a very large array can result in quite a bit of
+// unwanted overhead. Furthermore, if the array is accessed randomly, system physical memory
+// will become very fragmented, which will also hurt performance.
+//
+// By default, the base block size is based on a heuristic that balances the size of the spatial
+// array reserve against a best-guess performance profile for the target platform.
+//
+class SpatialArrayReserve : public BaseVirtualMemoryReserve
{
+ typedef BaseVirtualMemoryReserve __parent;
+
protected:
public:
- RecompiledCodeReserve( const wxString& name, uint defCommit = 0 );
+ SpatialArrayReserve( const wxString& name, uint defCommit = 0 );
+
+ virtual void* Reserve( uint size, uptr base = 0, uptr upper_bounds = 0 );
+
void OnCommittedBlock( void* block );
void OnOutOfMemory( const Exception::OutOfMemory& ex, void* blockptr, bool& handled );
+
+ // This method allows the programmer to specify the block size of the array as a function
+ // of its reserved size. This function *must* be called *after* the reserve has been made.
+ // Calls to this function prior to initializing the reserve will be ignored (and will
+ // generate an assertion in debug builds).
+ SpatialArrayReserve& SetBlockCount( uint blocks );
+
+ // Sets the block size via pages (pages are defined by the __pagesize global, which is
+ // typically 4096).
+ SpatialArrayReserve& SetBlockSizeInPages( uint bytes );
+
+ // This method assigns the block size of the spatial array, in bytes. The actual size of
+ // each block will be rounded up to the nearest page size. The resulting size is returned.
+ uint SetBlockSize( uint bytes );
+
operator void*() { return m_baseptr; }
operator const void*() const { return m_baseptr; }
@@ -190,7 +237,6 @@ extern int SysPageFaultExceptionFilter(struct _EXCEPTION_POINTERS* eps);
# error PCSX2 - Unsupported operating system platform.
#endif
-
extern void InstallSignalHandler();
extern SrcType_PageFault* Source_PageFault;
diff --git a/common/include/Utilities/Path.h b/common/include/Utilities/Path.h
index 351e99d851..334dc2bca2 100644
--- a/common/include/Utilities/Path.h
+++ b/common/include/Utilities/Path.h
@@ -101,6 +101,7 @@ public:
wxFileName operator+( const wxFileName& right ) const { return Combine( right ); }
wxDirName operator+( const wxDirName& right ) const { return Combine( right ); }
+ wxFileName operator+( const wxString& right ) const { return Combine( wxFileName(right) ); }
bool operator==(const wxDirName& filename) const { return SameAs(filename); }
bool operator!=(const wxDirName& filename) const { return !SameAs(filename); }
@@ -121,7 +122,7 @@ public:
// --------------------------------------------------------------------------------------
// Cross-platform utilities for manipulation of paths and filenames. Mostly these fall
// back on wxWidgets APIs internally, but are still helpful because some of wx's file stuff
-// has minor glitches, or requies sloppy wxFileName typecasting.
+// has minor glitches, or requires sloppy wxFileName typecasting.
//
namespace Path
{
diff --git a/common/src/Utilities/CMakeLists.txt b/common/src/Utilities/CMakeLists.txt
index 72c51a5a53..a659c5b4c0 100644
--- a/common/src/Utilities/CMakeLists.txt
+++ b/common/src/Utilities/CMakeLists.txt
@@ -121,6 +121,7 @@ set(UtilitiesSources
ThreadingDialogs.cpp
ThreadTools.cpp
vssprintf.cpp
+ VirtualMemory.cpp
wxAppWithHelpers.cpp
wxGuiTools.cpp
wxHelpers.cpp
@@ -145,7 +146,9 @@ set(UtilitiesHeaders
../../include/Utilities/HashMap.h
../../include/Utilities/lnx_memzero.h
../../include/Utilities/MemcpyFast.h
+ ../../include/Utilities/MemsetFast.h
../../include/Utilities/Path.h
+ ../../include/Utilities/PageFaultSource.h
../../include/Utilities/pxCheckBox.h
../../include/Utilities/pxRadioPanel.h
../../include/Utilities/pxStaticText.h
diff --git a/common/src/Utilities/PathUtils.cpp b/common/src/Utilities/PathUtils.cpp
index 800576b76e..3b6daaa2ff 100644
--- a/common/src/Utilities/PathUtils.cpp
+++ b/common/src/Utilities/PathUtils.cpp
@@ -136,7 +136,7 @@ wxString Path::Combine( const wxDirName& srcPath, const wxFileName& srcFile )
wxString Path::Combine( const wxString& srcPath, const wxDirName& srcFile )
{
- return ((wxDirName)srcPath + srcFile).ToString();
+ return (wxDirName( srcPath ) + srcFile).ToString();
}
// Replaces the extension of the file with the one given.
diff --git a/common/src/Utilities/VirtualMemory.cpp b/common/src/Utilities/VirtualMemory.cpp
new file mode 100644
index 0000000000..8eab5a1edc
--- /dev/null
+++ b/common/src/Utilities/VirtualMemory.cpp
@@ -0,0 +1,203 @@
+/* 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 .
+ */
+
+#include "PrecompiledHeader.h"
+
+#include "PageFaultSource.h"
+#include "EventSource.inl"
+#include "MemsetFast.inl"
+
+template class EventSource< IEventListener_PageFault >;
+
+SrcType_PageFault* Source_PageFault = NULL;
+
+EventListener_PageFault::EventListener_PageFault()
+{
+ pxAssume(Source_PageFault);
+ Source_PageFault->Add( *this );
+}
+
+EventListener_PageFault::~EventListener_PageFault() throw()
+{
+ if (Source_PageFault)
+ Source_PageFault->Remove( *this );
+}
+
+void SrcType_PageFault::Dispatch( const PageFaultInfo& params )
+{
+ m_handled = false;
+ _parent::Dispatch( params );
+}
+
+void SrcType_PageFault::_DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt )
+{
+ do {
+ (*iter)->DispatchEvent( evt, m_handled );
+ } while( (++iter != iend) && !m_handled );
+}
+
+// --------------------------------------------------------------------------------------
+// BaseVirtualMemoryReserve (implementations)
+// --------------------------------------------------------------------------------------
+
+BaseVirtualMemoryReserve::BaseVirtualMemoryReserve( const wxString& name )
+ : Name( name )
+{
+ m_commited = 0;
+ m_reserved = 0;
+ m_baseptr = NULL;
+ m_block_size = __pagesize;
+ m_prot_mode = PageAccess_None();
+}
+
+// Parameters:
+// upper_bounds - criteria that must be met for the allocation to be valid.
+// If the OS refuses to allocate the memory below the specified address, the
+// object will fail to initialize and an exception will be thrown.
+void* BaseVirtualMemoryReserve::Reserve( uint size, uptr base, uptr upper_bounds )
+{
+ if (!pxAssertDev( m_baseptr == NULL, "(VirtualMemoryReserve) Invalid object state; object has already been reserved." ))
+ return m_baseptr;
+
+ m_reserved = (size + __pagesize-4) / __pagesize;
+ uptr reserved_bytes = m_reserved * __pagesize;
+
+ m_baseptr = (void*)HostSys::MmapReserve(base, reserved_bytes);
+
+ if (!m_baseptr && (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds)))
+ {
+ if (base)
+ {
+ DevCon.Warning( L"%s: address 0x%08x is unavailable; trying OS-selected address instead.", Name.c_str(), base );
+
+ // Let's try again at an OS-picked memory area, and then hope it meets needed
+ // boundschecking criteria below.
+ SafeSysMunmap( m_baseptr, reserved_bytes );
+ m_baseptr = (void*)HostSys::MmapReserve( NULL, reserved_bytes );
+ }
+
+ if ((upper_bounds != 0) && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))
+ {
+ SafeSysMunmap( m_baseptr, reserved_bytes );
+ // returns null, caller should throw an exception or handle appropriately.
+ }
+ }
+
+ if (!m_baseptr) return NULL;
+
+ DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(),
+ m_baseptr, (uptr)m_baseptr+reserved_bytes, reserved_bytes / _1mb);
+
+ /*if (m_def_commit)
+ {
+ const uint camt = m_def_commit * __pagesize;
+ HostSys::MmapCommit(m_baseptr, camt);
+ HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
+
+ u8* init = (u8*)m_baseptr;
+ u8* endpos = init + camt;
+ for( ; init= m_reserved) return;
+
+ try {
+
+ if (!m_commited && m_def_commit)
+ {
+ const uint camt = m_def_commit * __pagesize;
+ // first block being committed! Commit the default requested
+ // amount if its different from the blocksize.
+
+ HostSys::MmapCommit(m_baseptr, camt);
+ HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
+
+ u8* init = (u8*)m_baseptr;
+ u8* endpos = init + camt;
+ for( ; init
+#include "Utilities/MemsetFast.inl"
+
// the BP doesn't advance and returns -1 if there is no data to be read
__aligned16 tIPU_cmd ipu_cmd;
__aligned16 tIPU_BP g_BP;
diff --git a/pcsx2/IPU/mpeg2lib/Mpeg.cpp b/pcsx2/IPU/mpeg2lib/Mpeg.cpp
index 4a2c3f00d2..f2fd7e3ac8 100644
--- a/pcsx2/IPU/mpeg2lib/Mpeg.cpp
+++ b/pcsx2/IPU/mpeg2lib/Mpeg.cpp
@@ -33,6 +33,8 @@
#include "Mpeg.h"
#include "Vlc.h"
+#include "Utilities/MemsetFast.inl"
+
const int non_linear_quantizer_scale [] =
{
0, 1, 2, 3, 4, 5, 6, 7,
diff --git a/pcsx2/IPU/mpeg2lib/Mpeg.h b/pcsx2/IPU/mpeg2lib/Mpeg.h
index b4741d9574..982007ed6c 100644
--- a/pcsx2/IPU/mpeg2lib/Mpeg.h
+++ b/pcsx2/IPU/mpeg2lib/Mpeg.h
@@ -24,48 +24,6 @@
#pragma once
-#include
-
-template< typename T >
-__noinline void memzero_sse_a( T& dest )
-{
-#define MZFqwc (sizeof(dest)/16)
-
- C_ASSERT( (sizeof(dest) & 0xf) == 0 );
-
- __m128 zeroreg = _mm_setzero_ps();
-
- float (*destxmm)[4] = (float(*)[4])&dest;
-
-#define StoreDestIdx(idx) case idx: _mm_store_ps(&destxmm[idx-1][0], zeroreg)
-
- switch( MZFqwc & 0x07 )
- {
- StoreDestIdx(0x07);
- StoreDestIdx(0x06);
- StoreDestIdx(0x05);
- StoreDestIdx(0x04);
- StoreDestIdx(0x03);
- StoreDestIdx(0x02);
- StoreDestIdx(0x01);
- }
-
- destxmm += (MZFqwc & 0x07);
- for( uint i=0; i
-
+
diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp
index 626d7d299c..5efe544ea4 100644
--- a/pcsx2/Memory.cpp
+++ b/pcsx2/Memory.cpp
@@ -40,11 +40,12 @@ BIOS
#include "IopCommon.h"
#include "VUmicro.h"
#include "GS.h"
-#include "System/PageFaultSource.h"
#include "ps2/HwInternal.h"
#include "ps2/BiosTools.h"
+#include "Utilities/PageFaultSource.h"
+
#ifdef ENABLECACHE
#include "Cache.h"
#endif
diff --git a/pcsx2/PrecompiledHeader.h b/pcsx2/PrecompiledHeader.h
index e24bcfc556..5788d481cd 100644
--- a/pcsx2/PrecompiledHeader.h
+++ b/pcsx2/PrecompiledHeader.h
@@ -102,20 +102,9 @@ typedef int BOOL;
typedef void FnType_Void();
typedef FnType_Void* Fnptr_Void;
-static const sptr _64kb = 0x10000;
-static const sptr _16kb = _64kb / 4;
-static const sptr _128kb = _64kb * 2;
-static const sptr _256kb = _128kb * 2;
-
-static const s64 _1mb = 0x100000;
-static const s64 _8mb = _1mb * 8;
-static const s64 _16mb = _1mb * 16;
-static const s64 _64mb = _1mb * 64;
-static const s64 _256mb = _1mb * 256;
-static const s64 _1gb = _256mb * 4;
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Compiler/OS specific macros and defines -- Begin Section
+// --------------------------------------------------------------------------------------
+// Compiler/OS specific macros and defines
+// --------------------------------------------------------------------------------------
// Linux isn't set up for svn version numbers yet.
#ifdef __LINUX__
diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp
index 411cafe84b..c9a547942e 100644
--- a/pcsx2/SaveState.cpp
+++ b/pcsx2/SaveState.cpp
@@ -48,7 +48,7 @@ static void PostLoadPrep()
wxString SaveStateBase::GetFilename( int slot )
{
return (g_Conf->Folders.Savestates +
- wxsFormat( L"%8.8X.%3.3d", ElfCRC, slot )).GetFullPath();
+ pxsFmt( L"%08X.%03d", ElfCRC, slot )).GetFullPath();
}
SaveStateBase::SaveStateBase( SafeArray& memblock )
diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp
index c9433e7914..ecb33f9d90 100644
--- a/pcsx2/System.cpp
+++ b/pcsx2/System.cpp
@@ -16,192 +16,24 @@
#include "PrecompiledHeader.h"
#include "Common.h"
#include "IopCommon.h"
-
-#include "System/PageFaultSource.h"
-#include "Utilities/EventSource.inl"
+#include "VUmicro.h"
// Includes needed for cleanup, since we don't have a good system (yet) for
// cleaning up these things.
-#include "sVU_zerorec.h"
#include "GameDatabase.h"
#include "Elfheader.h"
+#include "System/RecTypes.h"
+
+#include "Utilities/MemsetFast.inl"
+
+
extern void closeNewVif(int idx);
extern void resetNewVif(int idx);
-template class EventSource< IEventListener_PageFault >;
-
-SrcType_PageFault* Source_PageFault = NULL;
-
-EventListener_PageFault::EventListener_PageFault()
-{
- pxAssume(Source_PageFault);
- Source_PageFault->Add( *this );
-}
-
-EventListener_PageFault::~EventListener_PageFault() throw()
-{
- if (Source_PageFault)
- Source_PageFault->Remove( *this );
-}
-
-void SrcType_PageFault::Dispatch( const PageFaultInfo& params )
-{
- m_handled = false;
- _parent::Dispatch( params );
-}
-
-void SrcType_PageFault::_DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt )
-{
- do {
- (*iter)->DispatchEvent( evt, m_handled );
- } while( (++iter != iend) && !m_handled );
-}
-
// --------------------------------------------------------------------------------------
-// BaseVirtualMemoryReserve (implementations)
+// RecompiledCodeReserve (implementations)
// --------------------------------------------------------------------------------------
-
-BaseVirtualMemoryReserve::BaseVirtualMemoryReserve( const wxString& name )
- : Name( name )
-{
- m_commited = 0;
- m_reserved = 0;
- m_baseptr = NULL;
- m_block_size = __pagesize;
- m_prot_mode = PageAccess_None();
-}
-
-// Parameters:
-// upper_bounds - criteria that must be met for the allocation to be valid.
-// If the OS refuses to allocate the memory below the specified address, the
-// object will fail to initialize and an exception will be thrown.
-void* BaseVirtualMemoryReserve::Reserve( uint size, uptr base, uptr upper_bounds )
-{
- if (!pxAssertDev( m_baseptr == NULL, "(VirtualMemoryReserve) Invalid object state; object has already been reserved." ))
- return m_baseptr;
-
- m_reserved = (size + __pagesize-4) / __pagesize;
- uptr reserved_bytes = m_reserved * __pagesize;
-
- m_baseptr = (void*)HostSys::MmapReserve(base, reserved_bytes);
-
- if (!m_baseptr && (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds)))
- {
- if (base)
- {
- DevCon.Warning( L"%s default address 0x%08x is unavailable; falling back on OS-default address.", Name.c_str(), base );
-
- // Let's try again at an OS-picked memory area, and then hope it meets needed
- // boundschecking criteria below.
- SafeSysMunmap( m_baseptr, reserved_bytes );
- m_baseptr = (void*)HostSys::MmapReserve( NULL, reserved_bytes );
- }
-
- if ((upper_bounds != 0) && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))
- {
- SafeSysMunmap( m_baseptr, reserved_bytes );
- // returns null, caller should throw an exception or handle appropriately.
- }
- }
-
- if (!m_baseptr) return NULL;
-
- DevCon.WriteLn( Color_Blue, L"%s mapped @ 0x%08X -> 0x%08X [%umb]", Name.c_str(),
- m_baseptr, (uptr)m_baseptr+reserved_bytes, reserved_bytes / _1mb);
-
- /*if (m_def_commit)
- {
- const uint camt = m_def_commit * __pagesize;
- HostSys::MmapCommit(m_baseptr, camt);
- HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
-
- u8* init = (u8*)m_baseptr;
- u8* endpos = init + camt;
- for( ; init= m_reserved) return;
-
- try {
-
- if (!m_commited && m_def_commit)
- {
- const uint camt = m_def_commit * __pagesize;
- // first block being committed! Commit the default requested
- // amount if its different from the blocksize.
-
- HostSys::MmapCommit(m_baseptr, camt);
- HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
-
- u8* init = (u8*)m_baseptr;
- u8* endpos = init + camt;
- for( ; init
-__noinline void memset_sse_a( void* dest, const size_t size )
-{
- const uint MZFqwc = size / 16;
-
- pxAssert( (size & 0xf) == 0 );
-
- static __aligned16 const u8 loadval[8] = { data,data,data,data,data,data,data,data };
- __m128 srcreg = _mm_load_ps( (float*)loadval );
- srcreg = _mm_loadh_pi( srcreg, (__m64*)loadval );
-
- float (*destxmm)[4] = (float(*)[4])dest;
-
-#define StoreDestIdx(idx) case idx: _mm_store_ps(&destxmm[idx-1][0], srcreg)
-
- switch( MZFqwc & 0x07 )
- {
- StoreDestIdx(0x07);
- StoreDestIdx(0x06);
- StoreDestIdx(0x05);
- StoreDestIdx(0x04);
- StoreDestIdx(0x03);
- StoreDestIdx(0x02);
- StoreDestIdx(0x01);
- }
-
- destxmm += (MZFqwc & 0x07);
- for( uint i=0; iSetCacheReserve( (Cpu->GetCacheReserve() * 3) / 2 );
Cpu->Reset();
- //CpuVU0->SetCacheReserve( (CpuVU0->GetCacheReserve() * 3) / 2 );
+ CpuVU0->SetCacheReserve( (CpuVU0->GetCacheReserve() * 3) / 2 );
CpuVU0->Reset();
- //CpuVU1->SetCacheReserve( (CpuVU1->GetCacheReserve() * 3) / 2 );
+ CpuVU1->SetCacheReserve( (CpuVU1->GetCacheReserve() * 3) / 2 );
CpuVU1->Reset();
//psxCpu->SetCacheReserve( (psxCpu->GetCacheReserve() * 3) / 2 );
psxCpu->Reset();
+}
+
+// Default behavior for out of memory: the
+void RecompiledCodeReserve::OnOutOfMemory( const Exception::OutOfMemory& ex, void* blockptr, bool& handled )
+{
// Since the recompiler is happy writing away to memory, we have to truncate the reserve
// to include the page currently being accessed, and cannot go any smaller. This will
// allow the rec to finish emitting the current block of instructions, detect that it has
@@ -293,6 +87,11 @@ void RecompiledCodeReserve::OnOutOfMemory( const Exception::OutOfMemory& ex, voi
try
{
+ // Truncate and reset reserves of all other in-use recompiler caches, as this should
+ // help free up quite a bit of emergency memory.
+
+ ResetProcessReserves();
+
uint cusion = std::min( m_block_size, 4 );
HostSys::MmapCommit((u8*)blockptr, cusion * __pagesize);
HostSys::MemProtect((u8*)blockptr, cusion * __pagesize, m_prot_mode);
@@ -442,7 +241,7 @@ CpuInitializer< CpuType >::CpuInitializer()
{
try {
MyCpu = new CpuType();
- MyCpu->Allocate();
+ MyCpu->Reserve();
}
catch( Exception::RuntimeError& ex )
{
@@ -461,7 +260,7 @@ CpuInitializer< CpuType >::CpuInitializer()
template< typename CpuType >
CpuInitializer< CpuType >::~CpuInitializer() throw()
{
- if( MyCpu )
+ if (MyCpu)
MyCpu->Shutdown();
}
@@ -608,11 +407,6 @@ SysCpuProviderPack::SysCpuProviderPack()
}
// hmm! : VU0 and VU1 pre-allocations should do sVU and mVU separately? Sounds complicated. :(
-
- // If both VUrecs failed, then make sure the SuperVU is totally closed out, because it
- // actually initializes everything once and then shares it between both VU recs.
- if( !IsRecAvailable_SuperVU0() && !IsRecAvailable_SuperVU1() )
- SuperVUDestroy( -1 );
}
bool SysCpuProviderPack::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
@@ -633,9 +427,6 @@ void SysCpuProviderPack::CleanupMess() throw()
closeNewVif(0);
closeNewVif(1);
- // Special SuperVU "complete" terminator (stupid hacky recompiler)
- SuperVUDestroy( -1 );
-
psxRec.Shutdown();
recCpu.Shutdown();
}
@@ -695,10 +486,6 @@ void SysClearExecutionCache()
{
GetCpuProviders().ApplyConfig();
- // SuperVUreset will do nothing is none of the recs are initialized.
- // But it's needed if one or the other is initialized.
- SuperVUReset(-1);
-
Cpu->Reset();
psxCpu->Reset();
diff --git a/pcsx2/System.h b/pcsx2/System.h
index cec9cc0c66..f0e1fc1db5 100644
--- a/pcsx2/System.h
+++ b/pcsx2/System.h
@@ -22,8 +22,9 @@
#include "CDVD/CDVDaccess.h"
typedef SafeArray VmStateBuffer;
-class BaseVUmicroCPU;
+class BaseVUmicroCPU;
+class RecompiledCodeReserve;
// This is a table of default virtual map addresses for ps2vm components. These locations
// are provided and used to assist in debugging and possibly hacking; as it makes it possible
@@ -38,8 +39,9 @@ class BaseVUmicroCPU;
namespace HostMemoryMap
{
// superVU is OLD SCHOOL, and it requires its allocation to be in the lower 256mb
- // of the virtual memory space. (8mb)
- static const uptr sVUrec = 0x0f1e0000;
+ // of the virtual memory space. (8mb each)
+ static const uptr sVU0rec = _256mb - (_16mb*2);
+ static const uptr sVU1rec = _256mb - (_16mb*1);
// PS2 main memory, SPR, and ROMs
static const uptr EEmem = 0x20000000;
diff --git a/pcsx2/System/RecTypes.h b/pcsx2/System/RecTypes.h
new file mode 100644
index 0000000000..995444669d
--- /dev/null
+++ b/pcsx2/System/RecTypes.h
@@ -0,0 +1,46 @@
+/* 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
+
+#include "Utilities/PageFaultSource.h"
+
+// --------------------------------------------------------------------------------------
+// RecompiledCodeReserve
+// --------------------------------------------------------------------------------------
+// A recompiled code reserve is a simple sequential-growth block of memory which is auto-
+// cleared to INT 3 (0xcc) as needed. When using this class, care should be take to re-
+// implement the provided OnOutOfMemory handler so that it clears other recompiled memory
+// reserves that are known to be attached to the process.
+//
+class RecompiledCodeReserve : public BaseVirtualMemoryReserve
+{
+protected:
+
+public:
+ RecompiledCodeReserve( const wxString& name, uint defCommit = 0 );
+
+ virtual void OnCommittedBlock( void* block );
+ virtual void OnOutOfMemory( const Exception::OutOfMemory& ex, void* blockptr, bool& handled );
+
+ operator void*() { return m_baseptr; }
+ operator const void*() const { return m_baseptr; }
+
+ operator u8*() { return (u8*)m_baseptr; }
+ operator const u8*() const { return (u8*)m_baseptr; }
+
+protected:
+ void ResetProcessReserves() const;
+};
diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp
index 1238275900..a1f59ded4e 100644
--- a/pcsx2/System/SysCoreThread.cpp
+++ b/pcsx2/System/SysCoreThread.cpp
@@ -22,9 +22,9 @@
#include "GS.h"
#include "Elfheader.h"
#include "Patch.h"
-#include "PageFaultSource.h"
#include "SysThreads.h"
+#include "Utilities/PageFaultSource.h"
#include "Utilities/TlsVariable.inl"
#ifdef __WXMSW__
diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h
index 81436cdf48..8270c17714 100644
--- a/pcsx2/VUmicro.h
+++ b/pcsx2/VUmicro.h
@@ -47,9 +47,9 @@ static const uint VU1_PROGMASK = VU1_PROGSIZE-1;
class BaseCpuProvider
{
protected:
- // allocation counter for multiple init/shutdown calls
- // (most or all implementations will need this!)
- int m_AllocCount;
+ // allocation counter for multiple calls to Reserve. Most implementations should utilize
+ // this variable for sake of robustness.
+ u32 m_Reserved;
public:
// this boolean indicates to some generic logging facilities if the VU's registers
@@ -60,13 +60,13 @@ public:
public:
BaseCpuProvider()
{
- m_AllocCount = 0;
+ m_Reserved = 0;
}
virtual ~BaseCpuProvider() throw()
{
- if( m_AllocCount != 0 )
- Console.Warning( "Cleanup miscount detected on CPU provider. Count=%d", m_AllocCount );
+ if( m_Reserved != 0 )
+ Console.Warning( "Cleanup miscount detected on CPU provider. Count=%d", m_Reserved );
}
virtual const char* GetShortName() const=0;
@@ -80,7 +80,7 @@ public:
return 0;
}
- virtual void Allocate()=0;
+ virtual void Reserve()=0;
virtual void Shutdown()=0;
virtual void Reset()=0;
virtual void Execute(u32 cycles)=0;
@@ -96,6 +96,15 @@ public:
{
cpu->Execute(1024);
}
+
+ // Gets the current cache reserve allocated to this CPU (value returned in megabytes)
+ virtual uint GetCacheReserve() const=0;
+
+ // Specifies the maximum cache reserve amount for this CPU (value in megabytes).
+ // CPU providers are allowed to reset their reserves (recompiler resets, etc) if such is
+ // needed to conform to the new amount requested.
+ virtual void SetCacheReserve( uint reserveInMegs ) const=0;
+
};
// --------------------------------------------------------------------------------------
@@ -157,13 +166,16 @@ public:
const char* GetShortName() const { return "intVU0"; }
wxString GetLongName() const { return L"VU0 Interpreter"; }
- void Allocate() { }
+ void Reserve() { }
void Shutdown() throw() { }
void Reset() { }
void Step();
void Execute(u32 cycles);
void Clear(u32 addr, u32 size) {}
+
+ uint GetCacheReserve() const { return 0; }
+ void SetCacheReserve( uint reserveInMegs ) const {}
};
class InterpVU1 : public BaseVUmicroCPU
@@ -175,13 +187,16 @@ public:
const char* GetShortName() const { return "intVU1"; }
wxString GetLongName() const { return L"VU1 Interpreter"; }
- void Allocate() { }
+ void Reserve() { }
void Shutdown() throw() { }
void Reset() { }
void Step();
void Execute(u32 cycles);
void Clear(u32 addr, u32 size) {}
+
+ uint GetCacheReserve() const { return 0; }
+ void SetCacheReserve( uint reserveInMegs ) const {}
};
// --------------------------------------------------------------------------------------
@@ -196,13 +211,16 @@ public:
const char* GetShortName() const { return "mVU0"; }
wxString GetLongName() const { return L"microVU0 Recompiler"; }
- void Allocate();
+ void Reserve();
void Shutdown() throw();
void Reset();
void Execute(u32 cycles);
void Clear(u32 addr, u32 size);
void Vsync() throw();
+
+ uint GetCacheReserve() const;
+ void SetCacheReserve( uint reserveInMegs ) const;
};
class recMicroVU1 : public BaseVUmicroCPU
@@ -214,12 +232,15 @@ public:
const char* GetShortName() const { return "mVU1"; }
wxString GetLongName() const { return L"microVU1 Recompiler"; }
- void Allocate();
+ void Reserve();
void Shutdown() throw();
void Reset();
void Execute(u32 cycles);
void Clear(u32 addr, u32 size);
void Vsync() throw();
+
+ uint GetCacheReserve() const;
+ void SetCacheReserve( uint reserveInMegs ) const;
};
// --------------------------------------------------------------------------------------
@@ -234,11 +255,14 @@ public:
const char* GetShortName() const { return "sVU0"; }
wxString GetLongName() const { return L"SuperVU0 Recompiler"; }
- void Allocate();
+ void Reserve();
void Shutdown() throw();
void Reset();
void Execute(u32 cycles);
void Clear(u32 Addr, u32 Size);
+
+ uint GetCacheReserve() const;
+ void SetCacheReserve( uint reserveInMegs ) const;
};
class recSuperVU1 : public BaseVUmicroCPU
@@ -249,11 +273,14 @@ public:
const char* GetShortName() const { return "sVU1"; }
wxString GetLongName() const { return L"SuperVU1 Recompiler"; }
- void Allocate();
+ void Reserve();
void Shutdown() throw();
void Reset();
void Execute(u32 cycles);
void Clear(u32 Addr, u32 Size);
+
+ uint GetCacheReserve() const;
+ void SetCacheReserve( uint reserveInMegs ) const;
};
extern BaseVUmicroCPU* CpuVU0;
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index 1affaf6adf..c72c18c5cb 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -459,6 +459,10 @@
RelativePath="..\..\Plugins.h"
>
+
+
diff --git a/pcsx2/windows/WinSysExec.cpp b/pcsx2/windows/WinSysExec.cpp
index b454bea0d8..5d1f482fba 100644
--- a/pcsx2/windows/WinSysExec.cpp
+++ b/pcsx2/windows/WinSysExec.cpp
@@ -18,7 +18,7 @@
#include
#include "Common.h"
-#include "System/PageFaultSource.h"
+#include "Utilities/PageFaultSource.h"
int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
{
diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp
index 13724b55ba..2886d53080 100644
--- a/pcsx2/x86/iR3000A.cpp
+++ b/pcsx2/x86/iR3000A.cpp
@@ -22,7 +22,7 @@
#include "iR3000A.h"
#include "BaseblockEx.h"
-#include "PageFaultSource.h"
+#include "System/RecTypes.h"
#include
@@ -759,8 +759,9 @@ static void recReserve()
{
if (!recMem)
{
- recMem = new RecompiledCodeReserve(L"R3000A recompiled code cache", _1mb * 2);
+ recMem = new RecompiledCodeReserve(L"R3000A Recompiler Cache", _1mb * 2);
recMem->Reserve( _16mb, HostMemoryMap::IOPrec );
+ ProfilerRegisterSource( "IOP Rec", *recMem, recMem->GetReserveSizeInBytes() );
}
}
@@ -790,17 +791,16 @@ static void recAlloc()
if( s_pInstCache == NULL )
throw Exception::OutOfMemory( L"R3000 InstCache." );
- ProfilerRegisterSource( "IOP Rec", *recMem, recMem->GetReserveSizeInBytes() );
_DynGen_Dispatchers();
}
void recResetIOP()
{
+ DevCon.WriteLn( "iR3000A Recompiler reset." );
+
recAlloc();
recMem->Reset();
- DevCon.WriteLn( "iR3000A Recompiler reset." );
-
iopClearRecLUT((BASEBLOCK*)m_recBlockAlloc,
(((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4)));
diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp
index b3eb7783a5..3c90e9a28b 100644
--- a/pcsx2/x86/ix86-32/iR5900-32.cpp
+++ b/pcsx2/x86/ix86-32/iR5900-32.cpp
@@ -21,16 +21,15 @@
#include "R5900Exceptions.h"
#include "R5900OpcodeTables.h"
#include "iR5900.h"
-
#include "BaseblockEx.h"
+#include "System/RecTypes.h"
+
#include "vtlb.h"
#include "SamplProf.h"
#include "Dump.h"
#include "System/SysThreads.h"
-#include "System/PageFaultSource.h"
#include "GS.h"
-
#include "CDVD/CDVD.h"
#include "Elfheader.h"
@@ -562,7 +561,7 @@ static void recReserve()
if ( !x86caps.hasStreamingSIMD2Extensions )
recThrowHardwareDeficiency( L"SSE2" );
- recMem = new RecompiledCodeReserve(L"R5900-32 recompiled code cache", _1mb * 4);
+ recMem = new RecompiledCodeReserve(L"R5900-32 Recompiler Cache", _1mb * 4);
recMem->Reserve( _64mb, HostMemoryMap::EErec );
}
@@ -614,6 +613,7 @@ static __aligned16 u8 manual_counter[Ps2MemSize::MainRam >> 12];
static u32 eeRecIsReset = false;
static u32 eeRecNeedsReset = false;
static bool eeRecIsActive = false;
+static bool eeCpuExecuting = false;
////////////////////////////////////////////////////
static void recResetRaw()
@@ -701,7 +701,7 @@ static void recShutdown()
static void recResetEE()
{
- if (eeRecIsActive)
+ if (eeRecIsActive || eeCpuExecuting)
{
AtomicExchange( eeRecNeedsReset, true );
return;
@@ -746,8 +746,6 @@ static void recCheckExecutionState()
}
}
-static bool m_recExecutingCode = false;
-
static void recExecute()
{
// Implementation Notes:
@@ -755,12 +753,14 @@ static void recExecute()
#if PCSX2_SEH
eeRecIsReset = false;
- ScopedBool executing(m_recExecutingCode);
+ ScopedBool executing(eeCpuExecuting);
try {
EnterRecompiledCode();
}
- catch( Exception::ExitCpuExecute& ) { }
+ catch( Exception::ExitCpuExecute& )
+ {
+ }
#else
@@ -1369,7 +1369,7 @@ static void __fastcall recRecompile( const u32 startpc )
// From here on we need to have EE recompile resets disabled, since to reset
// the rec while we're writing to it typically leads to GPF.
- ScopedBool active_scope(eeRecIsActive);
+ //ScopedBool active_scope(eeRecIsActive);
xSetPtr( recPtr );
recPtr = xGetAlignedCallTarget();
@@ -1868,7 +1868,7 @@ static void recThrowException( const BaseR5900Exception& ex )
#if PCSX2_SEH
ex.Rethrow();
#else
- if (!m_recExecutingCode) ex.Rethrow();
+ if (!eeCpuExecuting) ex.Rethrow();
m_cpuException = ex.Clone();
recExitExecution();
#endif
@@ -1879,7 +1879,7 @@ static void recThrowException( const BaseException& ex )
#if PCSX2_SEH
ex.Rethrow();
#else
- if (!m_recExecutingCode) ex.Rethrow();
+ if (!eeCpuExecuting) ex.Rethrow();
m_Exception = ex.Clone();
recExitExecution();
#endif
diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp
index 114e9ed3d1..f6c409cb99 100644
--- a/pcsx2/x86/microVU.cpp
+++ b/pcsx2/x86/microVU.cpp
@@ -18,6 +18,7 @@
#include "PrecompiledHeader.h"
#include "Common.h"
#include "microVU.h"
+#include "RecTypes.h"
// Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files)
#include "microVU_Clamp.inl"
@@ -99,22 +100,22 @@ void microVU::init(uint vuIndex) {
microMemSize = (index ? 0x4000 : 0x1000);
progSize = (index ? 0x4000 : 0x1000) / 4;
progMemMask = progSize-1;
- dispCache = NULL;
- cache = NULL;
- cacheSize = mVUcacheSize;
- regAlloc = new microRegAlloc(index);
-
- for (u32 i = 0; i < (progSize / 2); i++) {
- prog.prog[i] = new deque();
- }
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(this, cacheSize + mVUcacheSafeZone);
- //if (vuIndex) gen_memcpy_vibes();
+ cache_reserve = new RecompiledCodeReserve( pxsFmt("Micro VU%u Recompiler Cache", index) );
+ cache = index ?
+ (u8*)cache_reserve->Reserve( cacheSize, HostMemoryMap::mVU1rec ) :
+ (u8*)cache_reserve->Reserve( cacheSize, HostMemoryMap::mVU0rec );
+
+ if(!cache_reserve->IsOk())
+ throw Exception::VirtualMemoryMapConflict().SetDiagMsg(pxsFmt( L"Micro VU%u Recompiler Cache", index ));
+
+ ProfilerRegisterSource (index ? "mVU1 Rec" : "mVU0 Rec", cache, cacheSize);
+
+ regAlloc = new microRegAlloc(index);
}
// Resets Rec Data
@@ -144,9 +145,15 @@ void microVU::reset() {
u8* z = cache;
prog.x86start = z;
prog.x86ptr = z;
- prog.x86end = (u8*)((uptr)z + (uptr)(cacheSize - mVUcacheSafeZone)); // "Safe Zone"
+ prog.x86end = z + (cacheSize - mVUcacheSafeZone);
for (u32 i = 0; i < (progSize / 2); i++) {
+ if (!prog.prog[i])
+ {
+ prog.prog[i] = new deque();
+ continue;
+ }
+
deque::iterator it(prog.prog[i]->begin());
for ( ; it != prog.prog[i]->end(); ++it) {
if (index) mVUdeleteProg<1>(it[0]);
@@ -161,11 +168,17 @@ void microVU::reset() {
// Free Allocated Resources
void microVU::close() {
- if (dispCache) { HostSys::Munmap(dispCache, mVUdispCacheSize); dispCache = NULL; }
- if (cache) { HostSys::Munmap(cache, cacheSize); cache = NULL; }
+ if (cache_reserve && cache_reserve->IsOk())
+ {
+ ProfilerTerminateSource (index ? "mVU1 Rec" : "mVU0 Rec");
+ safe_delete(cache_reserve);
+ }
+
+ SafeSysMunmap(dispCache, mVUdispCacheSize);
// Delete Programs and Block Managers
for (u32 i = 0; i < (progSize / 2); i++) {
+ if (!prog.prog[i]) continue;
deque::iterator it(prog.prog[i]->begin());
for ( ; it != prog.prog[i]->end(); ++it) {
if (index) mVUdeleteProg<1>(it[0]);
@@ -175,35 +188,6 @@ void microVU::close() {
}
}
-static void mVUresizeCache(mV, u32 size) {
-
- if (size >= (u32)mVUcacheMaxSize) {
- if (mVU->cacheSize==mVUcacheMaxSize) {
- // 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);
- mVU->reset();
- return;
- }
- size = mVUcacheMaxSize;
- }
-
- if (mVU->cache) Console.WriteLn(Color_Green, "microVU%d: Attempting to resize Cache [%dmb]", mVU->index, size/_1mb);
-
- u8* cache = SysMmapEx(mVU->index ? HostMemoryMap::mVU1rec : HostMemoryMap::mVU0rec, 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); mVU->reset(); return; }
- if (mVU->cache) {
- HostSys::Munmap(mVU->cache, mVU->cacheSize);
- ProfilerTerminateSource(isVU1?"mVU1 Rec":"mVU0 Rec");
- }
-
- mVU->cache = cache;
- mVU->cacheSize = size;
- ProfilerRegisterSource(isVU1?"mVU1 Rec":"mVU0 Rec", mVU->cache, mVU->cacheSize);
- mVU->reset();
-}
-
// Clears Block Data in specified range
static __fi void mVUclear(mV, u32 addr, u32 size) {
if (!mVU->prog.cleared) {
@@ -323,55 +307,40 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) {
// recMicroVU0 / recMicroVU1
//------------------------------------------------------------------
-static u32 mvu0_allocated = 0;
-static u32 mvu1_allocated = 0;
-
recMicroVU0::recMicroVU0() { m_Idx = 0; IsInterpreter = false; }
recMicroVU1::recMicroVU1() { m_Idx = 1; IsInterpreter = false; }
void recMicroVU0::Vsync() throw() { mVUvsyncUpdate(µVU0); }
void recMicroVU1::Vsync() throw() { mVUvsyncUpdate(µVU1); }
-void recMicroVU0::Allocate() {
- if(!m_AllocCount) {
- m_AllocCount++;
- if (AtomicExchange(mvu0_allocated, 1) == 0)
- microVU0.init(0);
- }
+void recMicroVU0::Reserve() {
+ if (AtomicExchange(m_Reserved, 1) == 0)
+ microVU0.init(0);
}
-void recMicroVU1::Allocate() {
- if(!m_AllocCount) {
- m_AllocCount++;
- if (AtomicExchange(mvu1_allocated, 1) == 0)
- microVU1.init(1);
- }
+void recMicroVU1::Reserve() {
+ if (AtomicExchange(m_Reserved, 1) == 0)
+ microVU1.init(1);
}
void recMicroVU0::Shutdown() throw() {
- if (m_AllocCount > 0) {
- m_AllocCount--;
- if (AtomicExchange(mvu0_allocated, 0) == 1)
- microVU0.close();
- }
+ if (AtomicExchange(m_Reserved, 0) == 1)
+ microVU0.close();
}
void recMicroVU1::Shutdown() throw() {
- if (m_AllocCount > 0) {
- m_AllocCount--;
- if (AtomicExchange(mvu1_allocated, 0) == 1)
- microVU1.close();
- }
+ if (AtomicExchange(m_Reserved, 0) == 1)
+ microVU1.close();
}
void recMicroVU0::Reset() {
- if(!pxAssertDev(m_AllocCount, "MicroVU0 CPU Provider has not been allocated prior to reset!")) return;
+ if(!pxAssertDev(m_Reserved, "MicroVU0 CPU Provider has not been reserved prior to reset!")) return;
microVU0.reset();
}
void recMicroVU1::Reset() {
- if(!pxAssertDev(m_AllocCount, "MicroVU1 CPU Provider has not been allocated prior to reset!")) return;
+ if(!pxAssertDev(m_Reserved, "MicroVU1 CPU Provider has not been reserved prior to reset!")) return;
microVU1.reset();
}
void recMicroVU0::Execute(u32 cycles) {
- pxAssert(mvu0_allocated); // please allocate me first! :|
+ pxAssert(m_Reserved); // please allocate me first! :|
if(!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
@@ -381,17 +350,35 @@ void recMicroVU0::Execute(u32 cycles) {
((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, cycles);
}
void recMicroVU1::Execute(u32 cycles) {
- pxAssert(mvu1_allocated); // please allocate me first! :|
+ pxAssert(m_Reserved); // please allocate me first! :|
if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, vu1RunCycles);
}
void recMicroVU0::Clear(u32 addr, u32 size) {
- pxAssert(mvu0_allocated); // please allocate me first! :|
+ pxAssert(m_Reserved); // please allocate me first! :|
mVUclear(µVU0, addr, size);
}
void recMicroVU1::Clear(u32 addr, u32 size) {
- pxAssert(mvu1_allocated); // please allocate me first! :|
+ pxAssert(m_Reserved); // please allocate me first! :|
mVUclear(µVU1, addr, size);
}
+
+uint recMicroVU0::GetCacheReserve() const
+{
+ return microVU0.cacheSize / _1mb;
+}
+uint recMicroVU1::GetCacheReserve() const
+{
+ return microVU1.cacheSize / _1mb;
+}
+
+void recMicroVU0::SetCacheReserve( uint reserveInMegs ) const
+{
+ microVU0.cacheSize = reserveInMegs * _1mb;
+}
+void recMicroVU1::SetCacheReserve( uint reserveInMegs ) const
+{
+ microVU1.cacheSize = reserveInMegs * _1mb;
+}
diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h
index 5cc8eb8f06..57cd99a092 100644
--- a/pcsx2/x86/microVU.h
+++ b/pcsx2/x86/microVU.h
@@ -150,7 +150,7 @@ struct microProgManager {
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
};
-#define mVUdispCacheSize (0x1000) // Dispatcher Cache Size
+#define mVUdispCacheSize (__pagesize) // Dispatcher Cache Size
#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
@@ -175,7 +175,9 @@ struct microVU {
ScopedPtr regAlloc; // Reg Alloc Class
ScopedPtr logFile; // Log File Pointer
- u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to)
+
+ RecompiledCodeReserve* cache_reserve;
+ 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
u8* exitFunct; // Ptr Function to the Exit code for recompiled programs
@@ -224,6 +226,15 @@ 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;
}
+
+ microVU()
+ {
+ cacheSize = _1mb * 64;
+ cache = NULL;
+ dispCache = NULL;
+ startFunct = NULL;
+ exitFunct = NULL;
+ }
void init(uint vuIndex);
void reset();
@@ -239,7 +250,6 @@ int mVUdebugNow = 0;
// Main Functions
static void mVUclear(mV, u32, u32);
-static void mVUresizeCache(mV, u32);
static void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
_mVUt extern void* __fastcall mVUcompileJIT(u32 startPC, uptr pState);
diff --git a/pcsx2/x86/microVU_Execute.inl b/pcsx2/x86/microVU_Execute.inl
index 198ab530da..cca83ed6ba 100644
--- a/pcsx2/x86/microVU_Execute.inl
+++ b/pcsx2/x86/microVU_Execute.inl
@@ -92,7 +92,7 @@ void mVUdispatcherB(mV) {
xRET();
- mVUcacheCheck(x86Ptr, mVU->dispCache, mVUdispCacheSize);
+ pxAssertDev(xGetPtr() < (mVU->dispCache + mVUdispCacheSize), "microVU: Dispatcher generation exceeded reserved cache area!");
}
//------------------------------------------------------------------
@@ -121,8 +121,14 @@ _mVUt void mVUcleanUp() {
//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);
+
mVU->prog.x86ptr = x86Ptr;
- mVUcacheCheck(x86Ptr, mVU->prog.x86start, (uptr)(mVU->prog.x86end - mVU->prog.x86start));
+
+ if ((xGetPtr() < mVU->prog.x86start) || (xGetPtr() >= mVU->prog.x86end)) {
+ Console.WriteLn(vuIndex ? Color_Orange : Color_Magenta, "microVU%d: Program cache limit reached.", mVU->index);
+ mVU->reset();
+ }
+
mVU->cycles = mVU->totalCycles - mVU->cycles;
mVU->regs().cycle += mVU->cycles;
cpuRegs.cycle += ((mVU->cycles < 3000) ? mVU->cycles : 3000) * EmuConfig.Speedhacks.VUCycleSteal;
diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h
index ef58dbe8ef..ff6b1b40e0 100644
--- a/pcsx2/x86/microVU_Misc.h
+++ b/pcsx2/x86/microVU_Misc.h
@@ -298,15 +298,6 @@ static const bool doConstProp = 0; // Set to 1 to turn on vi15 const propagation
//------------------------------------------------------------------
-// Cache Limit Check
-#define mVUcacheCheck(ptr, start, limit) { \
- uptr diff = ptr - start; \
- if (diff >= limit) { \
- DevCon.WriteLn("microVU%d: Program cache limit reached. Size = 0x%x", mVU->index, diff); \
- mVUresizeCache(mVU, mVU->cacheSize + mVUcacheGrowBy); \
- } \
-}
-
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);
diff --git a/pcsx2/x86/sVU_zerorec.cpp b/pcsx2/x86/sVU_zerorec.cpp
index 299e6764a1..43e1bf55e6 100644
--- a/pcsx2/x86/sVU_zerorec.cpp
+++ b/pcsx2/x86/sVU_zerorec.cpp
@@ -35,6 +35,7 @@
#include "R5900.h"
#include "iR5900.h"
+#include "System/RecTypes.h"
#include "sVU_zerorec.h"
#include "SamplProf.h"
@@ -72,7 +73,7 @@ extern void iDumpVU1Registers();
#define SUPERVU_CHECKCONDITION 0 // has to be 0!!
-static const uint VU_EXESIZE = _1mb * 8;
+static const uint sVU_EXESIZE = _8mb;
#define _Imm11_ (s32)( (vucode & 0x400) ? (0xfffffc00 | (vucode & 0x3ff)) : (vucode & 0x3ff) )
#define _UImm11_ (s32)(vucode & 0x7ff)
@@ -90,7 +91,9 @@ static const u32 PWaitTimes[] = { 53, 43, 28, 23, 17, 11, 10 };
static u32 s_vuInfo; // info passed into rec insts
static const u32 s_MemSize[2] = {VU0_MEMSIZE, VU1_MEMSIZE};
-static u8* s_recVUMem = NULL, *s_recVUPtr = NULL;
+//static u8* s_recVUMem = NULL, *s_recVUPtr = NULL;
+static RecompiledCodeReserve* s_recVUMem[2] = { NULL, NULL };
+static u8* s_recVUPtr[2] = { NULL, NULL };
// tables which are defined at the bottom of this massive file.
extern void (*recVU_UPPER_OPCODE[64])(VURegs* VU, s32 info);
@@ -315,9 +318,11 @@ VuBaseBlock::VuBaseBlock()
static list s_listVUHeaders[2];
static list* s_plistCachedHeaders[2] = {NULL, NULL};
-static VuFunctionHeader** recVUHeaders[2] = {NULL, NULL};
-static VuBlockHeader* recVUBlocks[2] = {NULL, NULL};
-static u8* recVUStack = NULL, *recVUStackPtr = NULL;
+static VuFunctionHeader** recVUHeaders[2] = { NULL, NULL };
+static VuBlockHeader* recVUBlocks[2] = { NULL, NULL };
+static u8* recVUStack[2] = { NULL, NULL };
+static u8* recVUStackPtr[2] = { NULL, NULL };
+
static vector<_x86regs> s_vecRegArray(128);
static VURegs* VU = NULL;
@@ -343,47 +348,24 @@ static void SuperVURecompile();
// allocate VU resources
static void SuperVUAlloc(int vuindex)
{
- // The old -1 crap has been depreciated on this function. Please
- // specify either 0 or 1, thanks.
- pxAssert(vuindex >= 0);
+ if (s_recVUMem[vuindex]) return;
+ s_recVUMem[vuindex] = new RecompiledCodeReserve( L"SuperVU Recompiler Cache", 0 );
+ s_recVUMem[vuindex]->Reserve( sVU_EXESIZE, vuindex ? HostMemoryMap::sVU1rec : HostMemoryMap::sVU0rec, _256mb );
+
// upper 4 bits must be zero!
- if (s_recVUMem == NULL)
+ if (!s_recVUMem[vuindex]->IsOk())
{
- // upper 4 bits must be zero!
- // Changed "first try base" to 0xf1e0000, since 0x0c000000 liked to fail a lot. (cottonvibes)
- s_recVUMem = SysMmapEx(HostMemoryMap::sVUrec, VU_EXESIZE, 0x10000000, "SuperVUAlloc");
+ safe_delete(s_recVUMem[vuindex]);
+ throw Exception::VirtualMemoryMapConflict()
+ .SetDiagMsg(pxsFmt( L"SuperVU failed to allocate virtual memory below 256MB." ))
+ .SetUserMsg(pxE( ".Error:superVU:VirtualMemoryAlloc",
+ L"Out of Memory (sorta): The SuperVU recompiler was unable to reserve the specific memory "
+ L"ranges required, and will not be available for use. This is not a critical error, since "
+ L"the sVU rec is obsolete, and you should use microVU instead anyway. :)"
+ ));
- // Try again at some other random memory location... whatever. >_<
- if( s_recVUMem == NULL )
- s_recVUMem = SysMmapEx(0xc2b0000, VU_EXESIZE, 0x10000000, "SuperVUAlloc");
-
- if (s_recVUMem == NULL)
- {
- throw Exception::VirtualMemoryMapConflict()
- .SetDiagMsg(pxsFmt( L"SuperVU failed to allocate virtual memory below 256MB." ))
- .SetUserMsg(pxE( ".Error:superVU:VirtualMemoryAlloc",
- L"Out of Memory (sorta): The SuperVU recompiler was unable to reserve the specific memory "
- L"ranges required, and will not be available for use. This is not a critical error, since "
- L"the sVU rec is obsolete, and you should use microVU instead anyway. :)"
- ));
- }
-
- ProfilerRegisterSource("sVU Rec", s_recVUMem, VU_EXESIZE);
-
- if (recVUStack == NULL) recVUStack = new u8[SUPERVU_STACKSIZE * 4];
- }
-
- if (vuindex >= 0)
- {
- pxAssert(s_recVUMem != NULL);
-
- if (recVUHeaders[vuindex] == NULL)
- recVUHeaders[vuindex] = new VuFunctionHeader* [s_MemSize[vuindex] / 8];
- if (recVUBlocks[vuindex] == NULL)
- recVUBlocks[vuindex] = new VuBlockHeader[s_MemSize[vuindex] / 8];
- if (s_plistCachedHeaders[vuindex] == NULL)
- s_plistCachedHeaders[vuindex] = new list[s_MemSize[vuindex] / 8];
+ ProfilerRegisterSource("sVU Rec", *s_recVUMem[vuindex], sVU_EXESIZE);
}
}
@@ -416,72 +398,66 @@ void DestroyVUHeaders(int vuindex)
// destroy VU resources
void SuperVUDestroy(int vuindex)
{
- list::iterator it;
+ pxAssumeDev(vuindex >= 0 && vuindex <= 2, "Invalid VU index parameter!");
- if (vuindex < 0)
- {
- SuperVUDestroy(0);
- SuperVUDestroy(1);
- ProfilerTerminateSource("VURec");
- SafeSysMunmap(s_recVUMem, VU_EXESIZE);
- safe_delete_array(recVUStack);
- }
- else
- {
- safe_delete_array(recVUHeaders[vuindex]);
- safe_delete_array(recVUBlocks[vuindex]);
+ safe_delete_array(recVUHeaders[vuindex]);
+ safe_delete_array(recVUBlocks[vuindex]);
- if (s_plistCachedHeaders[vuindex] != NULL)
+ if (s_plistCachedHeaders[vuindex] != NULL)
+ {
+ for (u32 j = 0; j < s_MemSize[vuindex] / 8; ++j)
{
- for (u32 j = 0; j < s_MemSize[vuindex] / 8; ++j)
- {
- DestroyCachedHeaders(vuindex, j);
- }
- safe_delete_array(s_plistCachedHeaders[vuindex]);
+ DestroyCachedHeaders(vuindex, j);
}
- DestroyVUHeaders(vuindex);
+ safe_delete_array(s_plistCachedHeaders[vuindex]);
}
+ DestroyVUHeaders(vuindex);
+
+ ProfilerTerminateSource(vuindex ? "sVU1Rec" : "sVU0Rec");
+
+ safe_delete(s_recVUMem[vuindex]);
+ safe_delete_array(recVUStack[vuindex]);
}
// reset VU
void SuperVUReset(int vuindex)
{
+ pxAssumeDev(vuindex >= 0 && vuindex <= 2, "Invalid VU index parameter!");
+
#ifdef PCSX2_DEBUG
s_vucount = 0;
#endif
- if (s_recVUMem == NULL)
- return;
+ DevCon.WriteLn("SuperVU%d: Resetting function and block lists.", vuindex);
- //pxAssume( s_recVUMem != NULL );
+ if (recVUHeaders[vuindex] == NULL)
+ recVUHeaders[vuindex] = new VuFunctionHeader* [s_MemSize[vuindex] / 8];
+ if (recVUBlocks[vuindex] == NULL)
+ recVUBlocks[vuindex] = new VuBlockHeader[s_MemSize[vuindex] / 8];
+ if (s_plistCachedHeaders[vuindex] == NULL)
+ s_plistCachedHeaders[vuindex] = new std::list[s_MemSize[vuindex] / 8];
- if (vuindex < 0)
+ if (recVUHeaders[vuindex]) memset(recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex] / 8));
+ if (recVUBlocks[vuindex]) memset(recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex] / 8));
+
+ if (s_plistCachedHeaders[vuindex] != NULL)
{
- DbgCon.WriteLn("SuperVU: Resetting recompiler memory and structures.");
-
- // Does this cause problems on VU recompiler resets? It could, if the VU works like
- // the EE used to, and actually tries to re-enter the recBlock after issuing a clear. (air)
-
- //memset_8<0xcd, VU_EXESIZE>(s_recVUMem);
- memzero_ptr(recVUStack);
-
- s_recVUPtr = s_recVUMem;
- }
- else
- {
- DbgCon.WriteLn("SuperVU [VU%d]: Resetting the recs and junk", vuindex);
- if (recVUHeaders[vuindex]) memset(recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex] / 8));
- if (recVUBlocks[vuindex]) memset(recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex] / 8));
-
- if (s_plistCachedHeaders[vuindex] != NULL)
+ for (u32 j = 0; j < s_MemSize[vuindex] / 8; ++j)
{
- for (u32 j = 0; j < s_MemSize[vuindex] / 8; ++j)
- {
- DestroyCachedHeaders(vuindex, j);
- }
+ DestroyCachedHeaders(vuindex, j);
}
- DestroyVUHeaders(vuindex);
}
+ DestroyVUHeaders(vuindex);
+
+ if (!s_recVUMem[vuindex] || !s_recVUMem[vuindex]->IsOk()) return;
+
+ DevCon.WriteLn("SuperVU%u: Resetting recompiler cache.", vuindex);
+
+ if (!recVUStack[vuindex]) recVUStack[vuindex] = new u8[SUPERVU_STACKSIZE * 4];
+ memzero_ptr(recVUStack[vuindex]);
+
+ s_recVUMem[vuindex]->Reset();
+ s_recVUPtr[vuindex] = *s_recVUMem[vuindex];
}
// clear the block and any joining blocks
@@ -847,16 +823,15 @@ void VuBaseBlock::GetInstsAtPc(int instpc, list& listinsts)
static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex)
{
pxAssert(vuindex < 2);
- pxAssert(s_recVUPtr != NULL);
+ pxAssert(s_recVUPtr[vuindex] != NULL);
//Console.WriteLn("svu%c rec: %x", '0'+vuindex, startpc);
// if recPtr reached the mem limit reset whole mem
- if (((uptr)s_recVUPtr - (uptr)s_recVUMem) >= VU_EXESIZE - 0x40000)
+ if ((s_recVUPtr[vuindex] < s_recVUMem[vuindex]->GetPtr()) || (s_recVUPtr[vuindex] >= s_recVUMem[vuindex]->GetPtrEnd() - _256kb))
{
- //Console.WriteLn("SuperVU reset mem");
+ Console.WriteLn("SuperVU%u: Recompiler cache reset...", vuindex);
SuperVUReset(0);
SuperVUReset(1);
- SuperVUReset(-1);
if (s_TotalVUCycles > 0)
{
// already executing, so return NULL
@@ -912,12 +887,12 @@ static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex)
#endif
// code generation
- x86SetPtr(s_recVUPtr);
+ xSetPtr(s_recVUPtr[vuindex]);
branch = 0;
SuperVURecompile();
- s_recVUPtr = x86Ptr;
+ s_recVUPtr[vuindex] = xGetPtr();
// set the function's range
VuFunctionHeader::RANGE r;
@@ -947,7 +922,7 @@ static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex)
}
s_listBlocks.clear();
- pxAssert(s_recVUPtr < s_recVUMem + VU_EXESIZE);
+ pxAssertDev(s_recVUPtr[vuindex] < s_recVUMem[vuindex]->GetPtrEnd(), "SuperVU recompiler cache exceeded! (possible memory corruption)");
return s_pFnHeader;
}
@@ -2697,18 +2672,18 @@ void SuperVUFlush(int p, int wait)
// executed only once per program
static u32* SuperVUStaticAlloc(u32 size)
{
- pxAssert(recVUStackPtr + size <= recVUStack + SUPERVU_STACKSIZE);
+ pxAssert(recVUStackPtr[s_vu] + size <= recVUStack[s_vu] + SUPERVU_STACKSIZE);
// always zero
- if (size == 4) *(u32*)recVUStackPtr = 0;
- else memset(recVUStackPtr, 0, size);
- recVUStackPtr += size;
- return (u32*)(recVUStackPtr - size);
+ if (size == 4) *(u32*)recVUStackPtr[s_vu] = 0;
+ else memset(recVUStackPtr[s_vu], 0, size);
+ recVUStackPtr[s_vu] += size;
+ return (u32*)(recVUStackPtr[s_vu] - size);
}
static void SuperVURecompile()
{
// save cpu state
- recVUStackPtr = recVUStack;
+ recVUStackPtr[s_vu] = recVUStack[s_vu];
_initXMMregs();
@@ -4617,9 +4592,9 @@ recSuperVU0::recSuperVU0()
IsInterpreter = false;
}
-void recSuperVU0::Allocate()
+void recSuperVU0::Reserve()
{
- SuperVUAlloc( 0 );
+ SuperVUAlloc(0);
}
void recSuperVU0::Shutdown() throw()
@@ -4645,6 +4620,15 @@ void recSuperVU0::Clear(u32 Addr, u32 Size)
SuperVUClear(Addr, Size, 0);
}
+uint recSuperVU0::GetCacheReserve() const
+{
+ return sVU_EXESIZE / _1mb;
+}
+
+void recSuperVU0::SetCacheReserve( uint reserveInMegs ) const
+{
+ //microVU0.cacheSize = reserveInMegs * _1mb;
+}
// --------------------------------------------------------------------------------------
// recSuperVU1 Interface
@@ -4655,9 +4639,9 @@ recSuperVU1::recSuperVU1()
IsInterpreter = false;
}
-void recSuperVU1::Allocate()
+void recSuperVU1::Reserve()
{
- SuperVUAlloc( 1 );
+ SuperVUAlloc(1);
}
void recSuperVU1::Shutdown() throw()
@@ -4670,6 +4654,16 @@ void recSuperVU1::Reset()
SuperVUReset( 1 );
}
+uint recSuperVU1::GetCacheReserve() const
+{
+ return sVU_EXESIZE / _1mb;
+}
+
+void recSuperVU1::SetCacheReserve( uint reserveInMegs ) const
+{
+ //microVU0.cacheSize = reserveInMegs * _1mb;
+}
+
#if 0
#include "sVU_Compare.h"
#else