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"
2015-03-17 09:31:25 +01:00
#include "MTVU.h"
2009-11-14 12:02:56 +00:00
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"
2015-12-07 09:26:25 +01:00
#include "Utilities/Perf.h"
2010-10-27 19:18:46 +00:00
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 )
2016-12-04 21:12:29 +01:00
: VirtualMemoryReserve ( name , defCommit )
2010-10-22 16:23:52 +00:00
{
m_prot_mode = PageAccess_Any ();
}
2017-05-06 15:17:12 +02:00
RecompiledCodeReserve ::~ RecompiledCodeReserve ()
2010-11-03 14:18:30 +00:00
{
_termProfiler ();
}
void RecompiledCodeReserve :: _registerProfiler ()
{
if ( m_profiler_name . IsEmpty () || ! IsOk ()) return ;
2015-12-07 09:26:25 +01:00
Perf :: any . map (( uptr ) m_baseptr , GetReserveSizeInBytes (), m_profiler_name . ToUTF8 ());
2010-11-03 14:18:30 +00:00
}
void RecompiledCodeReserve :: _termProfiler ()
{
}
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 ;
2015-11-11 15:28:56 +01:00
2016-12-04 21:12:29 +01:00
Commit ();
_registerProfiler ();
2015-11-11 15:28:56 +01:00
2010-11-03 14:18:30 +00:00
return m_baseptr ;
}
2015-11-11 15:28:56 +01:00
void RecompiledCodeReserve :: Reset ()
{
_parent :: Reset ();
2016-12-04 21:12:29 +01:00
Commit ();
2015-11-11 15:28:56 +01:00
}
2016-12-04 21:12:29 +01:00
bool RecompiledCodeReserve :: Commit ()
{
bool status = _parent :: Commit ();
if ( IsDevBuild && m_baseptr )
{
// 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.
memset ( m_baseptr , 0xCC , m_pages_commited * __pagesize );
}
return status ;
}
2010-11-03 14:18:30 +00:00
// 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-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-09-08 16:03:14 +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."
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
2013-06-28 10:43:50 +00:00
#include "svnrev.h"
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
{
2014-01-31 11:53:00 +00:00
if ( ! PCSX2_isReleaseVersion )
{
2014-09-17 22:36:44 +02:00
Console . WriteLn ( Color_StrongGreen , "PCSX2 %u.%u.%u-%lld %s"
2015-07-27 14:00:47 -04:00
#ifndef DISABLE_BUILD_DATE
2014-09-17 22:36:44 +02:00
"- compiled on " __DATE__
#endif
, PCSX2_VersionHi , PCSX2_VersionMid , PCSX2_VersionLo ,
2014-01-31 11:53:00 +00:00
SVN_REV , SVN_MODS ? "(modded)" : ""
);
}
else { // shorter release version string
2014-09-17 22:36:44 +02:00
Console . WriteLn ( Color_StrongGreen , "PCSX2 %u.%u.%u-%lld"
2015-07-27 14:00:47 -04:00
#ifndef DISABLE_BUILD_DATE
2014-09-17 22:36:44 +02:00
"- compiled on " __DATE__
#endif
, PCSX2_VersionHi , PCSX2_VersionMid , PCSX2_VersionLo ,
2014-01-31 11:53:00 +00:00
SVN_REV );
}
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
2014-06-29 09:05:03 +02:00
WX_STR ( GetOSVersionString ()),
2010-11-23 21:32:52 +00:00
( 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 "
2015-01-05 23:59:08 +01:00
L "CPU speed = %u.%03u ghz (%u logical thread%ls) \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" ,
2014-06-29 09:05:03 +02:00
WX_STR ( fromUTF8 ( x86caps . FamilyName ). Trim (). Trim ( false )),
WX_STR ( fromUTF8 ( x86caps . VendorName )), 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" ,
2014-06-29 09:05:03 +02:00
WX_STR ( x86caps . GetTypeName ()),
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 . 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" );
2015-11-28 23:39:06 +01:00
if ( x86caps . hasAVX2 ) features [ 0 ]. Add ( L "AVX2" );
2011-02-12 21:45:16 +00:00
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 . 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:" );
2019-06-16 17:33:17 -07:00
Console . Indent (). WriteLn ( result [ 0 ] + ( result [ 1 ]. IsEmpty () ? L "" : ( L " \n " + result [ 1 ])));
#ifdef __M_X86_64
Console . Indent (). WriteLn ( "Pcsx2 was compiled as 64-bits, which is unsupported and breaks all recompilers." );
#endif
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 :
2016-01-27 17:49:03 +00:00
std :: unique_ptr < CpuType > MyCpu ;
ScopedExcept ExThrown ;
2016-07-29 20:55:58 +03:00
2009-12-07 14:00:39 +00:00
CpuInitializer ();
2017-05-06 15:17:12 +02:00
virtual ~ CpuInitializer ();
2009-12-07 14:00:39 +00:00
bool IsAvailable () const
{
return !! MyCpu ;
}
2016-01-27 17:49:03 +00:00
CpuType * GetPtr () { return MyCpu . get (); }
const CpuType * GetPtr () const { return MyCpu . get (); }
2009-12-07 14:00:39 +00:00
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 {
2017-04-19 21:32:08 +02:00
MyCpu = std :: make_unique < 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 () );
2016-01-27 17:49:03 +00:00
MyCpu = nullptr ;
2016-01-27 17:50:51 +00:00
ExThrown = ScopedExcept ( 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 () ) );
2016-01-27 17:49:03 +00:00
MyCpu = nullptr ;
2016-01-27 17:50:51 +00:00
ExThrown = ScopedExcept ( new Exception :: RuntimeError ( ex ));
2009-12-07 14:00:39 +00:00
}
}
template < typename CpuType >
2017-05-06 15:17:12 +02:00
CpuInitializer < CpuType >::~ CpuInitializer ()
2009-12-07 14:00:39 +00:00
{
2015-09-22 19:06:12 +02:00
try {
if ( MyCpu )
MyCpu -> Shutdown ();
}
DESTRUCTOR_CATCHALL
2009-12-07 14:00:39 +00:00
}
2010-10-18 01:40:49 +00:00
// --------------------------------------------------------------------------------------
// CpuInitializerSet
// --------------------------------------------------------------------------------------
2009-12-07 14:00:39 +00:00
class CpuInitializerSet
{
public :
2015-01-06 23:45:43 +01:00
#ifndef DISABLE_SVU
2009-12-07 14:00:39 +00:00
// Note: Allocate sVU first -- it's the most picky.
CpuInitializer < recSuperVU0 > superVU0 ;
CpuInitializer < recSuperVU1 > superVU1 ;
2015-01-06 23:45:43 +01:00
#endif
2009-12-07 14:00:39 +00:00
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 () {}
2017-05-06 13:02:02 +02:00
virtual ~ CpuInitializerSet () = default ;
2009-12-07 14:00:39 +00:00
};
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
{
}
2017-05-06 15:17:12 +02:00
SysMainMemory ::~ SysMainMemory ()
2010-10-22 19:47:02 +00:00
{
2015-09-22 19:06:12 +02:00
try {
ReleaseAll ();
}
DESTRUCTOR_CATCHALL
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-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
2015-03-17 09:31:25 +01:00
// On linux, the MTVU isn't empty and the thread still uses the m_ee/m_vu memory
vu1Thread . WaitVU ();
// The EE thread must be stopped here command mustn't be send
// to the ring. Let's call it an extra safety valve :)
vu1Thread . Reset ();
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 );
2016-07-29 20:55:58 +03:00
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
2017-04-19 21:32:08 +02:00
CpuProviders = std :: make_unique < CpuInitializerSet > ();
2009-12-07 14:00:39 +00:00
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
{
2016-01-27 17:50:51 +00:00
m_RecExceptionEE = ScopedExcept ( 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
{
2016-01-27 17:50:51 +00:00
m_RecExceptionIOP = ScopedExcept ( 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 (); }
2016-01-27 17:50:51 +00:00
BaseException * SysCpuProviderPack :: GetException_MicroVU0 () const { return CpuProviders -> microVU0 . ExThrown . get (); }
BaseException * SysCpuProviderPack :: GetException_MicroVU1 () const { return CpuProviders -> microVU1 . ExThrown . get (); }
2009-12-07 14:00:39 +00:00
2015-01-06 23:45:43 +01:00
#ifndef DISABLE_SVU
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 (); }
2016-01-27 17:50:51 +00:00
BaseException * SysCpuProviderPack :: GetException_SuperVU0 () const { return CpuProviders -> superVU0 . ExThrown . get (); }
BaseException * SysCpuProviderPack :: GetException_SuperVU1 () const { return CpuProviders -> superVU1 . ExThrown . get (); }
2015-01-06 23:45:43 +01:00
#endif
2009-12-07 14:00:39 +00:00
2017-05-06 17:21:52 +02:00
void SysCpuProviderPack :: CleanupMess () noexcept
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
}
2017-05-06 15:17:12 +02:00
SysCpuProviderPack ::~ SysCpuProviderPack ()
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 ()) ||
2015-01-06 23:45:43 +01:00
#ifndef DISABLE_SVU
2009-12-07 14:00:39 +00:00
( recOpts . EnableVU0 && recOpts . UseMicroVU0 && ! IsRecAvailable_MicroVU0 ()) ||
( recOpts . EnableVU1 && recOpts . UseMicroVU0 && ! IsRecAvailable_MicroVU1 ()) ||
( recOpts . EnableVU0 && ! recOpts . UseMicroVU0 && ! IsRecAvailable_SuperVU0 ()) ||
2015-01-06 23:45:43 +01:00
( recOpts . EnableVU1 && ! recOpts . UseMicroVU1 && ! IsRecAvailable_SuperVU1 ())
#else
( recOpts . EnableVU0 && ! IsRecAvailable_MicroVU0 ()) ||
( recOpts . EnableVU1 && ! IsRecAvailable_MicroVU1 ())
#endif
;
2009-12-07 14:00:39 +00:00
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 )
2015-01-06 23:45:43 +01:00
#ifndef DISABLE_SVU
2009-12-07 14:00:39 +00:00
CpuVU0 = EmuConfig . Cpu . Recompiler . UseMicroVU0 ? ( BaseVUmicroCPU * ) CpuProviders -> microVU0 : ( BaseVUmicroCPU * ) CpuProviders -> superVU0 ;
2015-01-06 23:45:43 +01:00
#else
CpuVU0 = ( BaseVUmicroCPU * ) CpuProviders -> microVU0 ;
#endif
2009-12-07 14:00:39 +00:00
if ( EmuConfig . Cpu . Recompiler . EnableVU1 )
2015-01-06 23:45:43 +01:00
#ifndef DISABLE_SVU
2009-12-07 14:00:39 +00:00
CpuVU1 = EmuConfig . Cpu . Recompiler . UseMicroVU1 ? ( BaseVUmicroCPU * ) CpuProviders -> microVU1 : ( BaseVUmicroCPU * ) CpuProviders -> superVU1 ;
2015-01-06 23:45:43 +01:00
#else
CpuVU1 = ( BaseVUmicroCPU * ) CpuProviders -> microVU1 ;
#endif
2009-12-07 14:00:39 +00:00
}
2015-01-06 23:45:43 +01:00
#ifndef DISABLE_SVU
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 ;
}
2015-01-06 23:45:43 +01:00
#endif
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
2016-07-29 20:55:58 +03:00
wxString SysGetBiosDiscID ()
{
// FIXME: we should return a serial based on
// the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS
// region and revision).
return wxEmptyString ;
}
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 ;
2016-07-29 20:55:58 +03:00
2010-06-22 18:57:48 +00:00
if ( ! ElfCRC )
{
2016-07-29 20:55:58 +03:00
// system is currently running the BIOS
return SysGetBiosDiscID ();
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
}