win64/jit: Generate unwind table for the jit code cache
This required moving the SH4_TCB outside the exe, as new tables that belong on the executable are ignored. This isn't perfect, but there's a large area to scan for available address space so it shouldn't be a problem
This commit is contained in:
parent
e6a9d3e661
commit
e3845465f0
|
@ -28,7 +28,8 @@
|
|||
#if FEAT_SHREC != DYNAREC_NONE
|
||||
//uh uh
|
||||
|
||||
u8 SH4_TCB[2*CODE_SIZE+4096]
|
||||
#if !defined(_WIN64)
|
||||
u8 SH4_TCB[CODE_SIZE+4096]
|
||||
#if HOST_OS == OS_WINDOWS || FEAT_SHREC != DYNAREC_JIT
|
||||
;
|
||||
#elif HOST_OS == OS_LINUX
|
||||
|
@ -38,6 +39,7 @@ u8 SH4_TCB[2*CODE_SIZE+4096]
|
|||
#else
|
||||
#error SH4_TCB ALLOC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
u8* CodeCache;
|
||||
|
||||
|
@ -421,30 +423,43 @@ void recSh4_Init()
|
|||
verify(mem_b.data==((u8*)p_sh4rcb->sq_buffer+512+0x0C000000));
|
||||
#endif
|
||||
|
||||
//align to next page ..
|
||||
CodeCache = (u8*)(((unat)SH4_TCB+4095)& ~4095);
|
||||
#if defined(_WIN64)
|
||||
for (int i = 10; i < 1300; i++) {
|
||||
|
||||
|
||||
//align to next page ..
|
||||
u8* ptr = (u8*)recSh4_Init - i * 1024 * 1024;
|
||||
|
||||
CodeCache = (u8*)VirtualAlloc(ptr, CODE_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);//; (u8*)(((unat)SH4_TCB+4095)& ~4095);
|
||||
|
||||
if (CodeCache)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
CodeCache = (u8*)(((unat)SH4_TCB+4095)& ~4095);
|
||||
#endif
|
||||
|
||||
#if HOST_OS == OS_DARWIN
|
||||
munmap(CodeCache, CODE_SIZE*2);
|
||||
CodeCache = (u8*)mmap(CodeCache, 2*CODE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||
munmap(CodeCache, CODE_SIZE);
|
||||
CodeCache = (u8*)mmap(CodeCache, CODE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||
#endif
|
||||
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
DWORD old;
|
||||
VirtualProtect(CodeCache,CODE_SIZE*2,PAGE_EXECUTE_READWRITE,&old);
|
||||
VirtualProtect(CodeCache,CODE_SIZE,PAGE_EXECUTE_READWRITE,&old);
|
||||
#elif HOST_OS == OS_LINUX || HOST_OS == OS_DARWIN
|
||||
|
||||
printf("\n\t CodeCache addr: %p | from: %p | addr here: %p\n", CodeCache, CodeCache, recSh4_Init);
|
||||
|
||||
#if FEAT_SHREC == DYNAREC_JIT
|
||||
if (mprotect(CodeCache, CODE_SIZE*2, PROT_READ|PROT_WRITE|PROT_EXEC))
|
||||
if (mprotect(CodeCache, CODE_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC))
|
||||
{
|
||||
perror("\n\tError,Couldn’t mprotect CodeCache!");
|
||||
die("Couldn’t mprotect CodeCache");
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(CodeCache,0xFF,CODE_SIZE*2);
|
||||
memset(CodeCache,0xFF,CODE_SIZE);
|
||||
|
||||
#endif
|
||||
ngen_init();
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "blockmanager.h"
|
||||
|
||||
|
||||
#define CODE_SIZE (4*1024*1024)
|
||||
#define CODE_SIZE (6*1024*1024)
|
||||
|
||||
|
||||
//alternative emit ptr, set to 0 to use the main buffer
|
||||
|
|
|
@ -106,9 +106,12 @@ bool VramLockedWrite(u8* address);
|
|||
bool ngen_Rewrite(unat& addr,unat retadr,unat acc);
|
||||
bool BM_LockedWrite(u8* address);
|
||||
|
||||
int ExeptionHandler(u32 dwCode, void* pExceptionPointers)
|
||||
|
||||
LONG ExeptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
EXCEPTION_POINTERS* ep=(EXCEPTION_POINTERS*)pExceptionPointers;
|
||||
EXCEPTION_POINTERS* ep = ExceptionInfo;
|
||||
|
||||
u32 dwCode = ep->ExceptionRecord->ExceptionCode;
|
||||
|
||||
EXCEPTION_RECORD* pExceptionRecord=ep->ExceptionRecord;
|
||||
|
||||
|
@ -117,6 +120,8 @@ int ExeptionHandler(u32 dwCode, void* pExceptionPointers)
|
|||
|
||||
u8* address=(u8*)pExceptionRecord->ExceptionInformation[1];
|
||||
|
||||
//printf("[EXC] During access to : 0x%X\n", address);
|
||||
|
||||
if (VramLockedWrite(address))
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
|
@ -489,6 +494,108 @@ void ReserveBottomMemory()
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
#include "hw/sh4/dyna/ngen.h"
|
||||
|
||||
typedef union _UNWIND_CODE {
|
||||
struct {
|
||||
u8 CodeOffset;
|
||||
u8 UnwindOp : 4;
|
||||
u8 OpInfo : 4;
|
||||
};
|
||||
USHORT FrameOffset;
|
||||
} UNWIND_CODE, *PUNWIND_CODE;
|
||||
|
||||
typedef struct _UNWIND_INFO {
|
||||
u8 Version : 3;
|
||||
u8 Flags : 5;
|
||||
u8 SizeOfProlog;
|
||||
u8 CountOfCodes;
|
||||
u8 FrameRegister : 4;
|
||||
u8 FrameOffset : 4;
|
||||
//ULONG ExceptionHandler;
|
||||
UNWIND_CODE UnwindCode[1];
|
||||
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
||||
* union {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
|
||||
static RUNTIME_FUNCTION Table[1];
|
||||
static _UNWIND_INFO unwind_info[1];
|
||||
|
||||
EXCEPTION_DISPOSITION
|
||||
__gnat_SEH_error_handler(struct _EXCEPTION_RECORD* ExceptionRecord,
|
||||
void *EstablisherFrame,
|
||||
struct _CONTEXT* ContextRecord,
|
||||
void *DispatcherContext)
|
||||
{
|
||||
EXCEPTION_POINTERS ep;
|
||||
ep.ContextRecord = ContextRecord;
|
||||
ep.ExceptionRecord = ExceptionRecord;
|
||||
|
||||
return (EXCEPTION_DISPOSITION)ExeptionHandler(&ep);
|
||||
}
|
||||
|
||||
PRUNTIME_FUNCTION
|
||||
seh_callback(
|
||||
_In_ DWORD64 ControlPc,
|
||||
_In_opt_ PVOID Context
|
||||
) {
|
||||
unwind_info[0].Version = 1;
|
||||
unwind_info[0].Flags = UNW_FLAG_UHANDLER;
|
||||
/* We don't use the unwinding info so fill the structure with 0 values. */
|
||||
unwind_info[0].SizeOfProlog = 0;
|
||||
unwind_info[0].CountOfCodes = 0;
|
||||
unwind_info[0].FrameOffset = 0;
|
||||
unwind_info[0].FrameRegister = 0;
|
||||
/* Add the exception handler. */
|
||||
|
||||
// unwind_info[0].ExceptionHandler =
|
||||
// (DWORD)((u8 *)__gnat_SEH_error_handler - CodeCache);
|
||||
/* Set its scope to the entire program. */
|
||||
Table[0].BeginAddress = 0;// (CodeCache - (u8*)__ImageBase);
|
||||
Table[0].EndAddress = /*(CodeCache - (u8*)__ImageBase) +*/ CODE_SIZE;
|
||||
Table[0].UnwindData = (DWORD)((u8 *)unwind_info - CodeCache);
|
||||
printf("TABLE CALLBACK\n");
|
||||
//for (;;);
|
||||
return Table;
|
||||
}
|
||||
void setup_seh() {
|
||||
#if 1
|
||||
/* Get the base of the module. */
|
||||
//u8* __ImageBase = (u8*)GetModuleHandle(NULL);
|
||||
/* Current version is always 1 and we are registering an
|
||||
exception handler. */
|
||||
unwind_info[0].Version = 1;
|
||||
unwind_info[0].Flags = UNW_FLAG_NHANDLER;
|
||||
/* We don't use the unwinding info so fill the structure with 0 values. */
|
||||
unwind_info[0].SizeOfProlog = 0;
|
||||
unwind_info[0].CountOfCodes = 1;
|
||||
unwind_info[0].FrameOffset = 0;
|
||||
unwind_info[0].FrameRegister = 0;
|
||||
/* Add the exception handler. */
|
||||
|
||||
unwind_info[0].UnwindCode[0].CodeOffset = 0;
|
||||
unwind_info[0].UnwindCode[0].UnwindOp = 2;// UWOP_ALLOC_SMALL;
|
||||
unwind_info[0].UnwindCode[0].OpInfo = 0x20 / 8;
|
||||
|
||||
//unwind_info[0].ExceptionHandler =
|
||||
//(DWORD)((u8 *)__gnat_SEH_error_handler - CodeCache);
|
||||
/* Set its scope to the entire program. */
|
||||
Table[0].BeginAddress = 0;// (CodeCache - (u8*)__ImageBase);
|
||||
Table[0].EndAddress = /*(CodeCache - (u8*)__ImageBase) +*/ CODE_SIZE;
|
||||
Table[0].UnwindData = (DWORD)((u8 *)unwind_info - CodeCache);
|
||||
/* Register the unwind information. */
|
||||
RtlAddFunctionTable(Table, 1, (DWORD64)CodeCache);
|
||||
#endif
|
||||
|
||||
//verify(RtlInstallFunctionTableCallback((unat)CodeCache | 0x3, (DWORD64)CodeCache, CODE_SIZE, seh_callback, 0, 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShowCmd)
|
||||
{
|
||||
ReserveBottomMemory();
|
||||
|
@ -511,19 +618,26 @@ int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine
|
|||
|
||||
SetupPath();
|
||||
|
||||
//SetUnhandledExceptionFilter(&ExeptionHandler);
|
||||
__try
|
||||
{
|
||||
{
|
||||
int dc_init(int argc,wchar* argv[]);
|
||||
void dc_run();
|
||||
void dc_term();
|
||||
dc_init(argc,argv);
|
||||
|
||||
#ifdef _WIN64
|
||||
setup_seh();
|
||||
#endif
|
||||
|
||||
dc_run();
|
||||
dc_term();
|
||||
}
|
||||
__except( (EXCEPTION_CONTINUE_EXECUTION==ExeptionHandler( GetExceptionCode(), (GetExceptionInformation()))) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH )
|
||||
__except( ExeptionHandler(GetExceptionInformation()) )
|
||||
{
|
||||
printf("Unhandled exception - Emulation thread halted...\n");
|
||||
}
|
||||
SetUnhandledExceptionFilter(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue