about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_private.h4
-rwxr-xr-xsrc/dynarec/dynarec_native_pass.c40
-rwxr-xr-xsrc/include/debug.h1
-rwxr-xr-xsrc/main.c13
-rw-r--r--src/tools/rcfile.c9
5 files changed, 64 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index 1b194e97..d0ca7c9c 100755
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -106,6 +106,10 @@ typedef struct dynarec_arm_s {
     size_t              insts_size; // size of the instruction size array (calculated)
     uint8_t             smread;    // for strongmem model emulation
     uint8_t             smwrite;    // for strongmem model emulation
+    uintptr_t           forward;    // address of the last end of code while testing forward
+    uintptr_t           forward_to; // address of the next jump to (to check if everything is ok)
+    int32_t             forward_size;   // size at the forward point
+    int                 forward_ninst;  // ninst at the forward point
 } dynarec_arm_t;
 
 void add_next(dynarec_arm_t *dyn, uintptr_t addr);
diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index 12dbda7d..df115473 100755
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -40,6 +40,10 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
     // Clean up (because there are multiple passes)
     dyn->f.pending = 0;
     dyn->f.dfnone = 0;
+    dyn->forward = 0;
+    dyn->forward_to = 0;
+    dyn->forward_size = 0;
+    dyn->forward_ninst = 0;
     fpu_reset(dyn);
     int reset_n = -1;
     dyn->last_ip = (dyn->insts && dyn->insts[0].pred_sz)?0:ip;  // RIP is always set at start of block unless there is a predecessor!
@@ -177,6 +181,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
                 dyn->last_ip = 0;
             }
         }
+        #ifndef PROT_READ
+        #define PROT_READ 1
+        #endif
         #if STEP != 0
         if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
             ok = 1;
@@ -195,7 +202,29 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
             }
         }
         #else
-        if(!ok && !need_epilog && box64_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM)
+        if(dyn->forward) {
+            if(dyn->forward_to == addr && !need_epilog) {
+                // we made it!
+                if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
+                dyn->forward = 0;
+                dyn->forward_to = 0;
+                dyn->forward_size = 0;
+                dyn->forward_ninst = 0;
+                ok = 1; // in case it was 0
+            } else if ((dyn->forward_to < addr) || !ok) {
+                // something when wrong! rollback
+                if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
+                ok = 0;
+                dyn->size = dyn->forward_size;
+                ninst = dyn->forward_ninst;
+                addr = dyn->forward;
+                dyn->forward = 0;
+                dyn->forward_to = 0;
+                dyn->forward_size = 0;
+                dyn->forward_ninst = 0;
+            }
+            // else just continue
+        } else if(!ok && !need_epilog && box64_dynarec_bigblock && (getProtection(addr+3)&~PROT_READ))
             if(*(uint32_t*)addr!=0) {   // check if need to continue (but is next 4 bytes are 0, stop)
                 uintptr_t next = get_closest_next(dyn, addr);
                 if(next && (
@@ -211,8 +240,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
                             ii=ninst;
                         }
                     if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
-                } else if(next && (next-addr)<30) {
-                    if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
+                } else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
+                    dyn->forward = addr;
+                    dyn->forward_to = next;
+                    dyn->forward_size = dyn->size;
+                    dyn->forward_ninst = ninst;
+                    reset_n = -2;
+                    ok = 1;
                 }
             }
         #endif
diff --git a/src/include/debug.h b/src/include/debug.h
index e2e75ee1..e13de642 100755
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -15,6 +15,7 @@ extern int box64_dynarec_trace;
 extern int box64_dynarec_forced;
 extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
 extern int box64_dynarec_bigblock;
+extern int box64_dynarec_forward;
 extern int box64_dynarec_strongmem;
 extern int box64_dynarec_fastnan;
 extern int box64_dynarec_fastround;
diff --git a/src/main.c b/src/main.c
index 8119af20..8f956361 100755
--- a/src/main.c
+++ b/src/main.c
@@ -51,6 +51,7 @@ int box64_dynarec = 1;
 int box64_dynarec_dump = 0;
 int box64_dynarec_forced = 0;
 int box64_dynarec_bigblock = 1;
+int box64_dynarec_forward = 128;
 int box64_dynarec_strongmem = 0;
 int box64_dynarec_x87double = 0;
 int box64_dynarec_fastnan = 1;
@@ -479,6 +480,18 @@ void LoadLogEnv()
             printf_log(LOG_INFO, "Dynarec will try to make bigger blocks%s\n", (box64_dynarec_bigblock>2)?" even on non-elf memory":"");
 
     }
+    p = getenv("BOX64_DYNAREC_FORWARD");
+    if(p) {
+        int val = -1;
+        if(sscanf(p, "%d", &val)==1) {
+            if(val>=0)
+                box64_dynarec_forward = val;
+        }
+        if(box64_dynarec_forward)
+            printf_log(LOG_INFO, "Dynarec will continue block for %d bytes on forward jump\n", box64_dynarec_forward);
+        else
+            printf_log(LOG_INFO, "Dynarec will not continue block on forward jump\n");
+    }
     p = getenv("BOX64_DYNAREC_STRONGMEM");
     if(p) {
         if(strlen(p)==1) {
diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c
index 810af622..2e99bf2c 100644
--- a/src/tools/rcfile.c
+++ b/src/tools/rcfile.c
@@ -112,6 +112,7 @@ ENTRYBOOL(BOX64_DYNAREC, box64_dynarec)                             \
 ENTRYINT(BOX64_DYNAREC_DUMP, box64_dynarec_dump, 0, 2, 2)           \
 ENTRYINT(BOX64_DYNAREC_LOG, box64_dynarec_log, 0, 3, 2)             \
 ENTRYINT(BOX64_DYNAREC_BIGBLOCK, box64_dynarec_bigblock, 0, 3, 2)   \
+ENTRYSTRING_(BOX64_DYNAREC_FORWARD, box64_dynarec_forward)          \
 ENTRYINT(BOX64_DYNAREC_STRONGMEM, box64_dynarec_strongmem, 0, 2, 2) \
 ENTRYBOOL(BOX64_DYNAREC_X87DOUBLE, box64_dynarec_x87double)         \
 ENTRYBOOL(BOX64_DYNAREC_FASTNAN, box64_dynarec_fastnan)             \
@@ -130,6 +131,7 @@ IGNORE(BOX64_DYNAREC)                                               \
 IGNORE(BOX64_DYNAREC_DUMP)                                          \
 IGNORE(BOX64_DYNAREC_LOG)                                           \
 IGNORE(BOX64_DYNAREC_BIGBLOCK)                                      \
+IGNORE(BOX64_DYNAREC_FORWARD)                                       \
 IGNORE(BOX64_DYNAREC_STRONGMEM)                                     \
 IGNORE(BOX64_DYNAREC_X87DOUBLE)                                     \
 IGNORE(BOX64_DYNAREC_FASTNAN)                                       \
@@ -533,6 +535,13 @@ void ApplyParams(const char* name)
             }
         }
     }
+    if(param->is_box64_dynarec_forward_present) {
+        int forward = 0;
+        if(sscanf(param->box64_dynarec_forward, "%d", &forward)==1) {
+            box64_dynarec_forward = forward;
+            printf_log(LOG_INFO, "Appling BOX64_DYNAREC_FORWARD=%d\n", box64_dynarec_forward);
+        }
+    }
     if(!olddynarec && box64_dynarec)
         GatherDynarecExtensions();
     #endif