2009-09-08 12:08:10 +00:00
/* PCSX2 - PS2 Emulator for PCs
2010-05-03 14:08:02 +00:00
* Copyright (C) 2002-2010 PCSX2 Dev Team
2009-09-17 02:12:32 +00:00
*
2009-09-08 12:08:10 +00:00
* 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.
2009-02-09 21:15:56 +00:00
*
2009-09-08 12:08:10 +00:00
* 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.
2009-02-09 21:15:56 +00:00
*
2009-09-08 12:08:10 +00:00
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
2009-02-09 21:15:56 +00:00
*/
2009-09-17 02:12:32 +00:00
2009-02-09 21:15:56 +00:00
#include "PrecompiledHeader.h"
2009-11-14 12:02:56 +00:00
#include "Common.h"
2010-06-22 10:58:34 +00:00
#include "IopCommon.h"
2010-10-27 19:18:46 +00:00
#include "VUmicro.h"
2010-11-16 15:58:42 +00:00
#include "newVif.h"
2009-11-14 12:02:56 +00:00
2010-11-03 14:18:30 +00:00
#include "SamplProf.h"
2010-06-22 18:57:48 +00:00
#include "Elfheader.h"
2010-05-28 16:54:42 +00:00
2010-10-27 19:18:46 +00:00
#include "System/RecTypes.h"
#include "Utilities/MemsetFast.inl"
2010-10-22 16:23:52 +00:00
// --------------------------------------------------------------------------------------
2010-10-27 19:18:46 +00:00
// RecompiledCodeReserve (implementations)
2010-10-22 16:23:52 +00:00
// --------------------------------------------------------------------------------------
2010-11-03 14:18:30 +00:00
// Constructor!
// Parameters:
// name - a nice long name that accurately describes the contents of this reserve.
2010-10-22 16:23:52 +00:00
RecompiledCodeReserve :: RecompiledCodeReserve ( const wxString & name , uint defCommit )
2010-11-15 14:05:02 +00:00
: BaseVmReserveListener ( name )
2010-10-22 16:23:52 +00:00
{
2010-11-03 17:37:29 +00:00
m_blocksize = ( 1024 * 128 ) / __pagesize ;
2010-10-22 16:23:52 +00:00
m_prot_mode = PageAccess_Any ();
m_def_commit = defCommit / __pagesize ;
2010-11-03 14:18:30 +00:00
m_profiler_registered = false ;
2010-10-22 16:23:52 +00:00
}
2010-11-03 14:18:30 +00:00
RecompiledCodeReserve ::~ RecompiledCodeReserve () throw ()
{
_termProfiler ();
}
void RecompiledCodeReserve :: _registerProfiler ()
{
if ( m_profiler_name . IsEmpty () || ! IsOk ()) return ;
ProfilerRegisterSource ( m_profiler_name , m_baseptr , GetReserveSizeInBytes () );
m_profiler_registered = true ;
}
void RecompiledCodeReserve :: _termProfiler ()
{
if ( m_profiler_registered )
ProfilerTerminateSource ( m_profiler_name );
}
2010-11-03 17:37:29 +00:00
uint RecompiledCodeReserve :: _calcDefaultCommitInBlocks () const
{
return ( m_def_commit + m_blocksize - 1 ) / m_blocksize ;
}
2010-11-15 14:05:02 +00:00
void * RecompiledCodeReserve :: Reserve ( size_t size , uptr base , uptr upper_bounds )
2010-11-03 14:18:30 +00:00
{
2010-11-15 14:05:02 +00:00
if ( ! _parent :: Reserve ( size , base , upper_bounds )) return NULL ;
2010-11-03 14:18:30 +00:00
_registerProfiler ();
return m_baseptr ;
}
// Sets the abbreviated name used by the profiler. Name should be under 10 characters long.
// After a name has been set, a profiler source will be automatically registered and cleared
// in accordance with changes in the reserve area.
RecompiledCodeReserve & RecompiledCodeReserve :: SetProfilerName ( const wxString & shortname )
{
m_profiler_name = shortname ;
_registerProfiler ();
return * this ;
}
2010-10-22 16:23:52 +00:00
2010-11-03 17:37:29 +00:00
void RecompiledCodeReserve :: DoCommitAndProtect ( uptr page )
{
2010-11-15 14:05:02 +00:00
CommitBlocks ( page , ( m_pages_commited || ! m_def_commit ) ? 1 : _calcDefaultCommitInBlocks () );
2010-11-03 17:37:29 +00:00
}
2010-10-22 16:23:52 +00:00
void RecompiledCodeReserve :: OnCommittedBlock ( void * block )
{
if ( IsDevBuild )
{
// Clear the recompiled code block to 0xcc (INT3) -- this helps disasm tools show
// the assembly dump more cleanly. We don't clear the block on Release builds since
// it can add a noticeable amount of overhead to large block recompilations.
2010-11-03 17:37:29 +00:00
memset_sse_a < 0xcc > ( block , m_blocksize * __pagesize );
2010-10-22 16:23:52 +00:00
}
}
2010-11-16 15:58:42 +00:00
// 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." ))
2012-08-10 10:10:55 +00:00
. SetUserMsg ( pxE ( L "This recompiler was unable to reserve contiguous memory required for internal caches. This error can be caused by low virtual memory resources, such as a small or disabled swapfile, or by another program that is hogging a lot of memory. You can also try reducing the default cache sizes for all PCSX2 recompilers, found under Host Settings."
2010-11-16 15:58:42 +00:00
));
}
2010-11-05 01:33:01 +00:00
void SysOutOfMemory_EmergencyResponse ( uptr blocksize )
2010-10-22 16:23:52 +00:00
{
2010-11-05 01:33:01 +00:00
// An out of memory error occurred. All we can try to do in response is reset the various
// recompiler caches (which can sometimes total over 120megs, so it can be quite helpful).
// If the user is using interpreters, or if the memory allocation failure was on a very small
// allocation, then this code could fail; but that's fine. We're already trying harder than
// 99.995% of all programs ever written. -- air
2010-10-22 16:23:52 +00:00
2010-11-05 01:33:01 +00:00
if ( Cpu )
2010-10-22 16:23:52 +00:00
{
2010-12-12 06:38:17 +00:00
Cpu -> SetCacheReserve ( ( Cpu -> GetCacheReserve () * 2 ) / 3 );
2010-11-05 01:33:01 +00:00
Cpu -> Reset ();
2010-10-22 16:23:52 +00:00
}
2010-11-05 01:33:01 +00:00
if ( CpuVU0 )
{
2010-12-12 06:38:17 +00:00
CpuVU0 -> SetCacheReserve ( ( CpuVU0 -> GetCacheReserve () * 2 ) / 3 );
2010-11-05 01:33:01 +00:00
CpuVU0 -> Reset ();
}
if ( CpuVU1 )
{
2010-12-12 06:38:17 +00:00
CpuVU1 -> SetCacheReserve ( ( CpuVU1 -> GetCacheReserve () * 2 ) / 3 );
2010-11-05 01:33:01 +00:00
CpuVU1 -> Reset ();
}
if ( psxCpu )
{
2010-12-12 06:38:17 +00:00
psxCpu -> SetCacheReserve ( ( psxCpu -> GetCacheReserve () * 2 ) / 3 );
2010-11-05 01:33:01 +00:00
psxCpu -> Reset ();
2010-10-22 16:23:52 +00:00
}
}
2010-01-22 15:22:01 +00:00
2010-11-05 01:33:01 +00:00
2011-04-09 08:39:54 +00:00
#if _MSC_VER || defined(LINUX_PRINT_SVN_NUMBER)
2009-09-13 17:11:35 +00:00
# include "svnrev.h"
2009-09-04 01:56:33 +00:00
#endif
2009-07-15 01:17:28 +00:00
2009-09-22 11:50:27 +00:00
const Pcsx2Config EmuConfig ;
2009-08-04 08:21:10 +00:00
2009-12-03 15:51:39 +00:00
// Provides an accessor for quick modification of GS options. All GS options are allowed to be
// changed "on the fly" by the *main/gui thread only*.
Pcsx2Config :: GSOptions & SetGSConfig ()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.GS detected" );
2010-04-27 13:12:03 +00:00
AffinityAssert_AllowFrom_MainUI ();
2009-12-03 15:51:39 +00:00
return const_cast < Pcsx2Config :: GSOptions &> ( EmuConfig . GS );
}
2010-05-18 23:52:29 +00:00
// Provides an accessor for quick modification of Recompiler options.
// Used by loadGameSettings() to set clamp modes via database at game startup.
Pcsx2Config :: RecompilerOptions & SetRecompilerConfig ()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.Gamefixes detected" );
AffinityAssert_AllowFrom_MainUI ();
return const_cast < Pcsx2Config :: RecompilerOptions &> ( EmuConfig . Cpu . Recompiler );
}
2010-05-17 22:38:36 +00:00
// Provides an accessor for quick modification of Gamefix options.
// Used by loadGameSettings() to set gamefixes via database at game startup.
Pcsx2Config :: GamefixOptions & SetGameFixConfig ()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.Gamefixes detected" );
AffinityAssert_AllowFrom_MainUI ();
return const_cast < Pcsx2Config :: GamefixOptions &> ( EmuConfig . Gamefixes );
}
2009-12-03 15:51:39 +00:00
TraceLogFilters & SetTraceConfig ()
{
//DbgCon.WriteLn( "Direct modification of EmuConfig.TraceLog detected" );
2010-04-27 13:12:03 +00:00
AffinityAssert_AllowFrom_MainUI ();
2009-12-03 15:51:39 +00:00
return const_cast < TraceLogFilters &> ( EmuConfig . Trace );
}
2009-02-09 21:15:56 +00:00
// This function should be called once during program execution.
2009-12-14 12:18:55 +00:00
void SysLogMachineCaps ()
2009-02-09 21:15:56 +00:00
{
2010-11-23 21:32:52 +00:00
Console . WriteLn ( Color_StrongGreen , "PCSX2 %u.%u.%u.r%d %s - compiled on " __DATE__ ,
PCSX2_VersionHi , PCSX2_VersionMid , PCSX2_VersionLo ,
2009-09-06 05:21:07 +00:00
SVN_REV , SVN_MODS ? "(modded)" : ""
);
2009-09-16 17:23:02 +00:00
2009-10-29 13:32:40 +00:00
Console . WriteLn ( "Savestate version: 0x%x" , g_SaveVersion );
Console . Newline ();
2009-02-09 21:15:56 +00:00
2010-11-23 21:32:52 +00:00
Console . WriteLn ( Color_StrongBlack , "Host Machine Init:" );
Console . Indent (). WriteLn (
2010-12-02 08:15:11 +00:00
L "Operating System = %s \n "
L "Physical RAM = %u MB" ,
2010-11-23 21:32:52 +00:00
GetOSVersionString (). c_str (),
( u32 )( GetPhysicalMemory () / _1mb )
);
2010-04-25 00:31:27 +00:00
2010-06-01 03:33:51 +00:00
u32 speed = x86caps . CalculateMHz ();
2009-11-15 06:26:55 +00:00
Console . Indent (). WriteLn (
2010-11-23 21:32:52 +00:00
L "CPU name = %s \n "
2010-12-02 08:15:11 +00:00
L "Vendor/Model = %s (stepping %02X) \n "
2010-11-23 21:32:52 +00:00
L "CPU speed = %u.%03u ghz (%u logical thread%s) \n "
2009-11-15 06:26:55 +00:00
L "x86PType = %s \n "
2010-11-23 21:32:52 +00:00
L "x86Flags = %08x %08x \n "
L "x86EFlags = %08x" ,
2009-10-29 13:32:40 +00:00
fromUTF8 ( x86caps . FamilyName ). Trim (). Trim ( false ). c_str (),
2010-11-23 21:32:52 +00:00
fromUTF8 ( x86caps . VendorName ). c_str (), x86caps . StepID ,
2010-06-01 03:33:51 +00:00
speed / 1000 , speed % 1000 ,
2010-11-23 21:32:52 +00:00
x86caps . LogicalCores , ( x86caps . LogicalCores == 1 ) ? L "" : L "s" ,
2010-06-01 03:33:51 +00:00
x86caps . GetTypeName (). c_str (),
2009-07-29 14:00:00 +00:00
x86caps . Flags , x86caps . Flags2 ,
x86caps . EFlags
2009-10-29 13:32:40 +00:00
);
2010-04-25 00:31:27 +00:00
2009-11-16 00:40:09 +00:00
Console . Newline ();
2009-09-17 02:12:32 +00:00
2009-09-16 17:23:02 +00:00
wxArrayString features [ 2 ]; // 2 lines, for readability!
2009-09-17 02:12:32 +00:00
2009-09-16 17:23:02 +00:00
if ( x86caps . hasMultimediaExtensions ) features [ 0 ]. Add ( L "MMX" );
if ( x86caps . hasStreamingSIMDExtensions ) features [ 0 ]. Add ( L "SSE" );
if ( x86caps . hasStreamingSIMD2Extensions ) features [ 0 ]. Add ( L "SSE2" );
if ( x86caps . hasStreamingSIMD3Extensions ) features [ 0 ]. Add ( L "SSE3" );
if ( x86caps . hasSupplementalStreamingSIMD3Extensions ) features [ 0 ]. Add ( L "SSSE3" );
if ( x86caps . hasStreamingSIMD4Extensions ) features [ 0 ]. Add ( L "SSE4.1" );
if ( x86caps . hasStreamingSIMD4Extensions2 ) features [ 0 ]. Add ( L "SSE4.2" );
2011-02-12 21:45:16 +00:00
if ( x86caps . hasAVX ) features [ 0 ]. Add ( L "AVX" );
if ( x86caps . hasFMA ) features [ 0 ]. Add ( L "FMA" );
2009-02-09 21:15:56 +00:00
2009-09-16 17:23:02 +00:00
if ( x86caps . hasMultimediaExtensionsExt ) features [ 1 ]. Add ( L "MMX2 " );
if ( x86caps . has3DNOWInstructionExtensions ) features [ 1 ]. Add ( L "3DNOW " );
if ( x86caps . has3DNOWInstructionExtensionsExt ) features [ 1 ]. Add ( L "3DNOW2" );
if ( x86caps . hasStreamingSIMD4ExtensionsA ) features [ 1 ]. Add ( L "SSE4a " );
2009-02-09 21:15:56 +00:00
2010-06-30 03:21:59 +00:00
const wxString result [ 2 ] =
{
JoinString ( features [ 0 ], L ".. " ),
JoinString ( features [ 1 ], L ".. " )
};
2009-09-16 17:23:02 +00:00
2009-10-29 13:32:40 +00:00
Console . WriteLn ( Color_StrongBlack , L "x86 Features Detected:" );
2009-11-16 00:40:09 +00:00
Console . Indent (). WriteLn ( result [ 0 ] + ( result [ 1 ]. IsEmpty () ? L "" : ( L " \n " + result [ 1 ])) );
2009-11-15 06:26:55 +00:00
Console . Newline ();
2009-02-09 21:15:56 +00:00
}
2009-12-07 14:00:39 +00:00
template < typename CpuType >
class CpuInitializer
{
public :
2010-06-28 18:03:54 +00:00
ScopedPtr < CpuType > MyCpu ;
2010-10-18 01:40:49 +00:00
ScopedExcept ExThrown ;
2010-06-28 18:03:54 +00:00
2009-12-07 14:00:39 +00:00
CpuInitializer ();
virtual ~ CpuInitializer () throw ();
bool IsAvailable () const
{
return !! MyCpu ;
}
CpuType * GetPtr () { return MyCpu . GetPtr (); }
const CpuType * GetPtr () const { return MyCpu . GetPtr (); }
operator CpuType * () { return GetPtr (); }
operator const CpuType * () const { return GetPtr (); }
};
// --------------------------------------------------------------------------------------
// CpuInitializer Template
// --------------------------------------------------------------------------------------
// Helper for initializing various PCSX2 CPU providers, and handing errors and cleanup.
//
template < typename CpuType >
CpuInitializer < CpuType >:: CpuInitializer ()
{
try {
MyCpu = new CpuType ();
2010-10-27 19:18:46 +00:00
MyCpu -> Reserve ();
2009-12-07 14:00:39 +00:00
}
catch ( Exception :: RuntimeError & ex )
{
2009-12-14 12:18:55 +00:00
Console . Error ( L "CPU provider error: \n\t " + ex . FormatDiagnosticMessage () );
2010-06-28 18:03:54 +00:00
MyCpu = NULL ;
ExThrown = ex . Clone ();
2009-12-07 14:00:39 +00:00
}
catch ( std :: runtime_error & ex )
{
2009-12-14 12:18:55 +00:00
Console . Error ( L "CPU provider error (STL Exception) \n\t Details:" + fromUTF8 ( ex . what () ) );
2010-06-28 18:03:54 +00:00
MyCpu = NULL ;
ExThrown = new Exception :: RuntimeError ( ex );
2009-12-07 14:00:39 +00:00
}
}
template < typename CpuType >
CpuInitializer < CpuType >::~ CpuInitializer () throw ()
{
2010-10-27 19:18:46 +00:00
if ( MyCpu )
2009-12-07 14:00:39 +00:00
MyCpu -> Shutdown ();
}
2010-10-18 01:40:49 +00:00
// --------------------------------------------------------------------------------------
// CpuInitializerSet
// --------------------------------------------------------------------------------------
2009-12-07 14:00:39 +00:00
class CpuInitializerSet
{
public :
// Note: Allocate sVU first -- it's the most picky.
CpuInitializer < recSuperVU0 > superVU0 ;
CpuInitializer < recSuperVU1 > superVU1 ;
CpuInitializer < recMicroVU0 > microVU0 ;
CpuInitializer < recMicroVU1 > microVU1 ;
CpuInitializer < InterpVU0 > interpVU0 ;
CpuInitializer < InterpVU1 > interpVU1 ;
2010-04-25 00:31:27 +00:00
2009-12-07 14:00:39 +00:00
public :
CpuInitializerSet () {}
virtual ~ CpuInitializerSet () throw () {}
};
2009-09-16 17:23:02 +00:00
// returns the translated error message for the Virtual Machine failing to allocate!
static wxString GetMemoryErrorVM ()
2009-02-09 21:15:56 +00:00
{
2012-08-10 10:10:55 +00:00
return pxE ( L "PCSX2 is unable to allocate memory needed for the PS2 virtual machine. Close out some memory hogging background tasks and try again."
2009-09-16 17:23:02 +00:00
);
}
2009-02-09 21:15:56 +00:00
2010-10-22 19:47:02 +00:00
// --------------------------------------------------------------------------------------
// SysReserveVM (implementations)
// --------------------------------------------------------------------------------------
2010-11-15 14:05:02 +00:00
SysMainMemory :: SysMainMemory ()
2010-10-22 19:47:02 +00:00
{
}
2010-11-15 14:05:02 +00:00
SysMainMemory ::~ SysMainMemory () throw ()
2010-10-22 19:47:02 +00:00
{
2010-11-15 14:05:02 +00:00
ReleaseAll ();
2010-10-22 19:47:02 +00:00
}
2010-11-15 14:05:02 +00:00
void SysMainMemory :: ReserveAll ()
2010-10-22 19:47:02 +00:00
{
2010-11-15 14:05:02 +00:00
pxInstallSignalHandler ();
2010-11-16 15:58:42 +00:00
DevCon . WriteLn ( Color_StrongBlue , "Mapping host memory for virtual systems..." );
ConsoleIndentScope indent ( 1 );
2010-11-15 14:05:02 +00:00
m_ee . Reserve ();
m_iop . Reserve ();
m_vu . Reserve ();
2010-11-16 15:58:42 +00:00
reserveNewVif ( 0 );
reserveNewVif ( 1 );
2010-10-22 19:47:02 +00:00
}
2010-11-15 14:05:02 +00:00
void SysMainMemory :: CommitAll ()
2009-09-16 17:23:02 +00:00
{
2010-11-16 00:22:18 +00:00
vtlb_Core_Alloc ();
2010-11-15 14:05:02 +00:00
if ( m_ee . IsCommitted () && m_iop . IsCommitted () && m_vu . IsCommitted ()) return ;
2009-10-23 20:24:59 +00:00
2010-11-16 15:58:42 +00:00
DevCon . WriteLn ( Color_StrongBlue , "Allocating host memory for virtual systems..." );
ConsoleIndentScope indent ( 1 );
2009-09-16 17:23:02 +00:00
2010-11-15 14:05:02 +00:00
m_ee . Commit ();
m_iop . Commit ();
m_vu . Commit ();
2010-08-16 15:57:01 +00:00
}
2009-02-09 21:15:56 +00:00
2010-11-15 14:05:02 +00:00
void SysMainMemory :: ResetAll ()
2010-08-16 15:57:01 +00:00
{
2010-11-15 14:05:02 +00:00
CommitAll ();
2010-11-16 15:58:42 +00:00
DevCon . WriteLn ( Color_StrongBlue , "Resetting host memory for virtual systems..." );
ConsoleIndentScope indent ( 1 );
2010-11-15 14:05:02 +00:00
m_ee . Reset ();
m_iop . Reset ();
m_vu . Reset ();
2010-12-30 06:21:07 +00:00
2010-11-16 15:58:42 +00:00
// Note: newVif is reset as part of other VIF structures.
2010-08-16 15:57:01 +00:00
}
2010-11-16 00:22:18 +00:00
void SysMainMemory :: DecommitAll ()
2010-08-16 15:57:01 +00:00
{
2010-11-16 00:22:18 +00:00
if ( ! m_ee . IsCommitted () && ! m_iop . IsCommitted () && ! m_vu . IsCommitted ()) return ;
2010-11-15 14:05:02 +00:00
2010-11-16 15:58:42 +00:00
Console . WriteLn ( Color_Blue , "Decommitting host memory for virtual systems..." );
ConsoleIndentScope indent ( 1 );
2010-11-16 00:22:18 +00:00
m_ee . Decommit ();
m_iop . Decommit ();
m_vu . Decommit ();
2010-11-16 15:58:42 +00:00
closeNewVif ( 0 );
closeNewVif ( 1 );
2010-11-16 00:22:18 +00:00
vtlb_Core_Free ();
2010-08-16 15:57:01 +00:00
}
2010-11-15 14:05:02 +00:00
void SysMainMemory :: ReleaseAll ()
{
2010-11-16 00:22:18 +00:00
DecommitAll ();
2010-11-16 15:58:42 +00:00
Console . WriteLn ( Color_Blue , "Releasing host memory maps for virtual systems..." );
ConsoleIndentScope indent ( 1 );
2010-11-15 14:05:02 +00:00
2010-11-16 00:22:18 +00:00
vtlb_Core_Free (); // Just to be sure... (calling order could result in it getting missed during Decommit).
2010-11-16 15:58:42 +00:00
releaseNewVif ( 0 );
releaseNewVif ( 1 );
2010-11-16 00:22:18 +00:00
m_ee . Decommit ();
m_iop . Decommit ();
m_vu . Decommit ();
2010-11-15 14:05:02 +00:00
safe_delete ( Source_PageFault );
}
2010-08-16 15:57:01 +00:00
// --------------------------------------------------------------------------------------
// SysCpuProviderPack (implementations)
// --------------------------------------------------------------------------------------
SysCpuProviderPack :: SysCpuProviderPack ()
{
2010-11-16 15:58:42 +00:00
Console . WriteLn ( Color_StrongBlue , "Reserving memory for recompilers..." );
ConsoleIndentScope indent ( 1 );
2009-02-09 21:15:56 +00:00
2009-12-07 14:00:39 +00:00
CpuProviders = new CpuInitializerSet ();
2009-12-03 15:51:39 +00:00
try {
2010-10-22 16:23:52 +00:00
recCpu . Reserve ();
2009-02-09 21:15:56 +00:00
}
2009-12-03 15:51:39 +00:00
catch ( Exception :: RuntimeError & ex )
2009-02-09 21:15:56 +00:00
{
2010-06-28 18:03:54 +00:00
m_RecExceptionEE = ex . Clone ();
2010-10-22 16:23:52 +00:00
Console . Error ( L "EE Recompiler Reservation Failed: \n " + ex . FormatDiagnosticMessage () );
2009-02-09 21:15:56 +00:00
recCpu . Shutdown ();
2009-09-16 17:23:02 +00:00
}
2009-12-03 15:51:39 +00:00
try {
2010-10-22 16:23:52 +00:00
psxRec . Reserve ();
2009-09-16 17:23:02 +00:00
}
2009-12-03 15:51:39 +00:00
catch ( Exception :: RuntimeError & ex )
2009-09-16 17:23:02 +00:00
{
2010-06-28 18:03:54 +00:00
m_RecExceptionIOP = ex . Clone ();
2010-10-22 16:23:52 +00:00
Console . Error ( L "IOP Recompiler Reservation Failed: \n " + ex . FormatDiagnosticMessage () );
2009-02-09 21:15:56 +00:00
psxRec . Shutdown ();
}
2009-09-16 17:23:02 +00:00
// hmm! : VU0 and VU1 pre-allocations should do sVU and mVU separately? Sounds complicated. :(
2010-12-30 06:21:07 +00:00
if ( newVifDynaRec )
{
dVifReserve ( 0 );
dVifReserve ( 1 );
}
2009-09-16 17:23:02 +00:00
}
2010-08-16 15:57:01 +00:00
bool SysCpuProviderPack :: IsRecAvailable_MicroVU0 () const { return CpuProviders -> microVU0 . IsAvailable (); }
bool SysCpuProviderPack :: IsRecAvailable_MicroVU1 () const { return CpuProviders -> microVU1 . IsAvailable (); }
BaseException * SysCpuProviderPack :: GetException_MicroVU0 () const { return CpuProviders -> microVU0 . ExThrown ; }
BaseException * SysCpuProviderPack :: GetException_MicroVU1 () const { return CpuProviders -> microVU1 . ExThrown ; }
2009-12-07 14:00:39 +00:00
2010-08-16 15:57:01 +00:00
bool SysCpuProviderPack :: IsRecAvailable_SuperVU0 () const { return CpuProviders -> superVU0 . IsAvailable (); }
bool SysCpuProviderPack :: IsRecAvailable_SuperVU1 () const { return CpuProviders -> superVU1 . IsAvailable (); }
BaseException * SysCpuProviderPack :: GetException_SuperVU0 () const { return CpuProviders -> superVU0 . ExThrown ; }
BaseException * SysCpuProviderPack :: GetException_SuperVU1 () const { return CpuProviders -> superVU1 . ExThrown ; }
2009-12-07 14:00:39 +00:00
2010-08-16 15:57:01 +00:00
void SysCpuProviderPack :: CleanupMess () throw ()
2009-09-16 17:23:02 +00:00
{
try
{
psxRec . Shutdown ();
recCpu . Shutdown ();
2010-12-30 06:21:07 +00:00
if ( newVifDynaRec )
{
dVifRelease ( 0 );
dVifRelease ( 1 );
}
2009-09-16 17:23:02 +00:00
}
DESTRUCTOR_CATCHALL
2009-02-09 21:15:56 +00:00
}
2010-08-16 15:57:01 +00:00
SysCpuProviderPack ::~ SysCpuProviderPack () throw ()
2009-02-09 21:15:56 +00:00
{
2009-09-16 17:23:02 +00:00
CleanupMess ();
2009-02-09 21:15:56 +00:00
}
2010-08-16 15:57:01 +00:00
bool SysCpuProviderPack :: HadSomeFailures ( const Pcsx2Config :: RecompilerOptions & recOpts ) const
2009-02-09 21:15:56 +00:00
{
2009-12-07 14:00:39 +00:00
return ( recOpts . EnableEE && ! IsRecAvailable_EE ()) ||
( recOpts . EnableIOP && ! IsRecAvailable_IOP ()) ||
( recOpts . EnableVU0 && recOpts . UseMicroVU0 && ! IsRecAvailable_MicroVU0 ()) ||
( recOpts . EnableVU1 && recOpts . UseMicroVU0 && ! IsRecAvailable_MicroVU1 ()) ||
( recOpts . EnableVU0 && ! recOpts . UseMicroVU0 && ! IsRecAvailable_SuperVU0 ()) ||
( recOpts . EnableVU1 && ! recOpts . UseMicroVU1 && ! IsRecAvailable_SuperVU1 ());
2009-09-09 14:08:15 +00:00
}
2009-03-04 11:33:45 +00:00
2009-12-07 14:00:39 +00:00
BaseVUmicroCPU * CpuVU0 = NULL ;
BaseVUmicroCPU * CpuVU1 = NULL ;
2010-08-16 15:57:01 +00:00
void SysCpuProviderPack :: ApplyConfig () const
2009-12-07 14:00:39 +00:00
{
Cpu = CHECK_EEREC ? & recCpu : & intCpu ;
psxCpu = CHECK_IOPREC ? & psxRec : & psxInt ;
CpuVU0 = CpuProviders -> interpVU0 ;
CpuVU1 = CpuProviders -> interpVU1 ;
if ( EmuConfig . Cpu . Recompiler . EnableVU0 )
CpuVU0 = EmuConfig . Cpu . Recompiler . UseMicroVU0 ? ( BaseVUmicroCPU * ) CpuProviders -> microVU0 : ( BaseVUmicroCPU * ) CpuProviders -> superVU0 ;
if ( EmuConfig . Cpu . Recompiler . EnableVU1 )
CpuVU1 = EmuConfig . Cpu . Recompiler . UseMicroVU1 ? ( BaseVUmicroCPU * ) CpuProviders -> microVU1 : ( BaseVUmicroCPU * ) CpuProviders -> superVU1 ;
}
2010-07-07 05:59:25 +00:00
// This is a semi-hacky function for convenience
2010-08-16 15:57:01 +00:00
BaseVUmicroCPU * SysCpuProviderPack :: getVUprovider ( int whichProvider , int vuIndex ) const {
2010-07-07 05:59:25 +00:00
switch ( whichProvider ) {
case 0 : return vuIndex ? ( BaseVUmicroCPU * ) CpuProviders -> interpVU1 : ( BaseVUmicroCPU * ) CpuProviders -> interpVU0 ;
case 1 : return vuIndex ? ( BaseVUmicroCPU * ) CpuProviders -> superVU1 : ( BaseVUmicroCPU * ) CpuProviders -> superVU0 ;
case 2 : return vuIndex ? ( BaseVUmicroCPU * ) CpuProviders -> microVU1 : ( BaseVUmicroCPU * ) CpuProviders -> microVU0 ;
}
return NULL ;
}
2009-12-07 14:00:39 +00:00
2009-03-04 11:33:45 +00:00
// Resets all PS2 cpu execution caches, which does not affect that actual PS2 state/condition.
2009-02-09 21:15:56 +00:00
// This can be called at any time outside the context of a Cpu->Execute() block without
// bad things happening (recompilers will slow down for a brief moment since rec code blocks
// are dumped).
// Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
2009-03-04 11:33:45 +00:00
void SysClearExecutionCache ()
2009-02-09 21:15:56 +00:00
{
2010-08-16 15:57:01 +00:00
GetCpuProviders (). ApplyConfig ();
2009-12-07 14:00:39 +00:00
2009-02-09 21:15:56 +00:00
Cpu -> Reset ();
psxCpu -> Reset ();
2010-10-22 16:23:52 +00:00
// mVU's VU0 needs to be properly initialized for macro mode even if it's not used for micro mode!
2010-08-21 14:50:45 +00:00
if ( CHECK_EEREC )
(( BaseVUmicroCPU * ) GetCpuProviders (). CpuProviders -> microVU0 ) -> Reset ();
2010-10-22 16:23:52 +00:00
2010-05-28 16:54:42 +00:00
CpuVU0 -> Reset ();
CpuVU1 -> Reset ();
2010-04-25 00:31:27 +00:00
2010-12-30 06:21:07 +00:00
if ( newVifDynaRec )
{
dVifReset ( 0 );
dVifReset ( 1 );
}
2009-02-09 21:15:56 +00:00
}
2009-08-31 03:47:05 +00:00
// Maps a block of memory for use as a recompiled code buffer, and ensures that the
// allocation is below a certain memory address (specified in "bounds" parameter).
// The allocated block has code execution privileges.
// Returns NULL on allocation failure.
2010-06-22 18:57:48 +00:00
u8 * SysMmapEx ( uptr base , u32 size , uptr bounds , const char * caller )
2009-02-09 21:15:56 +00:00
{
2010-06-22 18:57:48 +00:00
u8 * Mem = ( u8 * ) HostSys :: Mmap ( base , size );
2009-02-09 21:15:56 +00:00
if ( ( Mem == NULL ) || ( bounds != 0 && ((( uptr ) Mem + size ) > bounds )) )
{
2010-10-27 23:58:10 +00:00
if ( base )
2009-12-07 14:00:39 +00:00
{
DbgCon . Warning ( "First try failed allocating %s at address 0x%x" , caller , base );
2009-02-09 21:15:56 +00:00
2010-10-22 16:23:52 +00:00
// Let's try again at an OS-picked memory area, and then hope it meets needed
// boundschecking criteria below.
2009-12-07 14:00:39 +00:00
SafeSysMunmap ( Mem , size );
2010-10-27 23:58:10 +00:00
Mem = ( u8 * ) HostSys :: Mmap ( 0 , size );
2009-12-07 14:00:39 +00:00
}
2009-02-09 21:15:56 +00:00
2010-10-22 16:23:52 +00:00
if ( ( bounds != 0 ) && ((( uptr ) Mem + size ) > bounds ) )
2009-02-09 21:15:56 +00:00
{
2009-12-07 14:00:39 +00:00
DevCon . Warning ( "Second try failed allocating %s, block ptr 0x%x does not meet required criteria." , caller , Mem );
2009-02-09 21:15:56 +00:00
SafeSysMunmap ( Mem , size );
// returns NULL, caller should throw an exception.
}
}
return Mem ;
}
2010-06-22 18:57:48 +00:00
// This function always returns a valid DiscID -- using the Sony serial when possible, and
// falling back on the CRC checksum of the ELF binary if the PS2 software being run is
// homebrew or some other serial-less item.
wxString SysGetDiscID ()
{
if ( ! DiscSerial . IsEmpty () ) return DiscSerial ;
if ( ! ElfCRC )
{
2010-12-14 07:28:05 +00:00
// FIXME: system is currently running the BIOS, so it should return a serial based on
2010-06-22 18:57:48 +00:00
// the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS
// region and revision).
2010-12-15 00:04:23 +00:00
return wxEmptyString ;
2010-06-22 18:57:48 +00:00
}
2010-11-16 15:58:42 +00:00
return pxsFmt ( L "%08x" , ElfCRC );
2010-06-22 18:57:48 +00:00
}