Made EE executor work on OSX.

This commit is contained in:
Jean-Philip Desjardins 2015-06-09 02:49:54 -04:00
parent 81e3ce2820
commit 6cd0e5e3dd
4 changed files with 157 additions and 24 deletions

View File

@ -784,6 +784,7 @@ void CPS2VM::EmuThread()
{
fesetround(FE_TOWARDZERO);
CProfiler::GetInstance().SetWorkThread();
m_ee->m_executor.AddExceptionHandler();
while(1)
{
while(m_mailBox.IsPending())

View File

@ -1,10 +1,27 @@
#ifndef _MSC_VER
#include <sys/mman.h>
#endif
#include "EeExecutor.h"
#include "../Ps2Const.h"
#include "AlignedAlloc.h"
#if defined(__ANDROID__) || defined(__APPLE__)
#include <sys/mman.h>
#endif
#if defined(__APPLE__)
#include "TargetConditionals.h"
//TODO: Include ARM/iOS stuff
#if TARGET_RT_64_BIT
#define STATE_FLAVOR x86_THREAD_STATE64
#define STATE_FLAVOR_COUNT x86_THREAD_STATE64_COUNT
#else
#define STATE_FLAVOR x86_THREAD_STATE32
#define STATE_FLAVOR_COUNT x86_THREAD_STATE32_COUNT
#endif // !TARGET_RT_64_BIT
#endif
static CEeExecutor* g_eeExecutor = nullptr;
CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram)
@ -12,14 +29,22 @@ CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram)
, m_ram(ram)
{
m_pageSize = framework_getpagesize();
}
CEeExecutor::~CEeExecutor()
{
}
void CEeExecutor::AddExceptionHandler()
{
assert(g_eeExecutor == nullptr);
g_eeExecutor = this;
#ifdef _MSC_VER
#if defined(_WIN32)
m_handler = AddVectoredExceptionHandler(TRUE, &CEeExecutor::HandleException);
assert(m_handler != NULL);
#else
#elif defined(__ANDROID__)
struct sigaction sigAction;
sigAction.sa_handler = nullptr;
sigAction.sa_sigaction = &HandleException;
@ -27,12 +52,26 @@ CEeExecutor::CEeExecutor(CMIPS& context, uint8* ram)
sigemptyset(&sigAction.sa_mask);
int result = sigaction(SIGSEGV, &sigAction, nullptr);
assert(result >= 0);
#elif defined(__APPLE__)
kern_return_t result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &m_port);
assert(result == KERN_SUCCESS);
m_handlerThread = std::thread([this] () { HandlerThreadProc(); });
result = mach_port_insert_right(mach_task_self(), m_port, m_port, MACH_MSG_TYPE_MAKE_SEND);
assert(result == KERN_SUCCESS);
result = thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS, m_port, EXCEPTION_STATE | MACH_EXCEPTION_CODES, STATE_FLAVOR);
assert(result == KERN_SUCCESS);
result = mach_port_mod_refs(mach_task_self(), m_port, MACH_PORT_RIGHT_SEND, -1);
assert(result == KERN_SUCCESS);
#endif
}
CEeExecutor::~CEeExecutor()
void CEeExecutor::RemoveExceptionHandler()
{
#ifdef _MSC_VER
#if defined(_WIN32)
RemoveVectoredExceptionHandler(m_handler);
#endif
g_eeExecutor = nullptr;
@ -71,22 +110,36 @@ CMipsExecutor::BasicBlockPtr CEeExecutor::BlockFactory(CMIPS& context, uint32 st
return CMipsExecutor::BlockFactory(context, start, end);
}
bool CEeExecutor::HandleAccessFault(intptr_t ptr)
{
ptrdiff_t addr = reinterpret_cast<uint8*>(ptr) - m_ram;
if(addr >= 0 && addr < PS2::EE_RAM_SIZE)
{
addr &= ~(m_pageSize - 1);
ClearActiveBlocksInRange(addr, addr + m_pageSize);
return true;
}
return false;
}
void CEeExecutor::SetMemoryProtected(void* addr, size_t size, bool protect)
{
#ifdef _MSC_VER
#if defined(_WIN32)
DWORD oldProtect = 0;
BOOL result = VirtualProtect(addr, size, protect ? PAGE_READONLY : PAGE_READWRITE, &oldProtect);
assert(result == TRUE);
#else
#elif defined(__ANDROID__) || defined(__APPLE__)
uintptr_t addrValue = reinterpret_cast<uintptr_t>(addr) & ~(m_pageSize - 1);
addr = reinterpret_cast<void*>(addrValue);
size = size + (m_pageSize - 1) & ~(m_pageSize - 1);
int result = mprotect(addr, size, protect ? PROT_READ : PROT_READ | PROT_WRITE);
assert(result >= 0);
#else
assert(false);
#endif
}
#ifdef _MSC_VER
#if defined(_WIN32)
LONG WINAPI CEeExecutor::HandleException(_EXCEPTION_POINTERS* exceptionInfo)
{
@ -98,18 +151,15 @@ LONG CEeExecutor::HandleExceptionInternal(_EXCEPTION_POINTERS* exceptionInfo)
auto exceptionRecord = exceptionInfo->ExceptionRecord;
if(exceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
ptrdiff_t addr = reinterpret_cast<uint8*>(exceptionRecord->ExceptionInformation[1]) - m_ram;
if(addr >= 0 && addr < PS2::EE_RAM_SIZE)
if(HandleAccessFault(exceptionRecord->ExceptionInformation[1]))
{
addr &= ~(m_pageSize - 1);
ClearActiveBlocksInRange(addr, addr + m_pageSize);
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
#else
#elif defined(__ANDROID__)
void CEeExecutor::HandleException(int sigId, siginfo_t* sigInfo, void* baseContext)
{
@ -119,14 +169,78 @@ void CEeExecutor::HandleException(int sigId, siginfo_t* sigInfo, void* baseConte
void CEeExecutor::HandleExceptionInternal(int sigId, siginfo_t* sigInfo, void* baseContext)
{
if(sigId != SIGSEGV) return;
ptrdiff_t addr = reinterpret_cast<uint8*>(sigInfo->si_addr) - m_ram;
if(addr >= 0 && addr < PS2::EE_RAM_SIZE)
if(HandleAccessFault(sigInfo->si_addr))
{
addr &= ~(m_pageSize - 1);
ClearActiveBlocksInRange(addr, addr + m_pageSize);
return;
}
signal(SIGSEGV, SIG_DFL);
}
#elif defined(__APPLE__)
void CEeExecutor::HandlerThreadProc()
{
#pragma pack(push, 4)
struct INPUT_MESSAGE
{
mach_msg_header_t head;
NDR_record_t ndr;
exception_type_t exception;
mach_msg_type_number_t codeCount;
intptr_t code[2];
int flavor;
mach_msg_type_number_t stateCount;
natural_t state[STATE_FLAVOR_COUNT];
mach_msg_trailer_t trailer;
};
struct OUTPUT_MESSAGE
{
mach_msg_header_t head;
NDR_record_t ndr;
kern_return_t result;
int flavor;
mach_msg_type_number_t stateCount;
natural_t state[STATE_FLAVOR_COUNT];
};
#pragma pack(pop)
while(1)
{
kern_return_t result = KERN_SUCCESS;
INPUT_MESSAGE inMsg;
result = mach_msg(&inMsg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(inMsg), m_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
assert(result == KERN_SUCCESS);
assert(inMsg.head.msgh_id == 2406); //MACH_EXCEPTION_RAISE_RPC
bool success = HandleAccessFault(inMsg.code[1]);
OUTPUT_MESSAGE outMsg;
outMsg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(inMsg.head.msgh_bits), 0);
outMsg.head.msgh_remote_port = inMsg.head.msgh_remote_port;
outMsg.head.msgh_local_port = MACH_PORT_NULL;
outMsg.head.msgh_id = inMsg.head.msgh_id + 100;
outMsg.head.msgh_size = sizeof(outMsg);
outMsg.ndr = inMsg.ndr;
if(success)
{
outMsg.result = KERN_SUCCESS;
outMsg.flavor = STATE_FLAVOR;
outMsg.stateCount = STATE_FLAVOR_COUNT;
memcpy(outMsg.state, inMsg.state, STATE_FLAVOR_COUNT * sizeof(natural_t));
}
else
{
outMsg.result = KERN_FAILURE;
outMsg.flavor = 0;
outMsg.stateCount = 0;
}
result = mach_msg(&outMsg.head, MACH_SEND_MSG | MACH_RCV_LARGE, sizeof(outMsg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
assert(result == KERN_SUCCESS);
}
}
#endif

View File

@ -1,7 +1,10 @@
#pragma once
#ifdef _MSC_VER
#ifdef _WIN32
#include <Windows.h>
#elif defined(__APPLE__)
#include <mach/mach.h>
#include <thread>
#endif
#include "../MipsExecutor.h"
@ -12,6 +15,9 @@ public:
CEeExecutor(CMIPS&, uint8*);
virtual ~CEeExecutor();
void AddExceptionHandler();
void RemoveExceptionHandler();
void Reset() override;
void ClearActiveBlocksInRange(uint32, uint32) override;
@ -19,17 +25,23 @@ public:
private:
uint8* m_ram = nullptr;
uint32 m_pageSize = 0;
size_t m_pageSize = 0;
bool HandleAccessFault(intptr_t);
void SetMemoryProtected(void*, size_t, bool);
#ifdef _MSC_VER
#if defined(_WIN32)
static LONG CALLBACK HandleException(_EXCEPTION_POINTERS*);
LONG HandleExceptionInternal(_EXCEPTION_POINTERS*);
LPVOID m_handler = NULL;
#else
#elif defined(__ANDROID__)
static void HandleException(int, siginfo_t*, void*);
void HandleExceptionInternal(int, siginfo_t*, void*);
#elif defined(__APPLE__)
void HandlerThreadProc();
mach_port_t m_port = MACH_PORT_NULL;
std::thread m_handlerThread;
#endif
};

View File

@ -21,6 +21,7 @@
704F23B51B0011C8009FD916 /* Vif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 704F23AF1B0011C8009FD916 /* Vif.cpp */; };
704F23B61B0011C8009FD916 /* Vif1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 704F23B11B0011C8009FD916 /* Vif1.cpp */; };
704F23B71B0011C8009FD916 /* Vpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 704F23B31B0011C8009FD916 /* Vpu.cpp */; };
7056F2851B2683C700389AFB /* EeExecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7056F2831B2683C700389AFB /* EeExecutor.cpp */; };
70684979151E882000C9574F /* libCodeGen.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 70684976151E880F00C9574F /* libCodeGen.a */; };
7068497B151E883D00C9574F /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7068497A151E883D00C9574F /* OpenGL.framework */; };
7068497D151E885200C9574F /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7068497C151E885200C9574F /* libz.dylib */; };
@ -218,6 +219,8 @@
704F23B21B0011C8009FD916 /* Vif1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Vif1.h; path = ../Source/ee/Vif1.h; sourceTree = "<group>"; };
704F23B31B0011C8009FD916 /* Vpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Vpu.cpp; path = ../Source/ee/Vpu.cpp; sourceTree = "<group>"; };
704F23B41B0011C8009FD916 /* Vpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Vpu.h; path = ../Source/ee/Vpu.h; sourceTree = "<group>"; };
7056F2831B2683C700389AFB /* EeExecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EeExecutor.cpp; path = ../Source/ee/EeExecutor.cpp; sourceTree = "<group>"; };
7056F2841B2683C700389AFB /* EeExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EeExecutor.h; path = ../Source/ee/EeExecutor.h; sourceTree = "<group>"; };
705B16BC1B097DD00081B3C6 /* BlockProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlockProvider.h; path = ../Source/ISO9660/BlockProvider.h; sourceTree = "<group>"; };
7068496E151E880E00C9574F /* CodeGen.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CodeGen.xcodeproj; path = ../../CodeGen/build_macosx/CodeGen.xcodeproj; sourceTree = "<group>"; };
7068497A151E883D00C9574F /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
@ -693,6 +696,8 @@
70D9F0F51AFB016900197BBE /* Ee_SubSystem.h */,
70D9F0F61AFB016900197BBE /* EEAssembler.cpp */,
70D9F0F71AFB016900197BBE /* EEAssembler.h */,
7056F2831B2683C700389AFB /* EeExecutor.cpp */,
7056F2841B2683C700389AFB /* EeExecutor.h */,
70D9F0F81AFB016900197BBE /* FpAddTruncate.cpp */,
70D9F0F91AFB016900197BBE /* FpAddTruncate.h */,
70D9F0FA1AFB016900197BBE /* FpMulTruncate.cpp */,
@ -1154,6 +1159,7 @@
70D9F13B1AFB016900197BBE /* IPU_MotionCodeTable.cpp in Sources */,
706849FF151E896900C9574F /* Iop_Thevent.cpp in Sources */,
70684A00151E896900C9574F /* Iop_Thsema.cpp in Sources */,
7056F2851B2683C700389AFB /* EeExecutor.cpp in Sources */,
70684A01151E896900C9574F /* Iop_Timrman.cpp in Sources */,
70D9F15A1AFB018900197BBE /* GSHandler.cpp in Sources */,
70684A02151E896900C9574F /* Iop_Vblank.cpp in Sources */,