#define SIG_READ 1
#define SIG_WRITE 2
-static int in_handler=0;
+static int in_handler = 0;
static uae_u8 *veccode;
-#ifdef _WIN32
+#if defined(JIT_DEBUG)
+#define DEBUG_ACCESS
+#elif defined(CPU_x86_64)
+#define DEBUG_ACCESS
+#endif
+
+#if defined(_WIN32) && defined(CPU_x86_64)
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_RSI(context) (context->ContextRecord->Rsi)
#define CONTEXT_RDI(context) (context->ContextRecord->Rdi)
-#define CONTEXT_CR2(context) ((uae_u32)(context->ExceptionRecord->ExceptionInformation[1]))
+#elif defined(_WIN32) && defined(CPU_i386)
-#elif HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS
-#ifdef CPU_x86_64
+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)
+#elif defined(HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS) && defined(CPU_x86_64)
+
+typedef void *CONTEXT_T;
+#define HAVE_CONTEXT_T 1
#define CONTEXT_RIP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RIP])
#define CONTEXT_RAX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RAX])
#define CONTEXT_RCX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RCX])
#define CONTEXT_RSI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RSI])
#define CONTEXT_RDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RDI])
-#else
+#elif defined(HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS) && defined(CPU_i386)
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_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
#endif
-#if defined(CPU_64_BIT)
+#if defined(CPU_x86_64)
#ifdef CONTEXT_RIP
#define CONTEXT_PC(context) CONTEXT_RIP(context)
#endif
#endif
#endif
+/* FIXME: replace usage with bswap16, move fallback defition to header */
static inline uae_u16 swap16(uae_u16 x)
{
- return ((x&0xff00)>>8)|((x&0x00ff)<<8);
+ return ((x & 0xff00) >> 8) | ((x & 0x00ff) << 8);
}
+/* FIXME: replace usage with bswap32, move fallback defition to header */
static inline uae_u32 swap32(uae_u32 x)
{
- return ((x&0xff00)<<8)|((x&0x00ff)<<24)|((x&0xff0000)>>8)|((x&0xff000000)>>24);
+ return ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) << 24) |
+ ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
+}
+
+static int delete_trigger(blockinfo *bi, void *pc)
+{
+ while (bi) {
+ if (bi->handler && (uae_u8*)bi->direct_handler <= pc &&
+ (uae_u8*)bi->nexthandler > pc) {
+#ifdef DEBUG_ACCESS
+ write_log(_T("JIT: Deleted trigger (%p < %p < %p) %p\n"),
+ bi->handler, pc, bi->nexthandler, bi->pc_p);
+#endif
+ invalidate_block(bi);
+ raise_in_cl_list(bi);
+ set_special(0);
+ return 1;
+ }
+ bi = bi->next;
+ }
+ return 0;
}
#ifdef HAVE_CONTEXT_T
*
* Returns 1 if handled, 0 otherwise
*/
-static int handle_access(CONTEXT_T context)
+static int handle_access(uintptr_t fault_addr, CONTEXT_T context)
{
- uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context);
- uae_u32 addr = CONTEXT_CR2(context);
+ uae_u8 *fault_pc = (uae_u8 *) CONTEXT_PC(context);
+#ifdef CPU_64_BIT
+ if (fault_addr > 0xffffffff) {
+ return 0;
+ }
+#endif
- int r=-1;
- int size=4;
- int dir=-1;
- int len=0;
+ 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);
+#ifdef DEBUG_ACCESS
+ write_log (_T("JIT: Fault address is 0x%lx at PC=%p\n"), fault_addr, fault_pc);
#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;
+ if (canbang && fault_pc >= compiled_code && fault_pc <= current_compile_p) {
+ uae_u8 *pc = fault_pc;
+#ifdef CPU_x86_64
+ if (*pc == 0x67) {
+ /* Skip address-size override prefix */
+ pc++;
+ len++;
+ }
+#endif
+ if (*pc == 0x66) {
+ pc++;
+ size = 2;
len++;
}
- switch(i[0]) {
+ switch (pc[0]) {
case 0x8a:
- if ((i[1]&0xc0)==0x80) {
- r=(i[1]>>3)&7;
+ if ((pc[1]&0xc0)==0x80) {
+ r=(pc[1]>>3)&7;
dir=SIG_READ;
size=1;
len+=6;
}
break;
case 0x88:
- if ((i[1]&0xc0)==0x80) {
- r=(i[1]>>3)&7;
+ if ((pc[1]&0xc0)==0x80) {
+ r=(pc[1]>>3)&7;
dir=SIG_WRITE;
size=1;
len+=6;
}
break;
case 0x8b:
- switch(i[1]&0xc0) {
+ switch (pc[1]&0xc0) {
case 0x80:
- r=(i[1]>>3)&7;
+ r=(pc[1]>>3)&7;
dir=SIG_READ;
len+=6;
break;
case 0x40:
- r=(i[1]>>3)&7;
+ r=(pc[1]>>3)&7;
dir=SIG_READ;
len+=3;
break;
case 0x00:
- r=(i[1]>>3)&7;
+ r=(pc[1]>>3)&7;
dir=SIG_READ;
len+=2;
break;
}
break;
case 0x89:
- switch(i[1]&0xc0) {
+ switch (pc[1]&0xc0) {
case 0x80:
- r=(i[1]>>3)&7;
+ r=(pc[1]>>3)&7;
dir=SIG_WRITE;
len+=6;
break;
case 0x40:
- r=(i[1]>>3)&7;
+ r=(pc[1]>>3)&7;
dir=SIG_WRITE;
len+=3;
break;
case 0x00:
- r=(i[1]>>3)&7;
+ r=(pc[1]>>3)&7;
dir=SIG_WRITE;
len+=2;
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);
+ void *pr = NULL;
+#ifdef DEBUG_ACCESS
+ 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)
+#if defined(CPU_x86_64)
case 0: pr = &(CONTEXT_RAX(context)); break;
case 1: pr = &(CONTEXT_RCX(context)); break;
case 2: pr = &(CONTEXT_RDX(context)); break;
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);
+ uae_u32 addr = uae_p32(fault_addr) - uae_p32(NATMEM_OFFSET);
+#ifdef DEBUG_ACCESS
+ 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) {
default: abort();
}
}
-#ifdef JIT_DEBUG
+#ifdef DEBUG_ACCESS
write_log (_T("JIT: Handled one access!\n"));
#endif
fflush(stdout);
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);
+ uae_u32 addr = uae_p32(fault_addr) - uae_p32(NATMEM_OFFSET);
+#ifdef DEBUG_ACCESS
+ if ((addr >= 0x10000000 && addr < 0x40000000) ||
+ (addr >= 0x50000000)) {
+ write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"), addr);
}
#endif
+ uae_u8* original_target = target;
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);
+ uae_u8 vecbuf[5];
+ for (int i = 0; i < 5; i++) {
+ vecbuf[i] = target[i];
+ }
+ raw_jmp(uae_p32(veccode));
+
+#ifdef DEBUG_ACCESS
+ write_log (_T("JIT: Create jump to %p\n"), veccode);
write_log (_T("JIT: Handled one access!\n"));
#endif
segvcount++;
- target=veccode;
+ target = veccode;
if (dir==SIG_READ) {
switch(size) {
default: abort();
}
}
- for (i=0;i<5;i++)
+ for (int 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;
+ raw_mov_l_mi(uae_p32(&in_handler), 0);
+ raw_jmp(uae_p32(CONTEXT_PC(context)) + len);
+ in_handler = 1;
+ target = original_target;
+ }
+
+ if (delete_trigger(active, fault_pc)) {
+ return 1;
}
/* 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;
+ * is in the dormant list */
+ if (delete_trigger(dormant, fault_pc)) {
+ return 1;
}
-#ifdef JIT_DEBUG
+#ifdef DEBUG_ACCESS
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("JIT: Can't handle access PC=%p!\n"), fault_pc);
+ if (fault_pc) {
+ write_log (_T("JIT: Instruction bytes"));
+ for (int j = 0; j < 10; j++) {
+ write_log (_T(" %02x"), fault_pc[j]);
}
+ write_log (_T("\n"));
}
- 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 */
if (code != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0)
return EXCEPTION_CONTINUE_SEARCH;
- if (handle_access(info)) {
+ uintptr_t address = info->ExceptionRecord->ExceptionInformation[1];
+ if (handle_access(address, 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)
+static void sigsegv_handler(int signum, siginfo_t *info, void *context)
{
- uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context);
- uae_u32 addr = CONTEXT_CR2(context);
+ uae_u8 *i = (uae_u8 *) CONTEXT_PC(context);
+ uintptr_t address = (uintptr_t) info->si_addr;
if (i >= compiled_code) {
- if (handle_access (context))
+ if (handle_access(address, 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);
+ write_log ("Caught illegal access to %08lx at eip=%p\n", address, i);
}
exit (EXIT_FAILURE);