#define CONTEXT_RBP(context) (context->ContextRecord->Rbp)
#define CONTEXT_RSI(context) (context->ContextRecord->Rsi)
#define CONTEXT_RDI(context) (context->ContextRecord->Rdi)
+#define CONTEXT_R8(context) (context->ContextRecord->R8)
+#define CONTEXT_R9(context) (context->ContextRecord->R9)
+#define CONTEXT_R10(context) (context->ContextRecord->R10)
+#define CONTEXT_R11(context) (context->ContextRecord->R11)
+#define CONTEXT_R12(context) (context->ContextRecord->R12)
+#define CONTEXT_R13(context) (context->ContextRecord->R13)
+#define CONTEXT_R14(context) (context->ContextRecord->R14)
+#define CONTEXT_R15(context) (context->ContextRecord->R15)
#elif defined(_WIN32) && defined(CPU_i386)
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->Eip)
+#define CONTEXT_RAX(context) (context->ContextRecord->Eax)
+#define CONTEXT_RCX(context) (context->ContextRecord->Ecx)
+#define CONTEXT_RDX(context) (context->ContextRecord->Edx)
+#define CONTEXT_RBX(context) (context->ContextRecord->Ebx)
+#define CONTEXT_RSP(context) (context->ContextRecord->Esp)
+#define CONTEXT_RBP(context) (context->ContextRecord->Ebp)
+#define CONTEXT_RSI(context) (context->ContextRecord->Esi)
+#define CONTEXT_RDI(context) (context->ContextRecord->Edi)
#elif defined(HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS) && defined(CPU_x86_64)
#define CONTEXT_RBP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RBP])
#define CONTEXT_RSI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RSI])
#define CONTEXT_RDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_RDI])
+#define CONTEXT_R8(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R8])
+#define CONTEXT_R9(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R9])
+#define CONTEXT_R10(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R10])
+#define CONTEXT_R11(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R11])
+#define CONTEXT_R12(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R12])
+#define CONTEXT_R13(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R13])
+#define CONTEXT_R14(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R14])
+#define CONTEXT_R15(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_R15])
#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_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_RIP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EIP])
+#define CONTEXT_RAX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EAX])
+#define CONTEXT_RCX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ECX])
+#define CONTEXT_RDX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDX])
+#define CONTEXT_RBX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBX])
+#define CONTEXT_RSP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESP])
+#define CONTEXT_RBP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBP])
+#define CONTEXT_RSI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESI])
+#define CONTEXT_RDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDI])
#elif defined(__DARWIN_UNIX03) && defined(CPU_x86_64)
#define CONTEXT_RBP(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rbp)
#define CONTEXT_RSI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rsi)
#define CONTEXT_RDI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__rdi)
+#define CONTEXT_R8(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r8)
+#define CONTEXT_R9(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r9)
+#define CONTEXT_R10(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r10)
+#define CONTEXT_R11(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r11)
+#define CONTEXT_R12(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r12)
+#define CONTEXT_R13(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r13)
+#define CONTEXT_R14(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r14)
+#define CONTEXT_R15(context) (((ucontext_t *) context)->uc_mcontext->__ss.__r15)
#elif defined(__DARWIN_UNIX03) && defined(CPU_i386)
typedef void *CONTEXT_T;
#define HAVE_CONTEXT_T 1
-#define CONTEXT_EIP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__eip))
-#define CONTEXT_EAX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__eax)
-#define CONTEXT_ECX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ecx)
-#define CONTEXT_EDX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edx)
-#define CONTEXT_EBX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebx)
-#define CONTEXT_ESP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__esp))
-#define CONTEXT_EBP(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebp)
-#define CONTEXT_ESI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__esi)
-#define CONTEXT_EDI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edi)
+#define CONTEXT_RIP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__eip))
+#define CONTEXT_RAX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__eax)
+#define CONTEXT_RCX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ecx)
+#define CONTEXT_RDX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edx)
+#define CONTEXT_RBX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebx)
+#define CONTEXT_RSP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__esp))
+#define CONTEXT_RBP(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebp)
+#define CONTEXT_RSI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__esi)
+#define CONTEXT_RDI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edi)
#endif
-#if defined(CPU_x86_64)
-#ifdef CONTEXT_RIP
#define CONTEXT_PC(context) CONTEXT_RIP(context)
-#endif
-#else
-#ifdef CONTEXT_EIP
-#define CONTEXT_PC(context) CONTEXT_EIP(context)
-#endif
-#endif
/* FIXME: replace usage with bswap16, move fallback defition to header */
static inline uae_u16 swap16(uae_u16 x)
return 0;
}
-static bool decode_instruction(uae_u8 *pc, int *r, int *dir, int *size, int *len)
+/* Opcode register id list:
+ *
+ * 8 Bit: 16 Bit: 32 Bit:
+ *
+ * 0: AL 0: AX 0: EAX
+ * 1: CL 1: CX 1: ECX
+ * 2: DL 2: DX 2: EDX
+ * 3: BL 3: BX 3: EBX
+ * 4: AH (SPL, if REX) 4: SP 4: ESP
+ * 5: CH (BPL, if REX) 5: BP 5: EBP
+ * 6: DH (SIL, if REX) 6: SI 6: ESI
+ * 7: BH (DIL, if REX) 7: DI 7: EDI
+ * 8: R8L 8: R8W 8: R8D
+ * 9: R9L 9: R9W 9: R9D
+ * 10: R10L 10: R10W 10: R10D
+ * 11: R11L 11: R11W 11: R11D
+ * 12: R12L 12: R12W 12: R12D
+ * 13: R13L 13: R13W 13: R13D
+ * 14: R14L 14: R14W 14: R14D
+ * 15: R15L 15: R15W 15: R15D
+ */
+
+static bool decode_instruction(
+ uae_u8 *pc, int *r, int *dir, int *size, int *len, int *rex)
{
*r = -1;
*size = 4;
*dir = -1;
*len = 0;
+ *rex = 0;
#ifdef CPU_x86_64
+ /* Skip address-size override prefix. */
if (*pc == 0x67) {
- /* Skip address-size override prefix */
- pc += 1;
- *len += 1;
- }
- if (*pc == 0x40) {
- /* Skip REX prefix */
pc += 1;
*len += 1;
}
#endif
+ /* Operand size override prefix. */
if (*pc == 0x66) {
pc += 1;
*size = 2;
*len += 1;
}
+#ifdef CPU_x86_64
+ /* Handle x86-64 REX prefix. */
+ if ((pc[0] & 0xf0) == 0x40) {
+ *rex = pc[0];
+ pc += 1;
+ *len += 1;
+ if (*rex & (1 << 3)) {
+ *size = 8;
+ /* 64-bit operand size not supported. */
+ return 0;
+ }
+ }
+#endif
switch (pc[0]) {
- case 0x8a:
+ case 0x8a: /* MOV r8, m8 */
if ((pc[1] & 0xc0) == 0x80) {
*r = (pc[1] >> 3) & 7;
*dir = SIG_READ;
break;
}
break;
- case 0x88:
+ case 0x88: /* MOV m8, r8 */
if ((pc[1] & 0xc0) == 0x80) {
*r = (pc[1] >> 3) & 7;
*dir = SIG_WRITE;
break;
}
break;
- case 0x8b:
+ case 0x8b: /* MOV r32, m32 */
switch (pc[1] & 0xc0) {
case 0x80:
*r = (pc[1] >> 3) & 7;
break;
}
break;
- case 0x89:
- switch (pc[1]&0xc0) {
+ case 0x89: /* MOV m32, r32 */
+ switch (pc[1] & 0xc0) {
case 0x80:
*r = (pc[1] >> 3) & 7;
*dir = SIG_WRITE;
}
break;
}
- return r != 0;
+#ifdef CPU_x86_64
+ if (*rex & (1 << 2)) {
+ /* Use x86-64 extended registers R8..R15. */
+ *r += 8;
+ }
+#endif
+ return *r != -1;
}
#ifdef HAVE_CONTEXT_T
+
+static void *get_pr_from_context(CONTEXT_T context, int r, int size, int rex)
+{
+ switch (r) {
+ case 0:
+ return &(CONTEXT_RAX(context));
+ case 1:
+ return &(CONTEXT_RCX(context));
+ case 2:
+ return &(CONTEXT_RDX(context));
+ case 3:
+ return &(CONTEXT_RBX(context));
+ case 4:
+ if (size > 1 || rex) {
+ return NULL;
+ } else {
+ return (((uae_u8 *) &(CONTEXT_RAX(context))) + 1); /* AH */
+ }
+ case 5:
+ if (size > 1 || rex) {
+ return &(CONTEXT_RBP(context));
+ } else {
+ return (((uae_u8 *) &(CONTEXT_RCX(context))) + 1); /* CH */
+ }
+ case 6:
+ if (size > 1 || rex) {
+ return &(CONTEXT_RSI(context));
+ } else {
+ return (((uae_u8 *) &(CONTEXT_RDX(context))) + 1); /* DH */
+ }
+ case 7:
+ if (size > 1 || rex) {
+ return &(CONTEXT_RDI(context));
+ } else {
+ return (((uae_u8 *) &(CONTEXT_RBX(context))) + 1); /* BH */
+ }
+#ifdef CPU_x86_64
+ case 8:
+ return &(CONTEXT_R8(context));
+ case 9:
+ return &(CONTEXT_R9(context));
+ case 10:
+ return &(CONTEXT_R10(context));
+ case 11:
+ return &(CONTEXT_R11(context));
+ case 12:
+ return &(CONTEXT_R12(context));
+ case 13:
+ return &(CONTEXT_R13(context));
+ case 14:
+ return &(CONTEXT_R14(context));
+ case 15:
+ return &(CONTEXT_R15(context));
+#endif
+ default:
+ abort ();
+ }
+}
+
+static void log_unhandled_access(uae_u8 *fault_pc)
+{
+ 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"));
+ }
+}
+
/*
* Try to handle faulted memory access in compiled code
*
}
#endif
- int r = -1;
- int size = 4;
- int dir = -1;
- int len = 0;
-
#ifdef DEBUG_ACCESS
- write_log (_T("JIT: Fault address is 0x%lx at PC=%p\n"), fault_addr, fault_pc);
+ 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"));
+ write_log(_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n"));
+
+ if (fault_pc < compiled_code || fault_pc > current_compile_p) {
+ return 0;
+ }
- if (canbang && fault_pc >= compiled_code && fault_pc <= current_compile_p) {
- decode_instruction(fault_pc, &r, &dir, &size, &len);
+ int r = -1, size = 4, dir = -1, len = 0, rex = 0;
+ decode_instruction(fault_pc, &r, &dir, &size, &len, &rex);
+ if (r == -1) {
+ log_unhandled_access(fault_pc);
+ return 0;
}
- if (r!=-1) {
- void *pr = NULL;
#ifdef DEBUG_ACCESS
- write_log (_T("JIT: Register was %d, direction was %d, size was %d\n"),
- r, dir, size);
+ write_log (_T("JIT: Register was %d, direction was %d, size was %d\n"),
+ r, dir, size);
#endif
- switch(r) {
-#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;
- 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) {
- {
- uae_u32 addr = uae_p32(fault_addr) - uae_p32(NATMEM_OFFSET);
+ void *pr = get_pr_from_context(context, r, size, rex);
+ if (pr == NULL) {
+ log_unhandled_access(fault_pc);
+ return 0;
+ }
+
+ 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);
- }
+ 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);
+ uae_u8* original_target = target;
+ target = (uae_u8*) CONTEXT_PC(context);
- uae_u8 vecbuf[5];
- for (int i = 0; i < 5; i++) {
- vecbuf[i] = target[i];
- }
- raw_jmp(uae_p32(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;
-
- 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 (int i = 0; i < 5; i++) {
- raw_mov_b_mi(CONTEXT_PC(context) + i, vecbuf[i]);
- }
- 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 */
- if (delete_trigger(dormant, fault_pc)) {
- return 1;
- }
-#ifdef DEBUG_ACCESS
- write_log (_T("JIT: Huh? Could not find trigger!\n"));
+ write_log(_T("JIT: Create jump to %p\n"), veccode);
+ write_log(_T("JIT: Handled one access!\n"));
#endif
- return 1;
+ 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 {
+ 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 (int i = 0; i < 5; i++) {
+ raw_mov_b_mi(CONTEXT_PC(context) + i, vecbuf[i]);
+ }
+ raw_mov_l_mi(uae_p32(&in_handler), 0);
+ raw_jmp(uae_p32(CONTEXT_PC(context)) + len);
- 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"));
+ in_handler = 1;
+ target = original_target;
+ if (delete_trigger(active, fault_pc)) {
+ return 1;
}
- return 0;
+ /* Not found in the active list. Might be a rom routine that
+ * is in the dormant list */
+ if (delete_trigger(dormant, fault_pc)) {
+ return 1;
+ }
+#ifdef DEBUG_ACCESS
+ write_log (_T("JIT: Huh? Could not find trigger!\n"));
+#endif
+ return 1;
}
+
#endif /* CONTEXT_T */
#ifdef _WIN32