Allocate low executable memory on OS X as on Windows and Linux.
Even with LoadStorePaired accounted for, there are still some niggling 64-bit cleanliness bugs left that are not practical to weed out on a single platform. We should probably have an option to use >2GB memory only on all platforms for debugging. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6792 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
f634d58035
commit
d4158f076a
|
@ -58,19 +58,12 @@ void MemArena::ReleaseSpace()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void* MemArena::CreateView(s64 offset, size_t size, bool ensure_low_mem)
|
void* MemArena::CreateView(s64 offset, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return MapViewOfFile(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size);
|
return MapViewOfFile(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size);
|
||||||
#else
|
#else
|
||||||
void* ptr = mmap(0, size,
|
return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
|
||||||
PROT_READ | PROT_WRITE,
|
|
||||||
MAP_SHARED
|
|
||||||
#ifdef __x86_64__
|
|
||||||
| (ensure_low_mem ? MAP_32BIT : 0)
|
|
||||||
#endif
|
|
||||||
, fd, offset);
|
|
||||||
return ptr;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,13 @@
|
||||||
// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
|
// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
|
||||||
// Multiple views can mirror the same section of the block, which makes it very convient for emulating
|
// Multiple views can mirror the same section of the block, which makes it very convient for emulating
|
||||||
// memory mirrors.
|
// memory mirrors.
|
||||||
// Pass ensure_low_mem = true to CreateView if you want arbitrarily positioned views to end up in the low 2GB.
|
|
||||||
|
|
||||||
class MemArena
|
class MemArena
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void GrabLowMemSpace(size_t size);
|
void GrabLowMemSpace(size_t size);
|
||||||
void ReleaseSpace();
|
void ReleaseSpace();
|
||||||
void* CreateView(s64 offset, size_t size, bool ensure_low_mem = false);
|
void* CreateView(s64 offset, size_t size);
|
||||||
void* CreateViewAt(s64 offset, size_t size, void* base);
|
void* CreateViewAt(s64 offset, size_t size, void* base);
|
||||||
void ReleaseView(void* view, size_t size);
|
void ReleaseView(void* view, size_t size);
|
||||||
|
|
||||||
|
|
|
@ -34,59 +34,42 @@ void* AllocateExecutableMemory(size_t size, bool low)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
#else
|
||||||
|
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
|
MAP_ANON | MAP_PRIVATE
|
||||||
|
#if defined __linux__ && defined __x86_64__
|
||||||
|
| (low ? MAP_32BIT : 0)
|
||||||
|
#endif
|
||||||
|
, -1, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
|
||||||
|
// (unsigned long)size);
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
PanicAlert("Failed to allocate executable memory");
|
||||||
if ((u64)ptr >= 0x80000000)
|
if ((u64)ptr >= 0x80000000)
|
||||||
{
|
|
||||||
PanicAlert("Executable memory ended up above 2GB!");
|
PanicAlert("Executable memory ended up above 2GB!");
|
||||||
// If this happens, we have to implement a free ram search scheme. ector knows how.
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
||||||
#else
|
|
||||||
void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
|
||||||
MAP_ANON | MAP_PRIVATE
|
|
||||||
#ifdef __x86_64__
|
|
||||||
| (low ? MAP_32BIT : 0)
|
|
||||||
#endif
|
|
||||||
, -1, 0); // | MAP_FIXED
|
|
||||||
// printf("Mapped executable memory at %p (size %i)\n", retval, size);
|
|
||||||
|
|
||||||
if (!retval)
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to allocate executable memory, errno=%i", errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* AllocateMemoryPages(size_t size)
|
void* AllocateMemoryPages(size_t size)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to allocate raw memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
void* retval = mmap(0, size, PROT_READ | PROT_WRITE,
|
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
|
||||||
MAP_ANON | MAP_PRIVATE, -1, 0); // | MAP_FIXED
|
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||||
// printf("Mapped memory at %p (size %i)\n", retval, size);
|
|
||||||
|
|
||||||
if (!retval)
|
|
||||||
{
|
|
||||||
PanicAlert("Failed to allocate raw memory, errno=%i", errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// printf("Mapped memory at %p (size %ld)\n", ptr,
|
||||||
|
// (unsigned long)size);
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
PanicAlert("Failed to allocate raw memory");
|
||||||
|
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeMemoryPages(void* ptr, size_t size)
|
void FreeMemoryPages(void* ptr, size_t size)
|
||||||
|
@ -125,27 +108,25 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string MemUsage()
|
std::string MemUsage()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD processID = GetCurrentProcessId();
|
DWORD processID = GetCurrentProcessId();
|
||||||
HANDLE hProcess;
|
HANDLE hProcess;
|
||||||
PROCESS_MEMORY_COUNTERS pmc;
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
std::string Ret;
|
std::string Ret;
|
||||||
|
|
||||||
// Print information about the memory usage of the process.
|
// Print information about the memory usage of the process.
|
||||||
|
|
||||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
|
||||||
if (NULL == hProcess) return "MemUsage Error";
|
if (NULL == hProcess) return "MemUsage Error";
|
||||||
|
|
||||||
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
|
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
|
||||||
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
|
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
|
||||||
|
|
||||||
CloseHandle(hProcess);
|
CloseHandle(hProcess);
|
||||||
return Ret;
|
return Ret;
|
||||||
|
#else
|
||||||
#else
|
|
||||||
return "";
|
return "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Linux-specific mmap(2) flag
|
|
||||||
#ifndef MAP_32BIT
|
|
||||||
#define MAP_32BIT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void* AllocateExecutableMemory(size_t size, bool low = true);
|
void* AllocateExecutableMemory(size_t size, bool low = true);
|
||||||
void* AllocateMemoryPages(size_t size);
|
void* AllocateMemoryPages(size_t size);
|
||||||
void FreeMemoryPages(void* ptr, size_t size);
|
void FreeMemoryPages(void* ptr, size_t size);
|
||||||
|
|
|
@ -91,27 +91,11 @@ void SCoreStartupParameter::LoadDefaults()
|
||||||
bJITOff = false; // debugger only settings
|
bJITOff = false; // debugger only settings
|
||||||
bJITLoadStoreOff = false;
|
bJITLoadStoreOff = false;
|
||||||
bJITLoadStoreFloatingOff = false;
|
bJITLoadStoreFloatingOff = false;
|
||||||
bJITLoadStorePairedOff = false;
|
bJITLoadStorePairedOff = false; // XXX not 64-bit clean
|
||||||
bJITFloatingPointOff = false;
|
bJITFloatingPointOff = false;
|
||||||
bJITIntegerOff = false;
|
bJITIntegerOff = false;
|
||||||
bJITPairedOff = false;
|
bJITPairedOff = false;
|
||||||
bJITSystemRegistersOff = false;
|
bJITSystemRegistersOff = false;
|
||||||
#ifdef __APPLE__
|
|
||||||
// These are required for the JIT cores to work in OSX
|
|
||||||
// Older revs (~4854) Only required LoadStorePaired to be turned off
|
|
||||||
// Newer revs (~4890) require both turned off
|
|
||||||
#ifdef _M_X64
|
|
||||||
// These work fine in 32bit OSX
|
|
||||||
// Since the reason why 64bit OSX fails out is due to casting (u32)(u64)
|
|
||||||
// Since all 64bit applications are above the 32bit memory boundary
|
|
||||||
bJITLoadStorePairedOff = true;
|
|
||||||
#endif
|
|
||||||
//#elif defined(__linux__)
|
|
||||||
// Similar to OSX, something with LoadStorePaired seems to cause
|
|
||||||
// crashes on linux. Only Win32 seems to be forgiving enough to
|
|
||||||
// not do anything funny...(FIXME)
|
|
||||||
// bJITLoadStorePairedOff = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_strName = "NONE";
|
m_strName = "NONE";
|
||||||
m_strUniqueID = "00000000";
|
m_strUniqueID = "00000000";
|
||||||
|
|
|
@ -35,63 +35,7 @@
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
static int temp32;
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__APPLE__) && _M_X64
|
|
||||||
void CommonAsmRoutines::GenFifoWrite(int size)
|
|
||||||
{
|
|
||||||
// Assume value in ABI_PARAM1
|
|
||||||
PUSH(RSI);
|
|
||||||
if (size != 32)
|
|
||||||
PUSH(EDX);
|
|
||||||
BSWAP(size, ABI_PARAM1);
|
|
||||||
MOV(32, R(EAX), Imm32((u64)GPFifo::m_gatherPipe));
|
|
||||||
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
|
|
||||||
if (size != 32) {
|
|
||||||
MOV(32, R(EDX), R(ABI_PARAM1));
|
|
||||||
MOV(size, MComplex(RAX, RSI, 1, 0), R(EDX));
|
|
||||||
} else {
|
|
||||||
MOV(size, MComplex(RAX, RSI, 1, 0), R(ABI_PARAM1));
|
|
||||||
}
|
|
||||||
ADD(64, R(RSI), Imm8(size >> 3));
|
|
||||||
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
|
|
||||||
if (size != 32)
|
|
||||||
POP(EDX);
|
|
||||||
POP(RSI);
|
|
||||||
RET();
|
|
||||||
}
|
|
||||||
void CommonAsmRoutines::GenFifoFloatWrite()
|
|
||||||
{
|
|
||||||
// Assume value in XMM0
|
|
||||||
PUSH(RSI);
|
|
||||||
PUSH(EDX);
|
|
||||||
MOVSS(M(&temp32), XMM0);
|
|
||||||
MOV(32, R(EDX), M(&temp32));
|
|
||||||
BSWAP(32, EDX);
|
|
||||||
MOV(64, R(RAX), Imm64((u64)GPFifo::m_gatherPipe));
|
|
||||||
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
|
|
||||||
MOV(32, MComplex(RAX, RSI, 1, 0), R(EDX));
|
|
||||||
ADD(64, R(RSI), Imm8(4));
|
|
||||||
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
|
|
||||||
POP(EDX);
|
|
||||||
POP(RSI);
|
|
||||||
RET();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommonAsmRoutines::GenFifoXmm64Write()
|
|
||||||
{
|
|
||||||
// Assume value in XMM0. Assume pre-byteswapped (unlike the others here!)
|
|
||||||
PUSH(RSI);
|
|
||||||
MOV(64, R(RAX), Imm32((u64)GPFifo::m_gatherPipe));
|
|
||||||
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
|
|
||||||
MOVQ_xmm(MComplex(RAX, RSI, 1, 0), XMM0);
|
|
||||||
ADD(64, R(RSI), Imm8(8));
|
|
||||||
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
|
|
||||||
POP(RSI);
|
|
||||||
RET();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void CommonAsmRoutines::GenFifoWrite(int size)
|
void CommonAsmRoutines::GenFifoWrite(int size)
|
||||||
{
|
{
|
||||||
// Assume value in ABI_PARAM1
|
// Assume value in ABI_PARAM1
|
||||||
|
@ -116,6 +60,8 @@ void CommonAsmRoutines::GenFifoWrite(int size)
|
||||||
}
|
}
|
||||||
void CommonAsmRoutines::GenFifoFloatWrite()
|
void CommonAsmRoutines::GenFifoFloatWrite()
|
||||||
{
|
{
|
||||||
|
int temp32;
|
||||||
|
|
||||||
// Assume value in XMM0
|
// Assume value in XMM0
|
||||||
PUSH(ESI);
|
PUSH(ESI);
|
||||||
PUSH(EDX);
|
PUSH(EDX);
|
||||||
|
@ -143,8 +89,6 @@ void CommonAsmRoutines::GenFifoXmm64Write()
|
||||||
POP(ESI);
|
POP(ESI);
|
||||||
RET();
|
RET();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Safe + Fast Quantizers, originally from JITIL by magumagu
|
// Safe + Fast Quantizers, originally from JITIL by magumagu
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ libs = [
|
||||||
'inputcommon', 'common', 'lua', 'z', 'sfml-network',
|
'inputcommon', 'common', 'lua', 'z', 'sfml-network',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
wxlibs = [ ]
|
||||||
|
|
||||||
|
ldflags = [ ]
|
||||||
|
|
||||||
if env['HAVE_WX']:
|
if env['HAVE_WX']:
|
||||||
files += [
|
files += [
|
||||||
'AboutDolphin.cpp',
|
'AboutDolphin.cpp',
|
||||||
|
@ -46,7 +50,7 @@ if env['HAVE_WX']:
|
||||||
'WxUtils.cpp',
|
'WxUtils.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
wxlibs = [ 'debwx', 'debugger_ui_util', 'inputuicommon' ]
|
wxlibs += [ 'debwx', 'debugger_ui_util', 'inputuicommon' ]
|
||||||
else:
|
else:
|
||||||
files += [
|
files += [
|
||||||
'MainNoGUI.cpp',
|
'MainNoGUI.cpp',
|
||||||
|
@ -57,14 +61,15 @@ if sys.platform == 'win32':
|
||||||
files += [ "stdafx.cpp" ]
|
files += [ "stdafx.cpp" ]
|
||||||
elif sys.platform == 'darwin' and not env['HAVE_WX']:
|
elif sys.platform == 'darwin' and not env['HAVE_WX']:
|
||||||
files += [ 'cocoaApp.m' ]
|
files += [ 'cocoaApp.m' ]
|
||||||
|
ldflags += [ '-Wl,-pagezero_size,0x1000' ]
|
||||||
exeNoGUI = '#' + env['prefix'] + '/DolphinNoGUI'
|
exeNoGUI = '#' + env['prefix'] + '/DolphinNoGUI'
|
||||||
elif sys.platform == 'darwin' and env['HAVE_WX']:
|
elif sys.platform == 'darwin' and env['HAVE_WX']:
|
||||||
wxlibs += env['wxconfiglibs']
|
wxlibs += env['wxconfiglibs']
|
||||||
|
ldflags += [ '-Wl,-pagezero_size,0x1000' ]
|
||||||
exeGUI = '#' + env['prefix'] + '/Dolphin.app/Contents/MacOS/Dolphin'
|
exeGUI = '#' + env['prefix'] + '/Dolphin.app/Contents/MacOS/Dolphin'
|
||||||
|
|
||||||
env.Install('#' + env['prefix'] + '/Dolphin.app/Contents/' +
|
env.Install('#' + env['prefix'] + '/Dolphin.app/Contents/' +
|
||||||
'Library/Frameworks/Cg.framework',
|
'Library/Frameworks', '#Externals/Cg/Cg.framework')
|
||||||
'#Externals/Cg/Cg.framework/Cg')
|
|
||||||
|
|
||||||
env.Install(env['data_dir'], '#Data/Sys')
|
env.Install(env['data_dir'], '#Data/Sys')
|
||||||
env.Install(env['data_dir'], '#Data/User')
|
env.Install(env['data_dir'], '#Data/User')
|
||||||
|
@ -104,7 +109,10 @@ else:
|
||||||
env.InstallAs(env['data_dir'] + '/sys', '#Data/Sys')
|
env.InstallAs(env['data_dir'] + '/sys', '#Data/Sys')
|
||||||
env.InstallAs(env['data_dir'] + '/user', '#Data/User')
|
env.InstallAs(env['data_dir'] + '/user', '#Data/User')
|
||||||
|
|
||||||
|
libs = wxlibs + libs + env['LIBS']
|
||||||
|
linkflags = ldflags + env['LINKFLAGS']
|
||||||
|
|
||||||
if env['HAVE_WX']:
|
if env['HAVE_WX']:
|
||||||
env.Program(exeGUI, files, LIBS = wxlibs + libs + env['LIBS'])
|
env.Program(exeGUI, files, LIBS = libs, LINKFLAGS = linkflags)
|
||||||
else:
|
else:
|
||||||
env.Program(exeNoGUI, files, LIBS = libs + env['LIBS'])
|
env.Program(exeNoGUI, files, LIBS = libs, LINKFLAGS = linkflags)
|
||||||
|
|
|
@ -31,15 +31,17 @@ files = [
|
||||||
'VertexFormatConverter.cpp',
|
'VertexFormatConverter.cpp',
|
||||||
'VertexLoader.cpp',
|
'VertexLoader.cpp',
|
||||||
'VideoConfig.cpp',
|
'VideoConfig.cpp',
|
||||||
'VideoConfigDialog.cpp',
|
|
||||||
'XFMemLoader.cpp',
|
'XFMemLoader.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
libs = [ 'videocommon', 'GLEW', 'SOIL', 'common' ]
|
if env['HAVE_WX']:
|
||||||
|
files += [ 'VideoConfigDialog.cpp' ]
|
||||||
|
|
||||||
if sys.platform == 'darwin' and not env['HAVE_WX']:
|
if sys.platform == 'darwin' and not env['HAVE_WX']:
|
||||||
files += [ 'cocoaGL.m' ]
|
files += [ 'cocoaGL.m' ]
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == 'win32':
|
||||||
files += [ 'Win32.cpp' ]
|
files += [ 'Win32.cpp' ]
|
||||||
|
|
||||||
|
libs = [ 'videocommon', 'GLEW', 'SOIL', 'common' ]
|
||||||
|
|
||||||
env.SharedLibrary(env['plugin_dir'] + name, files, LIBS = env['LIBS'] + libs)
|
env.SharedLibrary(env['plugin_dir'] + name, files, LIBS = env['LIBS'] + libs)
|
||||||
|
|
Loading…
Reference in New Issue