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:
Jake.Stine 2010-11-16 15:58:42 +00:00
parent 127ca00492
commit 63b254c8bd
17 changed files with 161 additions and 210 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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");
}
};

View File

@ -839,10 +839,6 @@
RelativePath="..\..\x86\newVif.h"
>
</File>
<File
RelativePath="..\..\x86\newVif_BlockBuffer.h"
>
</File>
<File
RelativePath="..\..\x86\newVif_HashBucket.h"
>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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