mirror of https://github.com/PCSX2/pcsx2.git
newHostVM:
* Applied the new RecompiledCodeReserve to the VIF recompilers (saves another 4-8mb of memory, depending on game). * Fixed a bug in pxsFmt / FastFormatUnicode (string formatting). * Final round of error handling cleanups. (branch is basically ready for re-integration -- needs some testin for obvious/show stopping bugs, thanks!) git-svn-id: http://pcsx2.googlecode.com/svn/branches/newHostVM@4025 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
127ca00492
commit
63b254c8bd
|
@ -127,10 +127,9 @@ class VirtualMemoryReserve
|
|||
{
|
||||
DeclareNoncopyableObject( VirtualMemoryReserve );
|
||||
|
||||
public:
|
||||
wxString Name;
|
||||
|
||||
protected:
|
||||
wxString m_name;
|
||||
|
||||
// Default size of the reserve, in bytes. Can be specified when the object is contructed.
|
||||
// Is used as the reserve size when Reserve() is called, unless an override is specified
|
||||
// in the Reserve parameters.
|
||||
|
@ -149,7 +148,7 @@ protected:
|
|||
uptr m_pages_commited;
|
||||
|
||||
public:
|
||||
VirtualMemoryReserve( const wxString& name, size_t size = 0 );
|
||||
VirtualMemoryReserve( const wxString& name=wxEmptyString, size_t size = 0 );
|
||||
virtual ~VirtualMemoryReserve() throw()
|
||||
{
|
||||
Release();
|
||||
|
@ -167,7 +166,7 @@ public:
|
|||
virtual bool Commit();
|
||||
|
||||
bool IsOk() const { return m_baseptr != NULL; }
|
||||
wxString GetName() const { return Name; }
|
||||
wxString GetName() const { return m_name; }
|
||||
|
||||
uptr GetReserveSizeInBytes() const { return m_pages_reserved * __pagesize; }
|
||||
uptr GetReserveSizeInPages() const { return m_pages_reserved; }
|
||||
|
@ -179,6 +178,7 @@ public:
|
|||
u8* GetPtrEnd() { return (u8*)m_baseptr + (m_pages_reserved * __pagesize); }
|
||||
const u8* GetPtrEnd() const { return (u8*)m_baseptr + (m_pages_reserved * __pagesize); }
|
||||
|
||||
VirtualMemoryReserve& SetName( const wxString& newname );
|
||||
VirtualMemoryReserve& SetBaseAddr( uptr newaddr );
|
||||
VirtualMemoryReserve& SetPageAccessOnCommit( const PageProtectionMode& mode );
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ static __ri void format_that_ascii_mess( CharBufferType& buffer, uint writepos,
|
|||
|
||||
len += writepos;
|
||||
if (len < size) break;
|
||||
buffer.Alloc( len + 128 );
|
||||
buffer.Resize( len + 128 );
|
||||
};
|
||||
|
||||
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
||||
|
@ -205,7 +205,7 @@ static __ri uint format_that_unicode_mess( CharBufferType& buffer, uint writepos
|
|||
|
||||
len += writepos;
|
||||
if (len < size) return len;
|
||||
buffer.Alloc( (len + 128) * sizeof(wxChar) );
|
||||
buffer.Resize( (len + 128) * sizeof(wxChar) );
|
||||
};
|
||||
|
||||
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
||||
|
|
|
@ -71,7 +71,7 @@ void SrcType_PageFault::_DispatchRaw( ListenerIterator iter, const ListenerItera
|
|||
// VirtualMemoryReserve (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
VirtualMemoryReserve::VirtualMemoryReserve( const wxString& name, size_t size )
|
||||
: Name( name )
|
||||
: m_name( name )
|
||||
{
|
||||
m_defsize = size;
|
||||
|
||||
|
@ -81,6 +81,12 @@ VirtualMemoryReserve::VirtualMemoryReserve( const wxString& name, size_t size )
|
|||
m_prot_mode = PageAccess_None();
|
||||
}
|
||||
|
||||
VirtualMemoryReserve& VirtualMemoryReserve::SetName( const wxString& newname )
|
||||
{
|
||||
m_name = newname;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VirtualMemoryReserve& VirtualMemoryReserve::SetBaseAddr( uptr newaddr )
|
||||
{
|
||||
if (!pxAssertDev(!m_pages_reserved, "Invalid object state: you must release the virtual memory reserve prior to changing its base address!")) return *this;
|
||||
|
@ -124,7 +130,7 @@ void* VirtualMemoryReserve::Reserve( size_t size, uptr base, uptr upper_bounds )
|
|||
if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds)))
|
||||
{
|
||||
DevCon.Warning( L"%s: host memory @ 0x%08x -> 0x%08x is unavailable; attempting to map elsewhere...",
|
||||
Name.c_str(), base, base + size );
|
||||
m_name.c_str(), base, base + size );
|
||||
|
||||
SafeSysMunmap(m_baseptr, reserved_bytes);
|
||||
|
||||
|
@ -143,9 +149,16 @@ void* VirtualMemoryReserve::Reserve( size_t size, uptr base, uptr upper_bounds )
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
FastFormatUnicode mbkb;
|
||||
uint mbytes = reserved_bytes / _1mb;
|
||||
if (mbytes)
|
||||
mbkb.Write( "[%umb]", mbytes );
|
||||
else
|
||||
mbkb.Write( "[%ukb]", reserved_bytes / 1024 );
|
||||
|
||||
DevCon.WriteLn( Color_Gray, L"%-32s @ 0x%08p -> 0x%08p %s", m_name.c_str(),
|
||||
m_baseptr, (uptr)m_baseptr+reserved_bytes, mbkb.c_str());
|
||||
|
||||
return m_baseptr;
|
||||
}
|
||||
|
@ -193,17 +206,17 @@ bool VirtualMemoryReserve::TryResize( uint newsize )
|
|||
uint toReservePages = newPages - m_pages_reserved;
|
||||
uint toReserveBytes = toReservePages * __pagesize;
|
||||
|
||||
DevCon.WriteLn( L"%-32s is being expanded by %u pages.", Name.c_str(), toReservePages);
|
||||
DevCon.WriteLn( L"%-32s is being expanded by %u pages.", m_name.c_str(), toReservePages);
|
||||
|
||||
m_baseptr = (void*)HostSys::MmapReserve((uptr)GetPtrEnd(), toReserveBytes);
|
||||
|
||||
if (!m_baseptr)
|
||||
{
|
||||
Console.Warning("%-32s could not be passively resized due to virtual memory conflict!");
|
||||
Console.Indent().Warning("(attempted to map memory @ 0x%08X -> 0x%08X", m_baseptr, (uptr)m_baseptr+toReserveBytes);
|
||||
Console.Indent().Warning("(attempted to map memory @ 0x%08p -> 0x%08p", m_baseptr, (uptr)m_baseptr+toReserveBytes);
|
||||
}
|
||||
|
||||
DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(),
|
||||
DevCon.WriteLn( Color_Gray, L"%-32s @ 0x%08p -> 0x%08p [%umb]", m_name.c_str(),
|
||||
m_baseptr, (uptr)m_baseptr+toReserveBytes, toReserveBytes / _1mb);
|
||||
}
|
||||
else if (newPages < m_pages_reserved)
|
||||
|
@ -213,11 +226,11 @@ bool VirtualMemoryReserve::TryResize( uint newsize )
|
|||
uint toRemovePages = m_pages_reserved - newPages;
|
||||
uint toRemoveBytes = toRemovePages * __pagesize;
|
||||
|
||||
DevCon.WriteLn( L"%-32s is being shrunk by %u pages.", Name.c_str(), toRemovePages);
|
||||
DevCon.WriteLn( L"%-32s is being shrunk by %u pages.", m_name.c_str(), toRemovePages);
|
||||
|
||||
HostSys::MmapResetPtr(GetPtrEnd(), toRemoveBytes);
|
||||
|
||||
DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(),
|
||||
DevCon.WriteLn( Color_Gray, L"%-32s @ 0x%08p -> 0x%08p [%umb]", m_name.c_str(),
|
||||
m_baseptr, (uptr)m_baseptr+toRemoveBytes, toRemoveBytes / _1mb);
|
||||
}
|
||||
|
||||
|
@ -244,7 +257,7 @@ void BaseVmReserveListener::CommitBlocks( uptr page, uint blocks )
|
|||
// physical ram or virtual memory.
|
||||
if (!HostSys::MmapCommitPtr(blockptr, blocksbytes, m_prot_mode))
|
||||
{
|
||||
throw Exception::OutOfMemory(Name)
|
||||
throw Exception::OutOfMemory(m_name)
|
||||
.SetDiagMsg(pxsFmt("An additional %u blocks @ 0x%08x were requested, but could not be committed!", blocks, blockptr));
|
||||
}
|
||||
|
||||
|
|
|
@ -541,7 +541,6 @@ set(pcsx2x86Headers
|
|||
x86/microVU_Tables.inl
|
||||
x86/microVU_Upper.inl
|
||||
x86/newVif.h
|
||||
x86/newVif_BlockBuffer.h
|
||||
x86/newVif_HashBucket.h
|
||||
x86/newVif_UnpackSSE.h
|
||||
x86/sVU_Compare.h
|
||||
|
|
|
@ -646,7 +646,6 @@
|
|||
<Unit filename="../x86/microVU_Tables.inl" />
|
||||
<Unit filename="../x86/microVU_Upper.inl" />
|
||||
<Unit filename="../x86/newVif.h" />
|
||||
<Unit filename="../x86/newVif_BlockBuffer.h" />
|
||||
<Unit filename="../x86/newVif_Dynarec.cpp" />
|
||||
<Unit filename="../x86/newVif_HashBucket.h" />
|
||||
<Unit filename="../x86/newVif_Unpack.cpp" />
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Common.h"
|
||||
#include "IopCommon.h"
|
||||
#include "VUmicro.h"
|
||||
#include "newVif.h"
|
||||
|
||||
#include "SamplProf.h"
|
||||
|
||||
|
@ -30,9 +31,6 @@
|
|||
#include "Utilities/MemsetFast.inl"
|
||||
|
||||
|
||||
extern void closeNewVif(int idx);
|
||||
extern void resetNewVif(int idx);
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// RecompiledCodeReserve (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -108,6 +106,23 @@ void RecompiledCodeReserve::OnCommittedBlock( void* block )
|
|||
}
|
||||
}
|
||||
|
||||
// This error message is shared by R5900, R3000, and microVU recompilers. It is not used by the
|
||||
// SuperVU recompiler, since it has its own customized message.
|
||||
void RecompiledCodeReserve::ThrowIfNotOk() const
|
||||
{
|
||||
if (IsOk()) return;
|
||||
|
||||
throw Exception::OutOfMemory(m_name)
|
||||
.SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." ))
|
||||
.SetUserMsg( pxE( ".Error:Recompiler:VirtualMemoryAlloc",
|
||||
L"This recompiler was unable to reserve contiguous memory required for internal caches. "
|
||||
L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, "
|
||||
L"or by another program that is hogging a lot of memory. You can also try reducing the default "
|
||||
L"cache sizes for all PCSX2 recompilers, found under Host Settings."
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
void SysOutOfMemory_EmergencyResponse(uptr blocksize)
|
||||
{
|
||||
// An out of memory error occurred. All we can try to do in response is reset the various
|
||||
|
@ -346,11 +361,15 @@ void SysMainMemory::ReserveAll()
|
|||
{
|
||||
pxInstallSignalHandler();
|
||||
|
||||
DevCon.WriteLn( "PS2vm: Mapping host memory for all virtual systems..." );
|
||||
DevCon.WriteLn( Color_StrongBlue, "Mapping host memory for virtual systems..." );
|
||||
ConsoleIndentScope indent(1);
|
||||
|
||||
m_ee.Reserve();
|
||||
m_iop.Reserve();
|
||||
m_vu.Reserve();
|
||||
|
||||
reserveNewVif(0);
|
||||
reserveNewVif(1);
|
||||
}
|
||||
|
||||
void SysMainMemory::CommitAll()
|
||||
|
@ -358,7 +377,8 @@ void SysMainMemory::CommitAll()
|
|||
vtlb_Core_Alloc();
|
||||
if (m_ee.IsCommitted() && m_iop.IsCommitted() && m_vu.IsCommitted()) return;
|
||||
|
||||
DevCon.WriteLn( "PS2vm: Allocating host memory for all virtual systems..." );
|
||||
DevCon.WriteLn( Color_StrongBlue, "Allocating host memory for virtual systems..." );
|
||||
ConsoleIndentScope indent(1);
|
||||
|
||||
m_ee.Commit();
|
||||
m_iop.Commit();
|
||||
|
@ -370,23 +390,30 @@ void SysMainMemory::ResetAll()
|
|||
{
|
||||
CommitAll();
|
||||
|
||||
DevCon.WriteLn( "PS2vm: Resetting host memory for all virtual systems..." );
|
||||
DevCon.WriteLn( Color_StrongBlue, "Resetting host memory for virtual systems..." );
|
||||
ConsoleIndentScope indent(1);
|
||||
|
||||
m_ee.Reset();
|
||||
m_iop.Reset();
|
||||
m_vu.Reset();
|
||||
|
||||
// Note: newVif is reset as part of other VIF structures.
|
||||
}
|
||||
|
||||
void SysMainMemory::DecommitAll()
|
||||
{
|
||||
if (!m_ee.IsCommitted() && !m_iop.IsCommitted() && !m_vu.IsCommitted()) return;
|
||||
|
||||
Console.WriteLn( "PS2vm: Decommitting host memory for all virtual systems..." );
|
||||
Console.WriteLn( Color_Blue, "Decommitting host memory for virtual systems..." );
|
||||
ConsoleIndentScope indent(1);
|
||||
|
||||
m_ee.Decommit();
|
||||
m_iop.Decommit();
|
||||
m_vu.Decommit();
|
||||
|
||||
closeNewVif(0);
|
||||
closeNewVif(1);
|
||||
|
||||
vtlb_Core_Free();
|
||||
}
|
||||
|
||||
|
@ -394,10 +421,14 @@ void SysMainMemory::ReleaseAll()
|
|||
{
|
||||
DecommitAll();
|
||||
|
||||
Console.WriteLn( "PS2vm: Releasing host memory maps for all virtual systems..." );
|
||||
Console.WriteLn( Color_Blue, "Releasing host memory maps for virtual systems..." );
|
||||
ConsoleIndentScope indent(1);
|
||||
|
||||
vtlb_Core_Free(); // Just to be sure... (calling order could result in it getting missed during Decommit).
|
||||
|
||||
releaseNewVif(0);
|
||||
releaseNewVif(1);
|
||||
|
||||
m_ee.Decommit();
|
||||
m_iop.Decommit();
|
||||
m_vu.Decommit();
|
||||
|
@ -411,7 +442,8 @@ void SysMainMemory::ReleaseAll()
|
|||
// --------------------------------------------------------------------------------------
|
||||
SysCpuProviderPack::SysCpuProviderPack()
|
||||
{
|
||||
Console.WriteLn( "Reserving memory for recompilers..." );
|
||||
Console.WriteLn( Color_StrongBlue, "Reserving memory for recompilers..." );
|
||||
ConsoleIndentScope indent(1);
|
||||
|
||||
CpuProviders = new CpuInitializerSet();
|
||||
|
||||
|
@ -453,9 +485,6 @@ void SysCpuProviderPack::CleanupMess() throw()
|
|||
{
|
||||
try
|
||||
{
|
||||
closeNewVif(0);
|
||||
closeNewVif(1);
|
||||
|
||||
psxRec.Shutdown();
|
||||
recCpu.Shutdown();
|
||||
}
|
||||
|
@ -574,5 +603,5 @@ wxString SysGetDiscID()
|
|||
// region and revision).
|
||||
}
|
||||
|
||||
return wxsFormat( L"%8.8x", ElfCRC );
|
||||
return pxsFmt( L"%08x", ElfCRC );
|
||||
}
|
||||
|
|
|
@ -61,11 +61,18 @@ namespace HostMemoryMap
|
|||
// IOP recompiler code cache area (16 or 32mb)
|
||||
static const uptr IOPrec = 0x34000000;
|
||||
|
||||
// newVif0 recompiler code cache area (16mb)
|
||||
static const uptr VIF0rec = 0x36000000;
|
||||
|
||||
// newVif1 recompiler code cache area (32mb)
|
||||
static const uptr VIF1rec = 0x38000000;
|
||||
|
||||
// microVU1 recompiler code cache area (32 or 64mb)
|
||||
static const uptr mVU0rec = 0x38000000;
|
||||
static const uptr mVU0rec = 0x3C000000;
|
||||
|
||||
// microVU0 recompiler code cache area (64mb)
|
||||
static const uptr mVU1rec = 0x40000000;
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -37,7 +37,7 @@ protected:
|
|||
bool m_profiler_registered;
|
||||
|
||||
public:
|
||||
RecompiledCodeReserve( const wxString& name, uint defCommit = 0 );
|
||||
RecompiledCodeReserve( const wxString& name=wxEmptyString, uint defCommit = 0 );
|
||||
virtual ~RecompiledCodeReserve() throw();
|
||||
|
||||
virtual void* Reserve( size_t size, uptr base=0, uptr upper_bounds=0 );
|
||||
|
@ -48,6 +48,8 @@ public:
|
|||
{
|
||||
return SetProfilerName( fromUTF8(shortname) );
|
||||
}
|
||||
|
||||
void ThrowIfNotOk() const;
|
||||
|
||||
operator void*() { return m_baseptr; }
|
||||
operator const void*() const { return m_baseptr; }
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
class StackDump : public wxStackWalker
|
||||
{
|
||||
protected:
|
||||
wxString m_stackTrace;
|
||||
wxString m_srcFuncName;
|
||||
bool m_ignoreDone;
|
||||
int m_skipped;
|
||||
FastFormatUnicode m_stackTrace;
|
||||
wxString m_srcFuncName;
|
||||
bool m_ignoreDone;
|
||||
int m_skipped;
|
||||
|
||||
public:
|
||||
StackDump( const FnChar_t* src_function_name )
|
||||
|
@ -37,17 +37,12 @@ public:
|
|||
m_skipped = 0;
|
||||
}
|
||||
|
||||
const wxString& GetStackTrace() const { return m_stackTrace; }
|
||||
const wxChar* GetStackTrace() const { return m_stackTrace.c_str(); }
|
||||
|
||||
protected:
|
||||
virtual void OnStackFrame(const wxStackFrame& frame)
|
||||
{
|
||||
wxString name( frame.GetName() );
|
||||
if( name.IsEmpty() )
|
||||
{
|
||||
name = wxsFormat( L"%p ", frame.GetAddress() );
|
||||
}
|
||||
/*else if( m_srcFuncName.IsEmpty() || m_srcFuncName == name )
|
||||
/*if( m_srcFuncName.IsEmpty() || m_srcFuncName == name )
|
||||
{
|
||||
// FIXME: This logic isn't reliable yet.
|
||||
// It's possible for our debug information to not match the function names returned by
|
||||
|
@ -71,27 +66,25 @@ protected:
|
|||
return;
|
||||
}*/
|
||||
|
||||
//wxString briefName;
|
||||
wxString essenName;
|
||||
m_stackTrace.Write(pxsFmt( L"[%02d]", frame.GetLevel()-m_skipped));
|
||||
|
||||
if (!frame.GetName().IsEmpty())
|
||||
m_stackTrace.Write(pxsFmt( L" %-44s", frame.GetName().c_str() ));
|
||||
else
|
||||
m_stackTrace.Write(pxsFmt( L" 0x%-42p", frame.GetAddress() ));
|
||||
|
||||
if( frame.HasSourceLocation() )
|
||||
{
|
||||
wxFileName wxfn(frame.GetFileName());
|
||||
//briefName.Printf( L"(%s:%d)", wxfn.GetFullName().c_str(), frame.GetLine() );
|
||||
|
||||
wxfn.SetVolume( wxEmptyString );
|
||||
//int count = wxfn.GetDirCount();
|
||||
for( int i=0; i<2; ++i )
|
||||
wxfn.RemoveDir(0);
|
||||
|
||||
essenName.Printf( L"%s:%d", wxfn.GetFullPath().c_str(), frame.GetLine() );
|
||||
m_stackTrace.Write( L" %s:%d", wxfn.GetFullPath().c_str(), frame.GetLine() );
|
||||
}
|
||||
|
||||
m_stackTrace += pxsFmt( L"[%02d] %-44s %s\n",
|
||||
frame.GetLevel()-m_skipped,
|
||||
name.c_str(),
|
||||
essenName.c_str()
|
||||
);
|
||||
|
||||
m_stackTrace.Write(L"\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -839,10 +839,6 @@
|
|||
RelativePath="..\..\x86\newVif.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\newVif_BlockBuffer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\newVif_HashBucket.h"
|
||||
>
|
||||
|
|
|
@ -757,8 +757,6 @@ static const uint m_recBlockAllocSize =
|
|||
|
||||
static void recReserveCache()
|
||||
{
|
||||
extern wxString GetMsg_RecVmFailed();
|
||||
|
||||
if (!recMem) recMem = new RecompiledCodeReserve(L"R3000A Recompiler Cache", _1mb * 2);
|
||||
recMem->SetProfilerName("IOPrec");
|
||||
|
||||
|
@ -771,12 +769,7 @@ static void recReserveCache()
|
|||
m_ConfiguredCacheReserve /= 2;
|
||||
}
|
||||
|
||||
if (!recMem->IsOk())
|
||||
{
|
||||
throw Exception::VirtualMemoryMapConflict(recMem->GetName())
|
||||
.SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." ))
|
||||
.SetUserMsg(GetMsg_RecVmFailed());
|
||||
}
|
||||
recMem->ThrowIfNotOk();
|
||||
}
|
||||
|
||||
static void recReserve()
|
||||
|
|
|
@ -578,18 +578,6 @@ static void recThrowHardwareDeficiency( const wxChar* extFail )
|
|||
.SetUserMsg(pxsFmt(_("%s Extensions not found. The R5900-32 recompiler requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail ));
|
||||
}
|
||||
|
||||
// This error message is shared by R5900, R3000, and microVU recompilers. It is not used by the
|
||||
// SuperVU recompiler, since it has its own customized message.
|
||||
wxString GetMsg_RecVmFailed()
|
||||
{
|
||||
return pxE( ".Error:Recompiler:VirtualMemoryAlloc",
|
||||
L"This recompiler was unable to reserve contiguous memory required for internal caches. "
|
||||
L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, "
|
||||
L"or by another program that is hogging a lot of memory. You can also try reducing the default "
|
||||
L"cache sizes for all PCSX2 recompilers, found under Host Settings."
|
||||
);
|
||||
}
|
||||
|
||||
static void recReserveCache()
|
||||
{
|
||||
if (!recMem) recMem = new RecompiledCodeReserve(L"R5900-32 Recompiler Cache", _1mb * 4);
|
||||
|
@ -604,12 +592,7 @@ static void recReserveCache()
|
|||
m_ConfiguredCacheReserve /= 2;
|
||||
}
|
||||
|
||||
if (!recMem->IsOk())
|
||||
{
|
||||
throw Exception::VirtualMemoryMapConflict(recMem->GetName())
|
||||
.SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." ))
|
||||
.SetUserMsg(GetMsg_RecVmFailed());
|
||||
}
|
||||
recMem->ThrowIfNotOk();
|
||||
}
|
||||
|
||||
static void recReserve()
|
||||
|
|
|
@ -94,8 +94,7 @@ void microVU::reserveCache()
|
|||
(u8*)cache_reserve->Reserve( cacheSize * _1mb, HostMemoryMap::mVU1rec ) :
|
||||
(u8*)cache_reserve->Reserve( cacheSize * _1mb, HostMemoryMap::mVU0rec );
|
||||
|
||||
if(!cache_reserve->IsOk())
|
||||
throw Exception::VirtualMemoryMapConflict().SetDiagMsg(pxsFmt( L"Micro VU%u Recompiler Cache", index ));
|
||||
cache_reserve->ThrowIfNotOk();
|
||||
}
|
||||
|
||||
// Only run this once per VU! ;)
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "VU.h"
|
||||
|
||||
#include "x86emitter/x86emitter.h"
|
||||
#include "RecTypes.h"
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
#define aMax(x, y) std::max(x,y)
|
||||
|
@ -28,13 +30,14 @@ using namespace x86Emitter;
|
|||
typedef u32 (__fastcall *nVifCall)(void*, const void*);
|
||||
typedef void (__fastcall *nVifrecCall)(uptr dest, uptr src);
|
||||
|
||||
#include "newVif_BlockBuffer.h"
|
||||
#include "newVif_HashBucket.h"
|
||||
|
||||
extern void mVUmergeRegs(const xRegisterSSE& dest, const xRegisterSSE& src, int xyzw, bool modXYZW = 0);
|
||||
extern void _nVifUnpack (int idx, const u8* data, uint mode, bool isFill);
|
||||
extern void dVifReserve (int idx);
|
||||
extern void dVifReset (int idx);
|
||||
extern void dVifClose (int idx);
|
||||
extern void dVifRelease (int idx);
|
||||
extern void VifUnpackSSE_Init();
|
||||
|
||||
_vifT extern void dVifUnpack (const u8* data, bool isFill);
|
||||
|
@ -76,23 +79,25 @@ struct nVifStruct {
|
|||
u32 bSize; // Size of 'buffer'
|
||||
u32 bPtr;
|
||||
|
||||
u32 idx; // VIF0 or VIF1
|
||||
u8* recPtr; // Cur Pos to recompile to
|
||||
u8* recEnd; // 'Safe' End of Rec Cache
|
||||
BlockBuffer* vifCache; // Block Buffer
|
||||
uint recReserveSizeMB; // reserve size, in megabytes.
|
||||
RecompiledCodeReserve* recReserve;
|
||||
u8* recWritePtr; // current write pos into the reserve
|
||||
|
||||
HashBucket<_tParams>* vifBlocks; // Vif Blocks
|
||||
int numBlocks; // # of Blocks Recompiled
|
||||
|
||||
nVifStruct()
|
||||
{
|
||||
vifCache = NULL;
|
||||
vifBlocks = NULL;
|
||||
numBlocks = 0;
|
||||
recPtr = NULL;
|
||||
recEnd = NULL;
|
||||
}
|
||||
|
||||
// VIF0 or VIF1 - provided for debugging helpfulness only, and is generally unused.
|
||||
// (templates are used for most or all VIF indexing)
|
||||
u32 idx;
|
||||
|
||||
nVifStruct();
|
||||
};
|
||||
|
||||
extern void reserveNewVif(int idx);
|
||||
extern void closeNewVif(int idx);
|
||||
extern void resetNewVif(int idx);
|
||||
extern void releaseNewVif(int idx);
|
||||
|
||||
extern __aligned16 nVifStruct nVif[2];
|
||||
extern __aligned16 nVifCall nVifUpk[(2*2*16)*4]; // ([USN][Masking][Unpack Type]) [curCycle]
|
||||
extern __aligned16 u32 nVifMask[3][4][4]; // [MaskNumber][CycleNumber][Vector]
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Allocates a Chunk of memory using SysMmapEx...
|
||||
// This memory can be used to write recompiled code to.
|
||||
// Its got basic resizing/growing ability too, but probably
|
||||
// won't be too useful since growing the block buffer will
|
||||
// invalidate any pointers pointing to the old block buffer.
|
||||
// (so remember to invalidate those block pointers :D)
|
||||
// It also deallocates itself on 'delete', so you can
|
||||
// just use 'new' and 'delete' for initialization and
|
||||
// deletion/cleanup respectfully...
|
||||
class BlockBuffer {
|
||||
protected:
|
||||
u32 mSize; // Cur Size (in bytes)
|
||||
u32 mSizeT; // Total Size (in bytes)
|
||||
u32 mGrowBy; // amount to grow by when buffer fills (in bytes)
|
||||
u8* mData; // Data Ptr (allocated via SysMmap)
|
||||
|
||||
void alloc(int size) {
|
||||
mData = SysMmapEx(0, size, 0, "nVif_BlockBuffer");
|
||||
if (!mData) throw Exception::OutOfMemory(L"nVif recompiled code buffer (nVif_BlockBuffer)");
|
||||
clear();
|
||||
}
|
||||
void dealloc(u8* &dPtr, int size) {
|
||||
SafeSysMunmap( dPtr, size );
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~BlockBuffer() throw() {
|
||||
dealloc(mData, mSizeT);
|
||||
}
|
||||
|
||||
BlockBuffer(u32 tSize, u32 growby=_1mb*2) {
|
||||
mSizeT = tSize;
|
||||
mGrowBy = growby;
|
||||
mSize = 0;
|
||||
alloc(mSizeT);
|
||||
}
|
||||
|
||||
void append(void *addr, u32 size) {
|
||||
if ((mSize + size) > mSizeT) grow(mSizeT + mGrowBy);
|
||||
memcpy_fast(&mData[mSize], addr, size);
|
||||
mSize += size;
|
||||
}
|
||||
|
||||
// Increases the allocation size. Warning: Unlike 'realloc' this function will
|
||||
// CLEAR all contents of the buffer. This is because copying contents of recompiled
|
||||
// caches is mostly useless since it invalidates any pointers into the block.
|
||||
// (code relocation techniques are possible, but are difficult, potentially slow,
|
||||
// and easily bug prone. Not recommended at this time). --air
|
||||
void grow(u32 newSize) {
|
||||
pxAssume( newSize > mSizeT );
|
||||
u8* temp = mData;
|
||||
alloc(newSize);
|
||||
dealloc(temp, mSizeT);
|
||||
clear();
|
||||
mSizeT = newSize;
|
||||
}
|
||||
|
||||
// clears the entire buffer to recompiler fill (0xcc), and sets mSize to 0.
|
||||
// (indicating none of the buffer is allocated).
|
||||
void clear() {
|
||||
if( mSize == 0 ) return; // no clears needed if nothing's been written/modified
|
||||
mSize = 0;
|
||||
memset(mData, 0xcc, mSizeT);
|
||||
}
|
||||
|
||||
u32 getCurSize() { return mSize; }
|
||||
u32 getAllocSize() { return mSizeT; }
|
||||
u8* getBlock() { return mData; }
|
||||
};
|
|
@ -22,34 +22,37 @@
|
|||
|
||||
static __aligned16 nVifBlock _vBlock = {0};
|
||||
|
||||
void dVifReset(int idx) {
|
||||
// If the VIF cache is greater than 12mb, then it's due for a complete reset back
|
||||
// down to a reasonable starting point of 4mb.
|
||||
if( nVif[idx].vifCache && (nVif[idx].vifCache->getAllocSize() > _1mb*12) )
|
||||
safe_delete(nVif[idx].vifCache);
|
||||
void dVifReserve(int idx)
|
||||
{
|
||||
if (!nVif[idx].recReserve)
|
||||
nVif[idx].recReserve = new RecompiledCodeReserve(pxsFmt(L"VIF%u Unpack Recompiler Cache", idx));
|
||||
|
||||
if( !nVif[idx].vifCache )
|
||||
nVif[idx].vifCache = new BlockBuffer(_1mb*4);
|
||||
else
|
||||
nVif[idx].vifCache->clear();
|
||||
nVif[idx].recReserve->Reserve( nVif[idx].recReserveSizeMB * _1mb, idx ? HostMemoryMap::VIF1rec : HostMemoryMap::VIF0rec );
|
||||
}
|
||||
|
||||
void dVifReset(int idx) {
|
||||
|
||||
if( !nVif[idx].vifBlocks )
|
||||
nVif[idx].vifBlocks = new HashBucket<_tParams>();
|
||||
else
|
||||
nVif[idx].vifBlocks->clear();
|
||||
|
||||
nVif[idx].numBlocks = 0;
|
||||
|
||||
nVif[idx].recPtr = nVif[idx].vifCache->getBlock();
|
||||
nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone
|
||||
nVif[idx].recReserve->Reset();
|
||||
nVif[idx].numBlocks = 0;
|
||||
nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr();
|
||||
}
|
||||
|
||||
void dVifClose(int idx) {
|
||||
nVif[idx].numBlocks = 0;
|
||||
safe_delete(nVif[idx].vifCache);
|
||||
nVif[idx].recReserve->Reset();
|
||||
|
||||
safe_delete(nVif[idx].vifBlocks);
|
||||
}
|
||||
|
||||
void dVifRelease(int idx) {
|
||||
safe_delete(nVif[idx].recReserve);
|
||||
}
|
||||
|
||||
VifUnpackSSE_Dynarec::VifUnpackSSE_Dynarec(const nVifStruct& vif_, const nVifBlock& vifBlock_)
|
||||
: v(vif_)
|
||||
, vB(vifBlock_)
|
||||
|
@ -223,11 +226,10 @@ _vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, bool isFill) {
|
|||
// [TODO] : Finish implementing support for VIF's growable recBlocks buffer. Currently
|
||||
// it clears the buffer only.
|
||||
static __fi void dVifRecLimit(int idx) {
|
||||
if (nVif[idx].recPtr > nVif[idx].recEnd) {
|
||||
DevCon.WriteLn("nVif Rec - Out of Rec Cache! [%x > %x]", nVif[idx].recPtr, nVif[idx].recEnd);
|
||||
nVif[idx].vifBlocks->clear();
|
||||
nVif[idx].recPtr = nVif[idx].vifCache->getBlock();
|
||||
nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone
|
||||
if (nVif[idx].recWritePtr > (nVif[idx].recReserve->GetPtrEnd() - _256kb)) {
|
||||
DevCon.WriteLn("nVif Recompiler Cache Reset! [0x%08x > 0x%08x]", nVif[idx].recWritePtr, nVif[idx].recReserve->GetPtrEnd());
|
||||
nVif[idx].recReserve->Reset();
|
||||
nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,11 +279,11 @@ _vifT __fi void dVifUnpack(const u8* data, bool isFill) {
|
|||
|
||||
if (dVifExecuteUnpack<idx>(data, isFill)) return;
|
||||
|
||||
xSetPtr(v.recPtr);
|
||||
xSetPtr(v.recWritePtr);
|
||||
_vBlock.startPtr = (uptr)xGetAlignedCallTarget();
|
||||
v.vifBlocks->add(_vBlock);
|
||||
VifUnpackSSE_Dynarec( v, _vBlock ).CompileRoutine();
|
||||
nVif[idx].recPtr = xGetPtr();
|
||||
nVif[idx].recWritePtr = xGetPtr();
|
||||
|
||||
// [TODO] : Ideally we should test recompile buffer limits prior to each instruction,
|
||||
// which would be safer and more memory efficient than using an 0.25 meg recEnd marker.
|
||||
|
|
|
@ -70,6 +70,19 @@ static const __aligned16 Fnptr_VifUnpackLoop UnpackLoopTable[2][2][2] = {
|
|||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
nVifStruct::nVifStruct()
|
||||
{
|
||||
vifBlocks = NULL;
|
||||
numBlocks = 0;
|
||||
|
||||
recReserveSizeMB = 8;
|
||||
}
|
||||
|
||||
void reserveNewVif(int idx)
|
||||
{
|
||||
if (newVifDynaRec) dVifReserve(idx);
|
||||
}
|
||||
|
||||
void resetNewVif(int idx)
|
||||
{
|
||||
// Safety Reset : Reassign all VIF structure info, just in case the VU1 pointers have
|
||||
|
@ -86,6 +99,10 @@ void closeNewVif(int idx) {
|
|||
if (newVifDynaRec) dVifClose(idx);
|
||||
}
|
||||
|
||||
void releaseNewVif(int idx) {
|
||||
if (newVifDynaRec) dVifRelease(idx);
|
||||
}
|
||||
|
||||
static __fi u8* getVUptr(uint idx, int offset) {
|
||||
return (u8*)(vuRegs[idx].Mem + ( offset & (idx ? 0x3ff0 : 0xff0) ));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue