about summary refs log tree commit diff stats
path: root/src/dynarec/dynarec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/dynarec.c')
-rw-r--r--src/dynarec/dynarec.c148
1 files changed, 59 insertions, 89 deletions
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index f0b0eeb5..ab7a21ae 100644
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -1,6 +1,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <pthread.h>
 #include <errno.h>
 #include <setjmp.h>
 
@@ -8,7 +7,6 @@
 #include "box64context.h"
 #include "dynarec.h"
 #include "emu/x64emu_private.h"
-#include "tools/bridge_private.h"
 #include "x64run.h"
 #include "x64emu.h"
 #include "box64stack.h"
@@ -31,6 +29,7 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
 
 void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
 {
+    int is32bits = (R_CS == 0x23);
     #ifdef HAVE_TRACE
     if(!addr) {
         dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
@@ -38,29 +37,28 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
     }
     #endif
     void * jblock;
-    dynablock_t* block = DBGetBlock(emu, addr, 1);
+    dynablock_t* block = NULL;
+    if(hasAlternate((void*)addr)) {
+        printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr);
+        if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
+        uintptr_t old_addr = addr;
+        addr = (uintptr_t)getAlternate((void*)addr);    // set new address
+        R_RIP = addr;   // but also new RIP!
+        *x3 = addr; // and the RIP in x27 register
+        printf_log(LOG_DEBUG, " -> %p\n", (void*)addr);
+        block = DBAlternateBlock(emu, old_addr, addr, is32bits);
+    } else
+        block = DBGetBlock(emu, addr, 1, is32bits);
     if(!block) {
-        // no block, let link table as is...
-        if(hasAlternate((void*)addr)) {
-            printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr);
-            if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
-            addr = (uintptr_t)getAlternate((void*)addr);    // set new address
-            R_RIP = addr;   // but also new RIP!
-            *x3 = addr; // and the RIP in x27 register
-            printf_log(LOG_DEBUG, " -> %p\n", (void*)addr);
-            block = DBGetBlock(emu, addr, 1);
-        }
-        if(!block) {
-            #ifdef HAVE_TRACE
-            if(LOG_INFO<=box64_dynarec_log) {
-                dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
-                elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
-                dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
-            }
-            #endif
-            //tableupdate(native_epilog, addr, table);
-            return native_epilog;
+        #ifdef HAVE_TRACE
+        if(LOG_INFO<=box64_dynarec_log) {
+            dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
+            elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
+            dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
         }
+        #endif
+        //tableupdate(native_epilog, addr, table);
+        return native_epilog;
     }
     if(!block->done) {
         // not finished yet... leave linker
@@ -83,26 +81,21 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
 void DynaCall(x64emu_t* emu, uintptr_t addr)
 {
     // prepare setjump for signal handling
-    emu_jmpbuf_t *ejb = NULL;
-    int jmpbuf_reset = 0;
-    if(emu->type == EMUTYPE_MAIN) {
-        ejb = GetJmpBuf();
-        if(!ejb->jmpbuf_ok) {
-            ejb->emu = emu;
-            ejb->jmpbuf_ok = 1;
-            jmpbuf_reset = 1;
-            if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
-                printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
-                addr = R_RIP;   // not sure if it should still be inside DynaCall!
-                #ifdef DYNAREC
-                if(box64_dynarec_test) {
-                    if(emu->test.clean)
-                        x64test_check(emu, R_RIP);
-                    emu->test.clean = 0;
-                }
-                #endif
-            }
+    struct __jmp_buf_tag jmpbuf[1] = {0};
+    int skip = 0;
+    struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
+    emu->jmpbuf = jmpbuf;
+
+    if((skip = sigsetjmp(emu->jmpbuf, 1))) {
+        printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", emu->segs[_FS]);
+        addr = R_RIP;   // not sure if it should still be inside DynaCall!
+        #ifdef DYNAREC
+        if(box64_dynarec_test) {
+            if(emu->test.clean)
+                x64test_check(emu, R_RIP);
+            emu->test.clean = 0;
         }
+        #endif
     }
 #ifdef DYNAREC
     if(!box64_dynarec)
@@ -120,8 +113,10 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
         R_RIP = addr;
         emu->df = d_none;
         while(!emu->quit) {
-            dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
+            int is32bits = (emu->segs[_CS]==0x23);
+            dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
             if(!block || !block->block || !block->done) {
+                skip = 0;
                 // no block, of block doesn't have DynaRec content (yet, temp is not null)
                 // Use interpreter (should use single instruction step...)
                 dynarec_log(LOG_DEBUG, "%04d|Calling Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
@@ -129,7 +124,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
                     emu->test.clean = 0;
                 Run(emu, 1);
             } else {
-                dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,emu);
+                dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->hash, emu);
                 CHECK_FLAGS(emu);
                 // block is here, let's run it!
                 native_prolog(emu, block->block);
@@ -139,16 +134,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
                 emu->quit = 0;
                 emu->fork = 0;
                 emu = x64emu_fork(emu, forktype);
-                if(emu->type == EMUTYPE_MAIN) {
-                    ejb = GetJmpBuf();
-                    ejb->emu = emu;
-                    ejb->jmpbuf_ok = 1;
-                    jmpbuf_reset = 1;
-                    if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
-                        printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
-                        addr = R_RIP;
-                    }
-                }
             }
         }
         emu->quit = 0;  // reset Quit flags...
@@ -167,36 +152,28 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
     }
 #endif
     // clear the setjmp
-    if(ejb && jmpbuf_reset)
-        ejb->jmpbuf_ok = 0;
+    emu->jmpbuf = old_jmpbuf;
 }
 
 int DynaRun(x64emu_t* emu)
 {
     // prepare setjump for signal handling
-    emu_jmpbuf_t *ejb = NULL;
-#ifdef DYNAREC
-    int jmpbuf_reset = 1;
-#endif
-    if(emu->type == EMUTYPE_MAIN) {
-        ejb = GetJmpBuf();
-        if(!ejb->jmpbuf_ok) {
-            ejb->emu = emu;
-            ejb->jmpbuf_ok = 1;
-#ifdef DYNAREC
-            jmpbuf_reset = 1;
-#endif
-            if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
-                printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
-                #ifdef DYNAREC
-                if(box64_dynarec_test) {
-                    if(emu->test.clean)
-                        x64test_check(emu, R_RIP);
-                    emu->test.clean = 0;
-                }
-                #endif
+    struct __jmp_buf_tag jmpbuf[1] = {0};
+    int skip = 0;
+    struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
+    emu->jmpbuf = jmpbuf;
+
+    if((skip=sigsetjmp(emu->jmpbuf, 1))) {
+        printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
+        #ifdef DYNAREC
+        if(box64_dynarec_test) {
+            if(emu->test.clean)
+                x64test_check(emu, R_RIP);
+            emu->test.clean = 0;
         }
+        #endif
     }
+
 #ifdef DYNAREC
     if(!box64_dynarec)
 #endif
@@ -204,8 +181,10 @@ int DynaRun(x64emu_t* emu)
 #ifdef DYNAREC
     else {
         while(!emu->quit) {
-            dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
+            int is32bits = (emu->segs[_CS]==0x23);
+            dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
             if(!block || !block->block || !block->done) {
+                skip = 0;
                 // no block, of block doesn't have DynaRec content (yet, temp is not null)
                 // Use interpreter (should use single instruction step...)
                 dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
@@ -213,7 +192,7 @@ int DynaRun(x64emu_t* emu)
                     emu->test.clean = 0;
                 Run(emu, 1);
             } else {
-                dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, emu);
+                dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->hash, emu);
                 // block is here, let's run it!
                 native_prolog(emu, block->block);
             }
@@ -222,20 +201,11 @@ int DynaRun(x64emu_t* emu)
                 emu->quit = 0;
                 emu->fork = 0;
                 emu = x64emu_fork(emu, forktype);
-                if(emu->type == EMUTYPE_MAIN) {
-                    ejb = GetJmpBuf();
-                    ejb->emu = emu;
-                    ejb->jmpbuf_ok = 1;
-                    jmpbuf_reset = 1;
-                    if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
-                        printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
-                }
             }
         }
     }
     // clear the setjmp
-    if(ejb && jmpbuf_reset)
-        ejb->jmpbuf_ok = 0;
+    emu->jmpbuf = old_jmpbuf;
     return 0;
 #endif
 }