From: Frode Solheim Date: Fri, 4 Sep 2015 21:03:15 +0000 (+0200) Subject: JIT: moved exception handler into separate module, unify for Win32/Linux X-Git-Tag: 3200~89^2~12 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=a873fa88ba21d6521b9ae712c07f9d6aaf6a3534;p=francis%2Fwinuae.git JIT: moved exception handler into separate module, unify for Win32/Linux --- diff --git a/jit/compemu.h b/jit/compemu.h index 8636de22..b70e99d0 100644 --- a/jit/compemu.h +++ b/jit/compemu.h @@ -107,7 +107,6 @@ extern int check_for_cache_miss(void); extern uae_u32 needed_flags; -extern cacheline cache_tags[]; extern uae_u8* comp_pc_p; extern void* pushall_call_handler; @@ -234,7 +233,6 @@ typedef struct { n_smallstatus nat[N_REGS]; } smallstate; -extern bigstate live; extern int touchcnt; @@ -325,6 +323,7 @@ DECLARE(setcc_m(IMM d, IMM cc)); DECLARE(cmov_b_rr(RW1 d, R1 s, IMM cc)); DECLARE(cmov_w_rr(RW2 d, R2 s, IMM cc)); DECLARE(cmov_l_rr(RW4 d, R4 s, IMM cc)); +DECLARE(setzflg_l(RW4 r)); DECLARE(cmov_l_rm(RW4 d, IMM s, IMM cc)); DECLARE(bsf_l_rr(W4 d, R4 s)); DECLARE(pop_m(IMM d)); @@ -580,3 +579,10 @@ void comp_fbcc_opp (uae_u32 opcode); void comp_fsave_opp (uae_u32 opcode); void comp_frestore_opp (uae_u32 opcode); void comp_fpp_opp (uae_u32 opcode, uae_u16 extra); + +#ifdef _WIN32 +LONG WINAPI EvalException(LPEXCEPTION_POINTERS info); +#if defined(_MSC_VER) && !defined(NO_WIN32_EXCEPTION_HANDLER) +#define USE_STRUCTURED_EXCEPTION_HANDLING +#endif +#endif diff --git a/jit/compemu_codegen.h b/jit/compemu_codegen.h index 2f415d70..ffd36e86 100644 --- a/jit/compemu_codegen.h +++ b/jit/compemu_codegen.h @@ -160,7 +160,6 @@ extern void comp_fbcc_opp (uae_u32 opcode); extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra); extern uae_u32 needed_flags; -extern cacheline cache_tags[]; extern uae_u8* comp_pc_p; extern void* pushall_call_handler; diff --git a/jit/compemu_raw_x86.cpp b/jit/compemu_raw_x86.cpp index 7e4d6f8a..41835f7b 100644 --- a/jit/compemu_raw_x86.cpp +++ b/jit/compemu_raw_x86.cpp @@ -1670,564 +1670,15 @@ STATIC_INLINE void raw_inc_sp(int off) raw_add_l_ri(4,off); } + /************************************************************************* * Handling mistaken direct memory access * *************************************************************************/ - -#ifdef NATMEM_OFFSET -#ifdef _WIN32 // %%% BRIAN KING WAS HERE %%% -#include -#else -#include -#endif -#include - -#define SIG_READ 1 -#define SIG_WRITE 2 - -static int in_handler=0; -static uae_u8 *veccode; - -#ifdef _WIN32 - -#if defined(CPU_64_BIT) -#define ctxPC (pContext->Rip) -#else -#define ctxPC (pContext->Eip) -#endif - -int EvalException (LPEXCEPTION_POINTERS blah, int n_except) -{ - PEXCEPTION_RECORD pExceptRecord = NULL; - PCONTEXT pContext = NULL; - - uae_u8* i = NULL; - uae_u32 addr = 0; - int r=-1; - int size=4; - int dir=-1; - int len=0; - - if (n_except != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) - return EXCEPTION_CONTINUE_SEARCH; - - pExceptRecord = blah->ExceptionRecord; - pContext = blah->ContextRecord; - - if (pContext) - i = (uae_u8 *)ctxPC; - if (pExceptRecord) - addr = (uae_u32)(pExceptRecord->ExceptionInformation[1]); -#ifdef JIT_DEBUG - write_log (_T("JIT: fault address is 0x%x at 0x%x\n"),addr,i); -#endif - if (!canbang || !currprefs.cachesize) - return EXCEPTION_CONTINUE_SEARCH; - - if (in_handler) - write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); - - if (canbang && i>=compiled_code && i<=current_compile_p) { - if (*i==0x66) { - i++; - size=2; - len++; - } - - switch(i[0]) { - case 0x8a: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - size=1; - len+=6; - break; - } - break; - case 0x88: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - size=1; - len+=6; - break; - } - break; - case 0x8b: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=2; - break; - default: - break; - } - break; - case 0x89: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=2; - break; - } - break; - } - } - - if (r!=-1) { - void* pr=NULL; -#ifdef JIT_DEBUG - write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); +#ifdef UAE +#include "exception_handler.cpp" #endif - switch(r) { -#if defined(CPU_64_BIT) - case 0: pr=&(pContext->Rax); break; - case 1: pr=&(pContext->Rcx); break; - case 2: pr=&(pContext->Rdx); break; - case 3: pr=&(pContext->Rbx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Rax))+1); break; - case 5: pr=(size>1)? - (void*)(&(pContext->Rbp)): - (void*)(((uae_u8*)&(pContext->Rcx))+1); break; - case 6: pr=(size>1)? - (void*)(&(pContext->Rsi)): - (void*)(((uae_u8*)&(pContext->Rdx))+1); break; - case 7: pr=(size>1)? - (void*)(&(pContext->Rdi)): - (void*)(((uae_u8*)&(pContext->Rbx))+1); break; -#else - case 0: pr=&(pContext->Eax); break; - case 1: pr=&(pContext->Ecx); break; - case 2: pr=&(pContext->Edx); break; - case 3: pr=&(pContext->Ebx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Eax))+1); break; - case 5: pr=(size>1)? - (void*)(&(pContext->Ebp)): - (void*)(((uae_u8*)&(pContext->Ecx))+1); break; - case 6: pr=(size>1)? - (void*)(&(pContext->Esi)): - (void*)(((uae_u8*)&(pContext->Edx))+1); break; - case 7: pr=(size>1)? - (void*)(&(pContext->Edi)): - (void*)(((uae_u8*)&(pContext->Ebx))+1); break; -#endif - default: abort(); - } - if (pr) { - blockinfo* bi; - - if (currprefs.comp_oldsegv) { - addr-=(uae_u32)NATMEM_OFFSET; - -#ifdef JIT_DEBUG - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } -#endif - if (dir==SIG_READ) { - switch (size) { - case 1: *((uae_u8*)pr)=get_byte (addr); break; - case 2: *((uae_u16*)pr)=swap16(get_word (addr)); break; - case 4: *((uae_u32*)pr)=swap32(get_long (addr)); break; - default: abort(); - } - } - else { /* write */ - switch (size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; - case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; - default: abort(); - } - } -#ifdef JIT_DEBUG - write_log (_T("JIT: Handled one access!\n")); -#endif - fflush(stdout); - segvcount++; - ctxPC+=len; - } - else { - void* tmp=target; - int i; - uae_u8 vecbuf[5]; - - addr-=(uae_u32)NATMEM_OFFSET; - -#ifdef JIT_DEBUG - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } -#endif - - target=(uae_u8*)ctxPC; - for (i=0;i<5;i++) - vecbuf[i]=target[i]; - emit_byte(0xe9); - emit_long((uae_u32)veccode-(uae_u32)target-4); -#ifdef JIT_DEBUG - - write_log (_T("JIT: Create jump to %p\n"),veccode); - write_log (_T("JIT: Handled one access!\n")); -#endif - segvcount++; - - target=veccode; - - if (dir==SIG_READ) { - switch(size) { - case 1: raw_mov_b_ri(r,get_byte (addr)); break; - case 2: raw_mov_w_ri(r,swap16(get_word (addr))); break; - case 4: raw_mov_l_ri(r,swap32(get_long (addr))); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; - case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; - default: abort(); - } - } - for (i=0;i<5;i++) - raw_mov_b_mi(ctxPC+i,vecbuf[i]); - raw_mov_l_mi((uae_u32)&in_handler,0); - emit_byte(0xe9); - emit_long(ctxPC+len-(uae_u32)target-4); - in_handler=1; - target=(uae_u8*)tmp; - } - bi=active; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { -#ifdef JIT_DEBUG - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); -#endif - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return EXCEPTION_CONTINUE_EXECUTION; - } - bi=bi->next; - } - /* Not found in the active list. Might be a rom routine that - is in the dormant list */ - bi=dormant; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { -#ifdef JIT_DEBUG - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); -#endif - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return EXCEPTION_CONTINUE_EXECUTION; - } - bi=bi->next; - } -#ifdef JIT_DEBUG - write_log (_T("JIT: Huh? Could not find trigger!\n")); -#endif - return EXCEPTION_CONTINUE_EXECUTION; - } - } - write_log (_T("JIT: Can't handle access %08X!\n"), i); -#if 0 - if (i) - { - int j; - - for (j=0;j<10;j++) { - write_log (_T("JIT: instruction byte %2d is 0x%02x\n"),j,i[j]); - } - } - write_log (_T("Please send the above info (starting at \"fault address\") to\n") - _T("bmeyer@csse.monash.edu.au\n") - _T("This shouldn't happen ;-)\n")); -#endif - return EXCEPTION_CONTINUE_SEARCH; -} -#else -static void vec(int x, struct sigcontext sc) -{ - uae_u8* i=(uae_u8*)sc.eip; - uae_u32 addr=sc.cr2; - int r=-1; - int size=4; - int dir=-1; - int len=0; - int j; - - write_log (_T("JIT: fault address is %08x at %08x\n"),sc.cr2,sc.eip); - if (!canbang) - write_log (_T("JIT: Not happy! Canbang is 0 in SIGSEGV handler!\n")); - if (in_handler) - write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); - - if (canbang && i>=compiled_code && i<=current_compile_p) { - if (*i==0x66) { - i++; - size=2; - len++; - } - - switch(i[0]) { - case 0x8a: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - size=1; - len+=6; - break; - } - break; - case 0x88: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - size=1; - len+=6; - break; - } - break; - - case 0x8b: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=2; - break; - default: - break; - } - break; - - case 0x89: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=2; - break; - } - break; - } - } - - if (r!=-1) { - void* pr=NULL; - write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); - - switch(r) { - case 0: pr=&(sc.eax); break; - case 1: pr=&(sc.ecx); break; - case 2: pr=&(sc.edx); break; - case 3: pr=&(sc.ebx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(sc.eax))+1); break; - case 5: pr=(size>1)? - (void*)(&(sc.ebp)): - (void*)(((uae_u8*)&(sc.ecx))+1); break; - case 6: pr=(size>1)? - (void*)(&(sc.esi)): - (void*)(((uae_u8*)&(sc.edx))+1); break; - case 7: pr=(size>1)? - (void*)(&(sc.edi)): - (void*)(((uae_u8*)&(sc.ebx))+1); break; - default: abort(); - } - if (pr) { - blockinfo* bi; - - if (currprefs.comp_oldsegv) { - addr-=NATMEM_OFFSET; - - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address in %x SEGV handler.\n"),addr); - } - if (dir==SIG_READ) { - switch(size) { - case 1: *((uae_u8*)pr)=get_byte (addr); break; - case 2: *((uae_u16*)pr)=get_word (addr); break; - case 4: *((uae_u32*)pr)=get_long (addr); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,*((uae_u16*)pr)); break; - case 4: put_long (addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - write_log (_T("JIT: Handled one access!\n")); - fflush(stdout); - segvcount++; - sc.eip+=len; - } - else { - void* tmp=target; - int i; - uae_u8 vecbuf[5]; - - addr-=NATMEM_OFFSET; - - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } - - target=(uae_u8*)sc.eip; - for (i=0;i<5;i++) - vecbuf[i]=target[i]; - emit_byte(0xe9); - emit_long((uae_u32)veccode-(uae_u32)target-4); - write_log (_T("JIT: Create jump to %p\n"),veccode); - - write_log (_T("JIT: Handled one access!\n")); - segvcount++; - - target=veccode; - - if (dir==SIG_READ) { - switch(size) { - case 1: raw_mov_b_ri(r,get_byte (addr)); break; - case 2: raw_mov_w_ri(r,get_word (addr)); break; - case 4: raw_mov_l_ri(r,get_long (addr)); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,*((uae_u16*)pr)); break; - case 4: put_long (addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - for (i=0;i<5;i++) - raw_mov_b_mi(sc.eip+i,vecbuf[i]); - raw_mov_l_mi((uae_u32)&in_handler,0); - emit_byte(0xe9); - emit_long(sc.eip+len-(uae_u32)target-4); - in_handler=1; - target=tmp; - } - bi=active; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - /* Not found in the active list. Might be a rom routine that - is in the dormant list */ - bi=dormant; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - write_log (_T("JIT: Huh? Could not find trigger!\n")); - return; - } - } - write_log (_T("JIT: Can't handle access!\n")); - for (j=0;j<10;j++) { - write_log (_T("JIT: instruction byte %2d is %02x\n"),j,i[j]); - } -#if 0 - write_log (_T("Please send the above info (starting at \"fault address\") to\n") - "bmeyer@csse.monash.edu.au\n" - "This shouldn't happen ;-)\n"); - fflush(stdout); -#endif - signal(SIGSEGV,SIG_DFL); /* returning here will cause a "real" SEGV */ -} -#endif -#endif /************************************************************************* * Checking for CPU features * @@ -2322,6 +1773,8 @@ static void cpuid(uae_u32 op, uae_u32 *eax, uae_u32 *ebx, uae_u32 *ecx, uae_u32 { const int CPUID_SPACE = 4096; uae_u8* cpuid_space = (uae_u8*)cache_alloc(CPUID_SPACE); + if (cpuid_space == 0) + abort (); static uae_u32 s_op, s_eax, s_ebx, s_ecx, s_edx; uae_u8* tmp=get_target(); diff --git a/jit/compemu_support.cpp b/jit/compemu_support.cpp index 982e1135..ace8ae6b 100644 --- a/jit/compemu_support.cpp +++ b/jit/compemu_support.cpp @@ -10,7 +10,7 @@ #include "options.h" #include "events.h" -#include "include/memory.h" +#include "memory.h" #include "custom.h" #include "newcpu.h" #include "comptbl.h" @@ -21,7 +21,7 @@ // %%% BRIAN KING WAS HERE %%% extern bool canbang; -#include +//#include extern void jit_abort(const TCHAR*,...); compop_func *compfunctbl[65536]; compop_func *nfcompfunctbl[65536]; @@ -5007,15 +5007,6 @@ STATIC_INLINE void writemem(int address, int source, int offset, int size, int t void writebyte(int address, int source, int tmp) { int distrust = currprefs.comptrustbyte; -#if 0 - switch (currprefs.comptrustbyte) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if ((special_mem&S_WRITE) || distrust) writemem_special(address,source,20,1,tmp); else @@ -5026,15 +5017,6 @@ STATIC_INLINE void writeword_general(int address, int source, int tmp, int clobber) { int distrust = currprefs.comptrustword; -#if 0 - switch (currprefs.comptrustword) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if ((special_mem&S_WRITE) || distrust) writemem_special(address,source,16,2,tmp); else @@ -5055,15 +5037,6 @@ STATIC_INLINE void writelong_general(int address, int source, int tmp, int clobber) { int distrust = currprefs.comptrustlong; -#if 0 - switch (currprefs.comptrustlong) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if ((special_mem&S_WRITE) || distrust) writemem_special(address,source,12,4,tmp); else @@ -5137,15 +5110,6 @@ STATIC_INLINE void readmem(int address, int dest, int offset, int size, int tmp) void readbyte(int address, int dest, int tmp) { int distrust = currprefs.comptrustbyte; -#if 0 - switch (currprefs.comptrustbyte) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if ((special_mem&S_READ) || distrust) readmem_special(address,dest,8,1,tmp); else @@ -5155,15 +5119,6 @@ void readbyte(int address, int dest, int tmp) void readword(int address, int dest, int tmp) { int distrust = currprefs.comptrustword; -#if 0 - switch (currprefs.comptrustword) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if ((special_mem&S_READ) || distrust) readmem_special(address,dest,4,2,tmp); else @@ -5173,15 +5128,6 @@ void readword(int address, int dest, int tmp) void readlong(int address, int dest, int tmp) { int distrust = currprefs.comptrustlong; -#if 0 - switch (currprefs.comptrustlong) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if ((special_mem&S_READ) || distrust) readmem_special(address,dest,0,4,tmp); else @@ -5220,15 +5166,6 @@ STATIC_INLINE void get_n_addr_real(int address, int dest, int tmp) void get_n_addr(int address, int dest, int tmp) { int distrust = currprefs.comptrustnaddr; -#if 0 - switch (currprefs.comptrustnaddr) { - case 0: distrust=0; break; - case 1: distrust=1; break; - case 2: distrust=((start_pc&0xF80000)==0xF80000); break; - case 3: distrust=!have_done_picasso; break; - default: abort(); - } -#endif if (special_mem || distrust) get_n_addr_old(address,dest,tmp); else @@ -5669,10 +5606,7 @@ void build_comp(void) #endif raw_init_cpu(); #ifdef NATMEM_OFFSET - write_log (_T("JIT: Setting signal handler\n")); -#ifndef _WIN32 - signal(SIGSEGV,vec); -#endif + install_exception_handler(); #endif write_log (_T("JIT: Building Compiler function table\n")); for (opcode = 0; opcode < 65536; opcode++) { diff --git a/jit/exception_handler.cpp b/jit/exception_handler.cpp new file mode 100644 index 00000000..e93ade41 --- /dev/null +++ b/jit/exception_handler.cpp @@ -0,0 +1,426 @@ +/************************************************************************* +* Handling mistaken direct memory access * +*************************************************************************/ + +#ifdef NATMEM_OFFSET +#ifdef _WIN32 // %%% BRIAN KING WAS HERE %%% +#include +#else +#ifndef __USE_GNU +#define __USE_GNU +#endif +#include +#endif +#include + +#define SIG_READ 1 +#define SIG_WRITE 2 + +static int in_handler=0; +static uae_u8 *veccode; + +#ifdef _WIN32 + +typedef LPEXCEPTION_POINTERS CONTEXT_T; +#define HAVE_CONTEXT_T 1 + +#define CONTEXT_EIP(context) (context->ContextRecord->Eip) +#define CONTEXT_EAX(context) (context->ContextRecord->Eax) +#define CONTEXT_ECX(context) (context->ContextRecord->Ecx) +#define CONTEXT_EDX(context) (context->ContextRecord->Edx) +#define CONTEXT_EBX(context) (context->ContextRecord->Ebx) +#define CONTEXT_ESP(context) (context->ContextRecord->Esp) +#define CONTEXT_EBP(context) (context->ContextRecord->Ebp) +#define CONTEXT_ESI(context) (context->ContextRecord->Esi) +#define CONTEXT_EDI(context) (context->ContextRecord->Edi) + +#define CONTEXT_RIP(context) (context->ContextRecord->Rip) +#define CONTEXT_RAX(context) (context->ContextRecord->Rax) +#define CONTEXT_RCX(context) (context->ContextRecord->Rcx) +#define CONTEXT_RDX(context) (context->ContextRecord->Rdx) +#define CONTEXT_RBX(context) (context->ContextRecord->Rbx) +#define CONTEXT_RSP(context) (context->ContextRecord->Rsp) +#define CONTEXT_RBP(context) (context->ContextRecord->Rbp) +#define CONTEXT_RSI(context) (context->ContextRecord->Rsi) +#define CONTEXT_RDI(context) (context->ContextRecord->Rdi) + +#define CONTEXT_CR2(context) ((uae_u32)(context->ExceptionRecord->ExceptionInformation[1])) + +#elif HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS + +typedef void *CONTEXT_T; +#define HAVE_CONTEXT_T 1 + +#define CONTEXT_EIP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EIP]) +#define CONTEXT_EAX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EAX]) +#define CONTEXT_ECX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ECX]) +#define CONTEXT_EDX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDX]) +#define CONTEXT_EBX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBX]) +#define CONTEXT_ESP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESP]) +#define CONTEXT_EBP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBP]) +#define CONTEXT_ESI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESI]) +#define CONTEXT_EDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDI]) + +#define CONTEXT_CR2(context) (((struct ucontext *) context)->uc_mcontext.cr2) + +#endif + +#if defined(CPU_64_BIT) +#ifdef CONTEXT_RIP +#define CONTEXT_PC(context) CONTEXT_RIP(context) +#endif +#else +#ifdef CONTEXT_EIP +#define CONTEXT_PC(context) CONTEXT_EIP(context) +#endif +#endif + +#ifdef HAVE_CONTEXT_T +/* + * Try to handle faulted memory access in compiled code + * + * Returns 1 if handled, 0 otherwise + */ +static int handle_access(CONTEXT_T context) +{ + uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context); + uae_u32 addr = CONTEXT_CR2(context); + + int r=-1; + int size=4; + int dir=-1; + int len=0; + +#ifdef JIT_DEBUG + write_log (_T("JIT: fault address is 0x%x at 0x%x\n"),addr,i); +#endif + if (!canbang || !currprefs.cachesize) + return 0; + + if (in_handler) + write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); + + if (canbang && i>=compiled_code && i<=current_compile_p) { + if (*i==0x66) { + i++; + size=2; + len++; + } + + switch(i[0]) { + case 0x8a: + if ((i[1]&0xc0)==0x80) { + r=(i[1]>>3)&7; + dir=SIG_READ; + size=1; + len+=6; + break; + } + break; + case 0x88: + if ((i[1]&0xc0)==0x80) { + r=(i[1]>>3)&7; + dir=SIG_WRITE; + size=1; + len+=6; + break; + } + break; + case 0x8b: + switch(i[1]&0xc0) { + case 0x80: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=6; + break; + case 0x40: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=3; + break; + case 0x00: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=2; + break; + default: + break; + } + break; + case 0x89: + switch(i[1]&0xc0) { + case 0x80: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=6; + break; + case 0x40: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=3; + break; + case 0x00: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=2; + break; + } + break; + } + } + + if (r!=-1) { + void* pr=NULL; +#ifdef JIT_DEBUG + write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); +#endif + + switch(r) { +#if defined(CPU_64_BIT) + case 0: pr = &(CONTEXT_RAX(context)); break; + case 1: pr = &(CONTEXT_RCX(context)); break; + case 2: pr = &(CONTEXT_RDX(context)); break; + case 3: pr = &(CONTEXT_RBX(context)); break; + case 4: pr = (size > 1) ? NULL + : (((uae_u8*)&(CONTEXT_RAX(context)))+1); + break; + case 5: pr = (size > 1) ? (void*) (&(CONTEXT_RBP(context))) + : (void*)(((uae_u8*)&(CONTEXT_RCX(context))) + 1); + break; + case 6: pr = (size > 1) ? (void*) (&(CONTEXT_RSI(context))) + : (void*)(((uae_u8*)&(CONTEXT_RDX(context))) + 1); + break; + case 7: pr = (size > 1) ? (void*) (&(CONTEXT_RDI(context))) + : (void*)(((uae_u8*)&(CONTEXT_RBX(context))) + 1); + break; +#else + case 0: pr = &(CONTEXT_EAX(context)); break; + case 1: pr = &(CONTEXT_ECX(context)); break; + case 2: pr = &(CONTEXT_EDX(context)); break; + case 3: pr = &(CONTEXT_EBX(context)); break; + case 4: pr = (size > 1) ? NULL + : (((uae_u8*)&(CONTEXT_EAX(context)))+1); + break; + case 5: pr = (size > 1) ? (void*) (&(CONTEXT_EBP(context))) + : (void*)(((uae_u8*)&(CONTEXT_ECX(context))) + 1); + break; + case 6: pr = (size > 1) ? (void*) (&(CONTEXT_ESI(context))) + : (void*)(((uae_u8*)&(CONTEXT_EDX(context))) + 1); + break; + case 7: pr = (size > 1) ? (void*) (&(CONTEXT_EDI(context))) + : (void*)(((uae_u8*)&(CONTEXT_EBX(context))) + 1); + break; +#endif + default: + abort (); + } + if (pr) { + blockinfo* bi; + + if (currprefs.comp_oldsegv) { + addr-=(uae_u32)NATMEM_OFFSET; + +#ifdef JIT_DEBUG + if ((addr>=0x10000000 && addr<0x40000000) || + (addr>=0x50000000)) { + write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); + } +#endif + if (dir==SIG_READ) { + switch (size) { + case 1: *((uae_u8*)pr)=get_byte (addr); break; + case 2: *((uae_u16*)pr)=swap16(get_word (addr)); break; + case 4: *((uae_u32*)pr)=swap32(get_long (addr)); break; + default: abort(); + } + } + else { /* write */ + switch (size) { + case 1: put_byte (addr,*((uae_u8*)pr)); break; + case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; + case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; + default: abort(); + } + } +#ifdef JIT_DEBUG + write_log (_T("JIT: Handled one access!\n")); +#endif + fflush(stdout); + segvcount++; + CONTEXT_PC(context) += len; + } + else { + void* tmp=target; + int i; + uae_u8 vecbuf[5]; + + addr-=(uae_u32)NATMEM_OFFSET; + +#ifdef JIT_DEBUG + if ((addr>=0x10000000 && addr<0x40000000) || + (addr>=0x50000000)) { + write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); + } +#endif + + target = (uae_u8*) CONTEXT_PC(context); + for (i=0;i<5;i++) + vecbuf[i]=target[i]; + emit_byte(0xe9); + emit_long((uae_u32)veccode-(uae_u32)target-4); +#ifdef JIT_DEBUG + + write_log (_T("JIT: Create jump to %p\n"),veccode); + write_log (_T("JIT: Handled one access!\n")); +#endif + segvcount++; + + target=veccode; + + if (dir==SIG_READ) { + switch(size) { + case 1: raw_mov_b_ri(r,get_byte (addr)); break; + case 2: raw_mov_w_ri(r,swap16(get_word (addr))); break; + case 4: raw_mov_l_ri(r,swap32(get_long (addr))); break; + default: abort(); + } + } + else { /* write */ + switch(size) { + case 1: put_byte (addr,*((uae_u8*)pr)); break; + case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; + case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; + default: abort(); + } + } + for (i=0;i<5;i++) + raw_mov_b_mi(CONTEXT_PC(context) + i, vecbuf[i]); + raw_mov_l_mi((uae_u32)&in_handler,0); + emit_byte(0xe9); + emit_long(CONTEXT_PC(context) + len - (uae_u32)target - 4); + in_handler=1; + target=(uae_u8*)tmp; + } + bi=active; + while (bi) { + if (bi->handler && + (uae_u8*)bi->direct_handler<=i && + (uae_u8*)bi->nexthandler>i) { +#ifdef JIT_DEBUG + write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), + bi->handler, + i, + bi->nexthandler, + bi->pc_p); +#endif + invalidate_block(bi); + raise_in_cl_list(bi); + set_special(0); + return 1; + } + bi=bi->next; + } + /* Not found in the active list. Might be a rom routine that + is in the dormant list */ + bi=dormant; + while (bi) { + if (bi->handler && + (uae_u8*)bi->direct_handler<=i && + (uae_u8*)bi->nexthandler>i) { +#ifdef JIT_DEBUG + write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), + bi->handler, + i, + bi->nexthandler, + bi->pc_p); +#endif + invalidate_block(bi); + raise_in_cl_list(bi); + set_special(0); + return 1; + } + bi=bi->next; + } +#ifdef JIT_DEBUG + write_log (_T("JIT: Huh? Could not find trigger!\n")); +#endif + return 1; + } + } + write_log (_T("JIT: Can't handle access %08X!\n"), i); +#if 0 + if (i) + { + int j; + + for (j=0;j<10;j++) { + write_log (_T("JIT: instruction byte %2d is 0x%02x\n"),j,i[j]); + } + } + write_log (_T("Please send the above info (starting at \"fault address\") to\n")); + write_log (_T("bmeyer@csse.monash.edu.au\n")); + write_log (_T("This shouldn't happen ;-)\n")); +#endif + return 0; +} +#endif /* CONTEXT_T */ + +#ifdef _WIN32 + +LONG WINAPI EvalException(LPEXCEPTION_POINTERS info) +{ + DWORD code = info->ExceptionRecord->ExceptionCode; + if (code != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) + return EXCEPTION_CONTINUE_SEARCH; + + if (handle_access(info)) { + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +#elif defined(HAVE_CONTEXT_T) + +static void sigsegv_handler(int signum, struct siginfo *info, void *context) +{ + uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context); + uae_u32 addr = CONTEXT_CR2(context); + + if (i >= compiled_code) { + if (handle_access (context)) + return; + else { + int j; + write_log ("JIT: can't handle access!\n"); + for (j = 0 ; j < 10; j++) + write_log ("JIT: instruction byte %2d is %02x\n", i, j[i]); + } + } else { + write_log ("Caught illegal access to %08x at eip=%08x\n", addr, i); + } + + exit (EXIT_FAILURE); +} + +#endif + +static void install_exception_handler(void) +{ +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING + /* Structured exception handler is installed in main.cpp */ +#elif defined(_WIN32) + write_log (_T("JIT: Installing unhandled exception filter\n")); + SetUnhandledExceptionFilter(EvalException); +#elif defined(HAVE_CONTEXT_T) + write_log (_T("JIT: Installing segfault handler\n")); + struct sigaction act; + act.sa_sigaction = (void (*)(int, siginfo_t*, void*)) sigsegv_handler; + sigemptyset (&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &act, NULL); +#else + write_log (_T("JIT: No segfault handler installed\n")); +#endif +} + +#endif /* NATMEM_OFFSET */ diff --git a/main.cpp b/main.cpp index 5e77da30..002077c2 100644 --- a/main.cpp +++ b/main.cpp @@ -41,6 +41,7 @@ #include "cpuboard.h" #include "uae/ppc.h" #include "devices.h" +#include "jit/compemu.h" #ifdef RETROPLATFORM #include "rp.h" #endif @@ -684,8 +685,9 @@ void fixup_prefs (struct uae_prefs *p) #endif } #endif - if (p->maprom && !p->address_space_24) + if (p->maprom && !p->address_space_24) { p->maprom = 0x0f000000; + } if (((p->maprom & 0xff000000) && p->address_space_24) || (p->maprom && p->mbresmem_high_size >= 0x08000000)) { p->maprom = 0x00e00000; } @@ -968,16 +970,15 @@ void do_start_program (void) #ifdef WITH_LUA uae_lua_loadall (); #endif -#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER) - extern int EvalException (LPEXCEPTION_POINTERS blah, int n_except); +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING __try #endif { m68k_go (1); } -#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER) +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING #ifdef JIT - __except (EvalException (GetExceptionInformation (), GetExceptionCode ())) + __except (EvalException(GetExceptionInformation())) #else __except (DummyException (GetExceptionInformation (), GetExceptionCode ())) #endif