about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/dynablock.c2
-rw-r--r--src/dynarec/dynarec_native.c34
-rw-r--r--src/dynarec/dynarec_native_pass.c4
-rw-r--r--src/include/dynarec_native.h2
4 files changed, 28 insertions, 14 deletions
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c
index 517a702e..7a7e4033 100644
--- a/src/dynarec/dynablock.c
+++ b/src/dynarec/dynablock.c
@@ -238,7 +238,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
             mutex_unlock(&my_context->mutex_dyndump);
         return NULL;
     }
-    void* ret = FillBlock64(block, filladdr, (addr==filladdr)?0:1, is32bits);
+    void* ret = FillBlock64(block, filladdr, (addr==filladdr)?0:1, is32bits, MAX_INSTS);
     if(!ret) {
         dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
         customFree(block);
diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c
index 678f5426..e8406cce 100644
--- a/src/dynarec/dynarec_native.c
+++ b/src/dynarec/dynarec_native.c
@@ -553,10 +553,10 @@ void CancelBlock64(int need_lock)
         mutex_unlock(&my_context->mutex_dyndump);
 }
 
-uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
-uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
-uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
-uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
+uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max);
+uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max);
+uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max);
+uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max);
 
 void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) {
     block->isize = 0;
@@ -582,7 +582,7 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) {
     return block;
 }
 
-void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits) {
+void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits, int inst_max) {
     /*
         A Block must have this layout:
 
@@ -626,7 +626,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
     helper.table64 = static_table64;
     helper.table64cap = sizeof(static_table64)/sizeof(uint64_t);
     // pass 0, addresses, x64 jump addresses, overall size of the block
-    uintptr_t end = native_pass0(&helper, addr, alternate, is32bits);
+    uintptr_t end = native_pass0(&helper, addr, alternate, is32bits, inst_max);
     if(helper.abort) {
         if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
         CancelBlock64(0);
@@ -741,7 +741,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
 
 
     // pass 1, float optimizations, first pass for flags
-    native_pass1(&helper, addr, alternate, is32bits);
+    native_pass1(&helper, addr, alternate, is32bits, inst_max);
     if(helper.abort) {
         if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass1\n");
         CancelBlock64(0);
@@ -749,16 +749,30 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
     }
     
     // pass 2, instruction size
-    native_pass2(&helper, addr, alternate, is32bits);
+    native_pass2(&helper, addr, alternate, is32bits, inst_max);
     if(helper.abort) {
         if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass2\n");
         CancelBlock64(0);
         return NULL;
     }
     // keep size of instructions for signal handling
+    size_t native_size = (helper.native_size+7)&~7;   // round the size...
+    // check if size is overlimit
+    if((inst_max==MAX_INSTS) && (native_size>MAXBLOCK_SIZE)) {
+        int imax = 0;
+        size_t max_size = 0;
+        while((max_size<MAXBLOCK_SIZE) && (imax<helper.size)) {
+            max_size += helper.insts[imax].size;
+            ++imax;
+        }
+        if(!imax) return NULL; //that should never happens
+        --imax;
+        if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Dynablock oversized, with %zu (max=%zd), recomputing cutting at %d from %d\n", native_size, MAXBLOCK_SIZE, imax, helper.size);
+        CancelBlock64(0);
+        return FillBlock64(block, addr, alternate, is32bits, imax);
+    }
     size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
     insts_rsize = (insts_rsize+7)&~7;   // round the size...
-    size_t native_size = (helper.native_size+7)&~7;   // round the size...
     size_t arch_size = ARCH_SIZE(&helper);
     // ok, now allocate mapped memory, with executable flag on
     size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize + arch_size;
@@ -799,7 +813,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
     helper.native_size = 0;
     helper.table64size = 0; // reset table64 (but not the cap)
     helper.insts_size = 0;  // reset
-    native_pass3(&helper, addr, alternate, is32bits);
+    native_pass3(&helper, addr, alternate, is32bits, inst_max);
     if(helper.abort) {
         if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass3\n");
         CancelBlock64(0);
diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index 8128d1b8..ba9bf9da 100644
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -32,7 +32,7 @@
 #endif
 #endif
 
-uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits)
+uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max)
 {
     int ok = 1;
     int ninst = 0;
@@ -78,7 +78,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
         // This test is here to prevent things like TABLE64 to be out of range
         // native_size is not exact at this point, but it should be larger, not smaller, and not by a huge margin anyway
         // so it's good enough to avoid overflow in relative to PC data fectching
-        if((dyn->native_size >= MAXBLOCK_SIZE) || (ninst >= MAX_INSTS)) {
+        if(ninst >= inst_max) {
             need_epilog = 1;
             break;
         }
diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h
index 2f305155..2754eed7 100644
--- a/src/include/dynarec_native.h
+++ b/src/include/dynarec_native.h
@@ -24,7 +24,7 @@ typedef struct instsize_s instsize_t;
 void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size);
 
 void CancelBlock64(int need_lock);
-void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits);
+void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits, int inst_max);
 
 void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size, const char* inst_name);