]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
JIT: Proper REX and and extended register support in access fault handler
authorFrode Solheim <frode@fs-uae.net>
Fri, 25 Sep 2015 23:23:14 +0000 (01:23 +0200)
committerFrode Solheim <frode@fs-uae.net>
Fri, 25 Sep 2015 23:23:14 +0000 (01:23 +0200)
jit/exception_handler.cpp

index c3caa59c114789e7e4898144353de39f1e574030..8cf96f82e948b0f54e1c211fac0bb196324386c9 100644 (file)
@@ -38,20 +38,28 @@ typedef LPEXCEPTION_POINTERS CONTEXT_T;
 #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)
 
@@ -66,20 +74,28 @@ typedef void *CONTEXT_T;
 #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)
 
@@ -94,32 +110,32 @@ typedef void *CONTEXT_T;
 #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)
@@ -153,33 +169,66 @@ static int delete_trigger(blockinfo *bi, void *pc)
        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;
@@ -188,7 +237,7 @@ static bool decode_instruction(uae_u8 *pc, int *r, int *dir, int *size, int *len
                        break;
                }
                break;
-       case 0x88:
+       case 0x88: /* MOV m8, r8 */
                if ((pc[1] & 0xc0) == 0x80) {
                        *r = (pc[1] >> 3) & 7;
                        *dir = SIG_WRITE;
@@ -197,7 +246,7 @@ static bool decode_instruction(uae_u8 *pc, int *r, int *dir, int *size, int *len
                        break;
                }
                break;
-       case 0x8b:
+       case 0x8b: /* MOV r32, m32 */
                switch (pc[1] & 0xc0) {
                case 0x80:
                        *r = (pc[1] >> 3) & 7;
@@ -218,8 +267,8 @@ static bool decode_instruction(uae_u8 *pc, int *r, int *dir, int *size, int *len
                        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;
@@ -238,10 +287,87 @@ static bool decode_instruction(uae_u8 *pc, int *r, int *dir, int *size, int *len
                }
                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
  *
@@ -261,147 +387,111 @@ static int handle_access(uintptr_t fault_addr, CONTEXT_T context)
        }
 #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