about summary refs log tree commit diff stats
path: root/src/dynarec
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-10-31 12:05:04 +0100
committerGitHub <noreply@github.com>2022-10-31 12:05:04 +0100
commit8459ea0d31a851e847318273233c9a8b2b079eae (patch)
tree2ab39af3c19d9720d906cd060211107c5dc549a2 /src/dynarec
parent494c245b591cef1a34cc4d4dc52163861d4e54af (diff)
downloadbox64-8459ea0d31a851e847318273233c9a8b2b079eae.tar.gz
box64-8459ea0d31a851e847318273233c9a8b2b079eae.zip
Remove dynablocklist (#438)
* [DYNAREC] Removed dynablock sons handling
* [DYNAREC] Removed dynablocklist, and attached dynablocks to the jumptable
* [DYNAREC] Changed handling of HotPage (part of Protection now)
* [DYNAREC] Fixed some performance issues (especially with heavily threaded programs)
Diffstat (limited to 'src/dynarec')
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.c26
-rw-r--r--src/dynarec/arm64/dynarec_arm64_jmpnext.c11
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_pass2.h1
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_pass3.h4
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_private.h7
-rwxr-xr-xsrc/dynarec/dynablock.c499
-rwxr-xr-xsrc/dynarec/dynablock_private.h22
-rwxr-xr-xsrc/dynarec/dynarec.c40
-rwxr-xr-xsrc/dynarec/dynarec_native.c163
-rwxr-xr-xsrc/dynarec/dynarec_native_pass.c3
-rw-r--r--src/dynarec/dynarec_next.h22
11 files changed, 217 insertions, 581 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index 521b0604..d38c8078 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -403,30 +403,30 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
         }
         uintptr_t tbl = getJumpTable64();
         MAYUSE(tbl);
-        TABLE64(x2, tbl);
-        UBFXx(x3, xRIP, 48, JMPTABL_SHIFT);
-        LDRx_REG_LSL3(x2, x2, x3);
-        UBFXx(x3, xRIP, 32, JMPTABL_SHIFT);
-        LDRx_REG_LSL3(x2, x2, x3);
-        UBFXx(x3, xRIP, 16, JMPTABL_SHIFT);
-        LDRx_REG_LSL3(x2, x2, x3);
-        UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
-        LDRx_REG_LSL3(x3, x2, x3);
+        TABLE64(x3, tbl);
+        UBFXx(x2, xRIP, 48, JMPTABL_SHIFT);
+        LDRx_REG_LSL3(x3, x3, x2);
+        UBFXx(x2, xRIP, 32, JMPTABL_SHIFT);
+        LDRx_REG_LSL3(x3, x3, x2);
+        UBFXx(x2, xRIP, 16, JMPTABL_SHIFT);
+        LDRx_REG_LSL3(x3, x3, x2);
+        UBFXx(x2, xRIP, 0, JMPTABL_SHIFT);
+        LDRx_REG_LSL3(x2, x3, x2);
     } else {
         uintptr_t p = getJumpTableAddress64(ip);
         MAYUSE(p);
-        TABLE64(x2, p);
+        TABLE64(x3, p);
         GETIP_(ip);
-        LDRx_U12(x3, x2, 0);
+        LDRx_U12(x2, x3, 0);
     }
     if(reg!=x1) {
         MOVx_REG(x1, xRIP);
     }
     CLEARIP();
     #ifdef HAVE_TRACE
-    //MOVx(x2, 15);    no access to PC reg 
+    //MOVx(x3, 15);    no access to PC reg 
     #endif
-    BLR(x3); // save LR...
+    BLR(x2); // save LR...
 }
 
 void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
diff --git a/src/dynarec/arm64/dynarec_arm64_jmpnext.c b/src/dynarec/arm64/dynarec_arm64_jmpnext.c
new file mode 100644
index 00000000..c40dfb1e
--- /dev/null
+++ b/src/dynarec/arm64/dynarec_arm64_jmpnext.c
@@ -0,0 +1,11 @@
+#include <stdint.h>
+
+#include "arm64_emitter.h"
+
+#define EMIT(A) *block = (A); ++block
+void CreateJmpNext(void* addr, void* next)
+{
+    uint32_t* block = (uint32_t*)addr;
+    LDRx_literal(x2, (intptr_t)next - (intptr_t)addr);
+    BR(x2);
+}
\ No newline at end of file
diff --git a/src/dynarec/arm64/dynarec_arm64_pass2.h b/src/dynarec/arm64/dynarec_arm64_pass2.h
index 4a5122c2..29d5f01a 100755
--- a/src/dynarec/arm64/dynarec_arm64_pass2.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass2.h
@@ -8,7 +8,6 @@
                 dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);     \
                 if(ninst && isInstClean(dyn, ninst)) {                                                  \
                         if(dyn->last_ip!=ip) dyn->last_ip = 0;                                          \
-                        ++dyn->sons_size;                                                               \
                 }                                                                                       \
         }
 #define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size; 
diff --git a/src/dynarec/arm64/dynarec_arm64_pass3.h b/src/dynarec/arm64/dynarec_arm64_pass3.h
index d1d8fbba..2a003711 100755
--- a/src/dynarec/arm64/dynarec_arm64_pass3.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass3.h
@@ -10,10 +10,6 @@
 #define NEW_INST        \
     if(ninst && isInstClean(dyn, ninst)) {                      \
         if(dyn->last_ip!=ip) dyn->last_ip = 0;                  \
-        dyn->sons_x64[dyn->sons_size] = (uintptr_t)ip;          \
-        dyn->sons_native[dyn->sons_size] = dyn->block;          \
-        MESSAGE(LOG_DUMP, "----> potential Son here %p/%p\n", (void*)ip, dyn->block);  \
-        ++dyn->sons_size;                                       \
     }
 #define INST_EPILOG     
 #define INST_NAME(name) \
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index 23fe4af5..1cac7d3e 100755
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -5,6 +5,7 @@
 
 typedef struct x64emu_s x64emu_t;
 typedef struct dynablock_s dynablock_t;
+typedef struct instsize_s instsize_t;
 
 #define BARRIER_MAYBE   8
 
@@ -99,11 +100,9 @@ typedef struct dynarec_arm_s {
     uintptr_t*          next;       // variable array of "next" jump address
     int                 next_sz;
     int                 next_cap;
-    uintptr_t*          sons_x64;   // the x64 address of potential dynablock sons
-    void**              sons_native;   // the arm address of potential dynablock sons
-    int                 sons_size;  // number of potential dynablock sons
     int*                predecessor;// single array of all predecessor
     dynablock_t*        dynablock;
+    instsize_t*         instsize;
 } dynarec_arm_t;
 
 void add_next(dynarec_arm_t *dyn, uintptr_t addr);
@@ -113,6 +112,8 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
 
 int Table64(dynarec_arm_t *dyn, uint64_t val);  // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
 
+void CreateJmpNext(void* addr, void* next);
+
 #define GO_TRACE() \
     GETIP_(ip);             \
     MOVx_REG(x1, xRIP);     \
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c
index 43222a2e..b795c3c1 100755
--- a/src/dynarec/dynablock.c
+++ b/src/dynarec/dynablock.c
@@ -3,6 +3,7 @@
 #include <pthread.h>
 #include <errno.h>
 #include <setjmp.h>
+#include <sys/mman.h>
 
 #include "debug.h"
 #include "box64context.h"
@@ -37,111 +38,37 @@ uint32_t X31_hash_code(void* addr, int len)
 	return (uint32_t)h;
 }
 
-dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
-{
-    if(!textsz) {
-        printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
-        return NULL;
-    }
-    dynablocklist_t* ret = (dynablocklist_t*)customCalloc(1, sizeof(dynablocklist_t));
-    ret->text = text;
-    ret->textsz = textsz;
-    ret->minstart = text;
-    ret->maxend = text+textsz-1;
-    if(direct && textsz) {
-        ret->direct = (dynablock_t**)customCalloc(textsz, sizeof(dynablock_t*));
-        if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
-    }
-    dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
-    return ret;
-}
-
 void FreeDynablock(dynablock_t* db, int need_lock)
 {
     if(db) {
         if(db->gone)
             return; // already in the process of deletion!
-        dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->parent, db->father, db->sons_size, db->gone);
+        dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
         if(need_lock)
             pthread_mutex_lock(&my_context->mutex_dyndump);
-        db->done = 0;
-        db->gone = 1;
-        // remove from direct if there
-        uintptr_t startdb = db->parent->text;
-        uintptr_t enddb = db->parent->text + db->parent->textsz;
-        if(db->parent->direct) {
-            uintptr_t addr = (uintptr_t)db->x64_addr;
-            if(addr>=startdb && addr<enddb)
-                native_lock_xchg(&db->parent->direct[addr-startdb], 0);   // secured write
-        }
         // remove jumptable
         setJumpTableDefault64(db->x64_addr);
-        // remove and free the sons
-        for (int i=0; i<db->sons_size; ++i) {
-            dynablock_t *son = (dynablock_t*)native_lock_xchg(&db->sons[i], 0);
-            FreeDynablock(son, 0);
-        }
-        // only the father free the DynarecMap
-        if(!db->father) {
-            dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
-            FreeDynarecMap(db, (uintptr_t)db->block, db->size);
-            customFree(db->sons);
-            customFree(db->instsize);
-        }
+        dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
+        db->done = 0;
+        db->gone = 1;
+        FreeDynarecMap(db, (uintptr_t)db->actual_block, db->size);
         customFree(db);
         if(need_lock)
             pthread_mutex_unlock(&my_context->mutex_dyndump);
     }
 }
 
-void FreeDynablockList(dynablocklist_t** dynablocks)
-{
-    if(!dynablocks)
-        return;
-    if(!*dynablocks)
-        return;
-    dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
-    if((*dynablocks)->direct) {
-        for (int i=0; i<(*dynablocks)->textsz; ++i) {
-            if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father) 
-                FreeDynablock((*dynablocks)->direct[i], 1);
-        }
-        customFree((*dynablocks)->direct);
-    }
-    (*dynablocks)->direct = NULL;
-
-    customFree(*dynablocks);
-    *dynablocks = NULL;
-}
-
 void MarkDynablock(dynablock_t* db)
 {
     if(db) {
-        if(db->father)
-            db = db->father;    // mark only father
         if(db->need_test)
             return; // already done
-        dynarec_log(LOG_DEBUG, "MarkDynablock %p with %d son(s) %p-%p\n", db, db->sons_size, db->x64_addr, db->x64_addr+db->x64_size-1);
+        dynarec_log(LOG_DEBUG, "MarkDynablock %p %p-%p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1);
         db->need_test = 1;
-        setJumpTableDefault64(db->x64_addr);
-        for(int i=0; i<db->sons_size; ++i)
-            setJumpTableDefault64(db->sons[i]->x64_addr);
+        setJumpTableIfRef64(db->x64_addr, db->jmpnext, db->block);
     }
 }
 
-uintptr_t StartDynablockList(dynablocklist_t* db)
-{
-    if(db)
-        return db->text;
-    return 0;
-}
-uintptr_t EndDynablockList(dynablocklist_t* db)
-{
-    if(db)
-        return db->text+db->textsz-1;
-    return 0;
-}
-
 int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
 {
     if(start1 > end2 || start2 > end1)
@@ -152,90 +79,35 @@ int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintp
 static int MarkedDynablock(dynablock_t* db)
 {
     if(db) {
-        if(db->father)
-            db = db->father;    // mark only father
         if(db->need_test)
             return 1; // already done
     }
     return 0;
 }
 
-void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
+void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
 {
     // Mark will try to find *any* blocks that intersect the range to mark
-    if(!dynablocks)
-        return;
-    if(!dynablocks->direct)
+    if(!db)
         return;
-    uintptr_t startdb = dynablocks->text;
-    uintptr_t sizedb = dynablocks->textsz;
-    dynablock_t *db;
-    dynarec_log(LOG_DEBUG, "MarkDirectDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)startdb, (void*)sizedb);
-    for(uintptr_t i = 0; i<sizedb; ++i)
-        if((db=dynablocks->direct[i]) && !MarkedDynablock(db))
-            if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
-                MarkDynablock(db);
+    dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x64_addr, (void*)db->x64_size);
+    if(!MarkedDynablock(db))
+        if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
+            MarkDynablock(db);
 }
 
-int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
+int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
 {
-    if(!dynablocks)
+    if(!db)
         return 1;
 
-    if(dynablocks->direct) {
-        int need_lock = my_context?1:0;
-        dynablock_t* db;
-        int ret;
-        khint_t k;
-        kh_dynablocks_t *blocks = kh_init(dynablocks);
-        // copy in a temporary list
-        uintptr_t startdb = dynablocks->text;
-        uintptr_t enddb = startdb + dynablocks->textsz;
-        uintptr_t start = addr;
-        uintptr_t end = addr+size;
-        if(start<startdb)
-            start = startdb;
-        if(end>enddb)
-            end = enddb;
-        if(end>startdb && start<enddb)
-            for(uintptr_t i = start; i<end; ++i) {
-                db = (dynablock_t*)native_lock_xchg(&dynablocks->direct[i-startdb], 0);
-                if(db) {
-                    if(db->father)
-                        db = db->father;
-                    if(db->parent==dynablocks) {
-                        k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
-                        kh_value(blocks, k) = db;
-                    }
-                }
-            }
-        // purge the list
-        kh_foreach_value(blocks, db,
-            FreeDynablock(db, need_lock);
-        );
-        kh_destroy(dynablocks, blocks);
-        // check emptyness
-        for(uintptr_t i=0; i<dynablocks->textsz; ++i)
-            if(dynablocks->direct[i])
-                return 0;
-        return 1;
+    int need_lock = my_context?1:0;
+    if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1)) {
+        FreeDynablock(db, need_lock);
+        return 0;
     }
     return 1;
 }
-void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
-{
-    if(!dynablocks)
-        return;
-    dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p\n", (void*)addr, (void*)addr+size-1);
-    if(dynablocks->direct) {
-        uintptr_t new_addr = dynablocks->minstart;
-        uintptr_t new_size = dynablocks->maxend - new_addr + 1;
-        MarkDirectDynablock(dynablocks, addr, size);
-        // the blocks check before
-        for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
-            MarkDirectDynablock(getDB(idx), addr, size);
-    }
-}
 
 dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
 {
@@ -246,63 +118,30 @@ dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
         const uintptr_t s = (uintptr_t)db->block;
         const uintptr_t e = (uintptr_t)db->block+db->size;
         if((uintptr_t)addr>=s && (uintptr_t)addr<e)
-            return db->father?db->father:db;
+            return db;
     )
     return NULL;
 }
 
-static dynablocklist_t* getDBFromAddress(uintptr_t addr)
-{
-    const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
-    return getDB(idx);
-}
-
-dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
+dynablock_t *AddNewDynablock(uintptr_t addr)
 {
-    if(!dynablocks) {
-        dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
-        *created = 0;
+    dynablock_t* block;
+    #if 0
+    // check if memory as the correct flags
+    int prot = getProtection(addr);
+    if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
+        dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
         return NULL;
     }
-    if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
-        return AddNewDynablock(getDBFromAddress(addr), addr, created);
-    }
-    dynablock_t* block = NULL;
-    // first, check if it exist in direct access mode
-    if(dynablocks->direct) {
-        block = dynablocks->direct[addr-dynablocks->text];
-        if(block) {
-            dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
-            *created = 0;
-            return block;
-        }
-    }
-    
-    if (!*created)
-        return block;
     
+    #endif
     pthread_mutex_lock(&my_context->mutex_dyndump);
-    if(!dynablocks->direct) {
-        dynablock_t** p = (dynablock_t**)customCalloc(dynablocks->textsz, sizeof(dynablock_t*));
-        if(native_lock_storeifnull(&dynablocks->direct, p)!=p)
-            customFree(p);    // someone already create the direct array, too late...
-    }
 
     // create and add new block
     dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
 
     block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
-    block->parent = dynablocks; 
-    dynablock_t* tmp = (dynablock_t*)native_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
-    if(tmp !=  block) {
-        // a block appeard!
-        pthread_mutex_unlock(&my_context->mutex_dyndump);
-        customFree(block);
-        *created = 0;
-        return tmp;
-    }
 
-    *created = 1;
     pthread_mutex_lock(&my_context->mutex_dyndump);
     return block;
 }
@@ -319,39 +158,26 @@ void cancelFillBlock()
     return NULL if block is not found / cannot be created. 
     Don't create if create==0
 */
-static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
+static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
 {
-    // try the quickest way first: get parent of current and check if ok!
-    dynablocklist_t *dynablocks = NULL;
-    dynablock_t* block = NULL;
-    if(current && current->done && !current->gone) {
-        dynablocks = current->parent;
-        if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
-            dynablocks = NULL;
-    }
-    // nope, lets do the long way
-    if(!dynablocks) {
-        dynablocks = getDBFromAddress(addr);
-        if(!dynablocks) {
-            dynablocks = GetDynablocksFromAddress(emu->context, addr);
-            if(!dynablocks)
-                return NULL;
-        }
-    }
-    // check direct first, without lock
-    if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
-        if((block = dynablocks->direct[addr-dynablocks->text]))
-            return block;
+    dynablock_t* block = getDB(addr);
+    if(block || !create)
+        return block;
 
-    int created = create;
-    block = AddNewDynablock(dynablocks, addr, &created);
-    if(!created)
-        return block;   // existing block...
+    if(need_lock)
+        pthread_mutex_lock(&my_context->mutex_dyndump);
+    
+    block = getDB(addr);    // just in case
+    if(block) {
+        if(need_lock)
+            pthread_mutex_unlock(&my_context->mutex_dyndump);
+        return block;
+    }
+    
+    block = AddNewDynablock(addr);
 
     // fill the block
     block->x64_addr = (void*)addr;
-    if(need_lock)
-        pthread_mutex_lock(&my_context->mutex_dyndump);
     if(sigsetjmp(&dynarec_jmpbuf, 1)) {
         printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
         if(need_lock)
@@ -359,209 +185,59 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
         return NULL;
     }
     void* ret = FillBlock64(block, filladdr);
-    if(need_lock)
-        pthread_mutex_unlock(&my_context->mutex_dyndump);
     if(!ret) {
         dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
-        void* old = (void*)native_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
-        if(old!=block && old) {// put it back in place, strange things are happening here!
-            dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
-            // doing nothing else, the block has not be writen
-        }
         customFree(block);
         block = NULL;
     }
     // check size
-    if(block && block->x64_size) {
-        if(dynablocks->minstart>addr)
-            dynablocks->minstart = addr;
+    if(block && (block->x64_size || (!block->x64_size && !block->done))) {
         int blocksz = block->x64_size;
-        if(dynablocks->maxend<addr+blocksz) {
-            dynablocks->maxend = addr+blocksz;
-            for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz-1)>>DYNAMAP_SHIFT); ++idx) {
-                dynablocklist_t* dblist;
-                if((dblist = getDB(idx)))
-                    if(dblist->minstart>addr)
-                        dblist->minstart = addr;
-            }
-        }
+        if(blocksz>my_context->max_db_size)
+            my_context->max_db_size = blocksz;
         // fill-in jumptable
-        addJumpTableIfDefault64(block->x64_addr, block->block);
-        for(int i=0; i<block->sons_size; ++i) {
-            addJumpTableIfDefault64(block->sons[i]->x64_addr, block->sons[i]->block);
-            block->sons[i]->done = 1;
+        if(!addJumpTableIfDefault64(block->x64_addr, block->block)) {
+            FreeDynablock(block, 1);
+            block = getDB(addr);
+        } else {
+            if(block->x64_size)
+                block->done = 1;    // don't validate the block if the size is null, but keep the block
         }
-        block->done = 1;
     }
+    if(need_lock)
+        pthread_mutex_unlock(&my_context->mutex_dyndump);
 
-    dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", GetTID(), created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
+    dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", GetTID(), (void*)addr, (void*)(addr+((block)?block->x64_size:1)-1), (block)?block->block:0, (block)?block->size:0);
 
     return block;
 }
 
-#define MAX_HOTPAGE 64
-#define HOTPAGE_STEP 64
-static int volatile hotpage_count[MAX_HOTPAGE] = {0};
-static uintptr_t volatile hotpage[MAX_HOTPAGE] = {0};
-static uintptr_t volatile hotpage_size[MAX_HOTPAGE] = {0};
-static volatile int hotpages = 0;
-
-int IsInHotPage(uintptr_t addr) {
-    if(!hotpages)
-        return 0;
-    for(int i=0; i<MAX_HOTPAGE; ++i) {
-        if((hotpage_count[i]>0) && (addr>=hotpage[i]) && (addr<hotpage[i]+0x1000*(hotpage_size[i]+1))) {
-            --hotpage_count[i];
-            if(!hotpage_count[i]) {
-                --hotpages;
-                hotpage_size[i] = 0;
-                dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
-            }
-            __sync_synchronize();
-            return 1;
-        }
-    }
-    return 0;
-}
-
-int AreaInHotPage(uintptr_t start, uintptr_t end) {
-    if(!hotpages)
-        return 0;
-    for(int i=0; i<MAX_HOTPAGE; ++i) {
-        if(hotpage_count[i]>0)
-            if(IntervalIntersects(start, end, hotpage[i], hotpage[i]+0x1000*(hotpage_size[i]+1)-1)) {
-                --hotpage_count[i];
-                if(!hotpage_count[i]) {
-                    --hotpages;
-                    hotpage_size[i] = 0;
-                    dynarec_log(LOG_DEBUG, "End of Hotpage %p\n", (void*)hotpage[i]);
-                }
-                return 1;
-        }
-    }
-    return 0;
-}
-
-void FuseHotPage(int idx) {
-    uintptr_t start = hotpage[idx];
-    uintptr_t end = start+0x1000*(hotpage_size[idx]+1);
-    for(int i=0; i<MAX_HOTPAGE; ++i)
-        if(i!=idx && hotpage_count[i]>0) {
-            if(IntervalIntersects(start, end, hotpage[i], hotpage[i]+0x1000*(hotpage_size[i]+1)-1)) {
-                if(hotpage_count[i]>hotpage_count[idx])
-                    hotpage_count[idx] = hotpage_count[i];
-                if(hotpage[i]>hotpage[idx])
-                    hotpage[idx]=hotpage[i];
-                if(hotpage[i]+0x1000*(hotpage_size[i]+1)>end)
-                    hotpage_size[idx] = ((hotpage[i]+0x1000*(hotpage_size[i]+1))-hotpage[idx])/0x1000 - 1;
-                hotpage_count[i] = 0;
-                return;
-            }
-        }
-}
-
-void AddHotPage(uintptr_t addr) {
-    addr&=~0xfff;
-    // look for same address
-    for(int i=0; i<MAX_HOTPAGE; ++i) {
-        if(addr>=hotpage[i] && addr<hotpage[i]+0x1000*(hotpage_size[i]+1)) {
-            if(!hotpage_count[i])
-                ++hotpages;
-            hotpage_count[i] = HOTPAGE_STEP;
-            __sync_synchronize();
-            return;
-        }
-        if(addr==hotpage[i]+0x1000*(hotpage_size[i]+1)) {
-            ++hotpage_size[i];
-            hotpage_count[i] = HOTPAGE_STEP;
-            FuseHotPage(i);
-            __sync_synchronize();
-            return;
-        }
-        if(addr+0x1000==hotpage[i]) {
-            ++hotpage_size[i];
-            hotpage[i] = addr;
-            hotpage_count[i] = HOTPAGE_STEP;
-            __sync_synchronize();
-            return;
-        }
-        if(addr==hotpage[i]+0x1000*(hotpage_size[i]+2)) {
-            hotpage_size[i]+=2;
-            hotpage_count[i] = HOTPAGE_STEP;
-            FuseHotPage(i);
-            __sync_synchronize();
-            return;
-        }
-        if(addr+0x2000==hotpage[i]) {
-            hotpage_size[i]+=2;
-            hotpage[i] = addr;
-            hotpage_count[i] = HOTPAGE_STEP;
-            FuseHotPage(i);
-            __sync_synchronize();
-            return;
-        }
-    }
-    // look for empty spot / minium
-    int mincnt = hotpage_count[0]*(hotpage_size[0]+1);
-    int minidx = 0;
-    for(int i=1; i<MAX_HOTPAGE; ++i)
-        if((hotpage_count[i]*(hotpage_size[i]+1))<mincnt) {
-            mincnt = (hotpage_count[i]*(hotpage_size[i]+1));
-            minidx = i;
-        }
-    if(hotpage_count[minidx]) {
-        static int cnt = 0;
-        if(cnt<50) {
-            dynarec_log(LOG_NONE, "Warning, not enough Hotpage, replacing %p(%p/%d) with %p\n", (void*)hotpage[minidx], (void*)(0x1000*(hotpage_size[minidx]+1)), hotpage_count[minidx], (void*)addr);
-            ++cnt;
-            if(cnt==50)   // stop spamming console with message...
-                dynarec_log(LOG_NONE, "    will stop warning about not enough Hotpage now\n");
-        }
-        hotpage_size[minidx] = 0;
-    } else
-        ++hotpages;
-    hotpage[minidx] = addr;
-    hotpage_count[minidx] = HOTPAGE_STEP;
-    __sync_synchronize();
-}
-
-dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
+dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create)
 {
-    dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
-    dynablock_t *father = (db && db->father)?db->father:db;
-    if(father && father->done && db->block && father->need_test) {
-        if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
-            dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) with %d son(s) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, db->sons_size, (void*)addr);
+    dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
+    if(db && db->done && db->block && db->need_test) {
+        if(AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
+            dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, (void*)addr);
             return NULL;
         }
-        if(AreaInHotPage((uintptr_t)father->x64_addr, (uintptr_t)father->x64_addr + father->x64_size - 1)) {
-            dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with %d son(s) for %p because it's in a hotpage\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->sons_size, (void*)addr);
-            pthread_mutex_unlock(&my_context->mutex_dyndump);
+        uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
+        if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
+            dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
             return NULL;
         }
-        uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
-        if(hash!=father->hash) {
-            father->done = 0;   // invalidating the block
-            dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, hash, father->hash, father->sons_size, (void*)addr);
-            // no more current if it gets invalidated too
-            if(*current && IntervalIntersects(
-             (uintptr_t)father->x64_addr, 
-             (uintptr_t)father->x64_addr+father->x64_size-1, 
-             (uintptr_t)(*current)->x64_addr, 
-             (uintptr_t)(*current)->x64_addr+(*current)->x64_size-1))
-                *current = NULL;
-            // Free father, it's now invalid!
-            FreeDynablock(father, 0);
+        if(hash!=db->hash) {
+            db->done = 0;   // invalidating the block
+            dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
+            // Free db, it's now invalid!
+            FreeDynablock(db, 0);
             // start again... (will create a new block)
-            db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
+            db = internalDBGetBlock(emu, addr, addr, create, 0);
         } else {
-            father->need_test = 0;
-            dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size-1, father->hash, father->sons_size, (void*)addr);
-            protectDB((uintptr_t)father->x64_addr, father->x64_size);
+            db->need_test = 0;
+            dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
+            protectDB((uintptr_t)db->x64_addr, db->x64_size);
             // fill back jumptable
-            addJumpTableIfDefault64(father->x64_addr, father->block);
-            for(int i=0; i<father->sons_size; ++i)
-                addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
+            setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
         }
         pthread_mutex_unlock(&my_context->mutex_dyndump);
     } 
@@ -572,26 +248,23 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
 {
     dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
     int create = 1;
-    dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
-    dynablock_t *father = (db && db->father)?db->father:db;
-    if(father && father->done && db->block && father->need_test) {
+    dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
+    if(db && db->done && db->block && db->need_test) {
         if(pthread_mutex_trylock(&my_context->mutex_dyndump))
             return NULL;
-        uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size);
-        if(hash!=father->hash) {
-            father->done = 0;   // invalidating the block
-            dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr);
-            // Free father, it's now invalid!
-            FreeDynablock(father, 0);
+        uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
+        if(hash!=db->hash) {
+            db->done = 0;   // invalidating the block
+            dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, hash, db->hash, (void*)addr);
+            // Free db, it's now invalid!
+            FreeDynablock(db, 0);
             // start again... (will create a new block)
-            db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
+            db = internalDBGetBlock(emu, addr, filladdr, create, 0);
         } else {
-            father->need_test = 0;
-            protectDB((uintptr_t)father->x64_addr, father->x64_size);
+            db->need_test = 0;
+            protectDB((uintptr_t)db->x64_addr, db->x64_size);
             // fill back jumptable
-            addJumpTableIfDefault64(father->x64_addr, father->block);
-            for(int i=0; i<father->sons_size; ++i)
-                addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block);
+            addJumpTableIfDefault64(db->x64_addr, db->block);
         }
         pthread_mutex_unlock(&my_context->mutex_dyndump);
     } 
diff --git a/src/dynarec/dynablock_private.h b/src/dynarec/dynablock_private.h
index e73d35ba..dbe8c502 100755
--- a/src/dynarec/dynablock_private.h
+++ b/src/dynarec/dynablock_private.h
@@ -1,16 +1,14 @@
 #ifndef __DYNABLOCK_PRIVATE_H_
 #define __DYNABLOCK_PRIVATE_H_
 
-typedef struct dynablocklist_s  dynablocklist_t;
-
 typedef struct instsize_s {
-    unsigned int x64:4;
-    unsigned int nat:4;
+    unsigned char x64:4;
+    unsigned char nat:4;
 } instsize_t;
 
 typedef struct dynablock_s {
-    dynablocklist_t* parent;
-    void*           block;
+    void*           block;  // block-sizeof(void*) == self
+    void*           actual_block;   // the actual start of the block (so block-sizeof(void*))
     int             size;
     void*           x64_addr;
     uintptr_t       x64_size;
@@ -20,18 +18,8 @@ typedef struct dynablock_s {
     uint8_t         gone;
     uint8_t         dummy;
     int             isize;
-    dynablock_t**   sons;   // sons (kind-of dummy dynablock...)
-    int             sons_size;
-    dynablock_t*    father; // set only in the case of a son
     instsize_t*     instsize;
+    void*           jmpnext;    // a branch jmpnext code when block is marked
 } dynablock_t;
 
-typedef struct dynablocklist_s {
-    uintptr_t           text;
-    int                 textsz;
-    uintptr_t           maxend;    // max address end for anyblock on this blocklist
-    uintptr_t           minstart;  // min start address for block overlapping this blocklist
-    dynablock_t**       direct;    // direct mapping (waste of space, so the array is created at first write)
-} dynablocklist_t;
-
 #endif //__DYNABLOCK_PRIVATE_H_
\ No newline at end of file
diff --git a/src/dynarec/dynarec.c b/src/dynarec/dynarec.c
index 819ef219..920bfaa8 100755
--- a/src/dynarec/dynarec.c
+++ b/src/dynarec/dynarec.c
@@ -20,22 +20,7 @@
 #include "dynablock.h"
 #include "dynablock_private.h"
 #include "bridge.h"
-#endif
-
-#ifdef DYNAREC
-#ifdef ARM64
-void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
-void arm64_epilog() EXPORTDYN;
-#define native_prolog       arm64_prolog
-#define native_epilog       arm64_epilog
-#elif defined(LA464)
-void la464_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
-void la464_epilog() EXPORTDYN;
-#define native_prolog       la464_prolog
-#define native_epilog       la464_epilog
-#else
-#error Unsupported architecture
-#endif
+#include "dynarec_next.h"
 #endif
 
 #ifdef DYNAREC
@@ -49,9 +34,8 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
         printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p/%s)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
     }
     #endif
-    dynablock_t* current = NULL;
     void * jblock;
-    dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
+    dynablock_t* block = DBGetBlock(emu, addr, 1);
     if(!block) {
         // no block, let link table as is...
         if(hasAlternate((void*)addr)) {
@@ -60,7 +44,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
             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, &current);
+            block = DBGetBlock(emu, addr, 1);
         }
         if(!block) {
             #ifdef HAVE_TRACE
@@ -121,23 +105,18 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
         PushExit(emu);
         R_RIP = addr;
         emu->df = d_none;
-        dynablock_t* current = NULL;
-        dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);
-        current = block;
         while(!emu->quit) {
+            dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
             if(!block || !block->block || !block->done) {
                 // 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 Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
                 Run(emu, 1);
-                block = DBGetBlock(emu, R_RIP, 1, &current);
-                current = block;
             } else {
-                dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->father, emu);
+                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);
                 CHECK_FLAGS(emu);
                 // block is here, let's run it!
                 native_prolog(emu, block->block);
-                block = NULL;
             }
             if(emu->fork) {
                 int forktype = emu->fork;
@@ -201,22 +180,17 @@ int DynaRun(x64emu_t* emu)
         return Run(emu, 0);
 #ifdef DYNAREC
     else {
-        dynablock_t* current = NULL;
-        dynablock_t* block = DBGetBlock(emu, R_RIP, 1, &current);;
-        current = block;
         while(!emu->quit) {
+            dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
             if(!block || !block->block || !block->done) {
                 // 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 Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
                 Run(emu, 1);
-                block = DBGetBlock(emu, R_RIP, 1, &current);
-                current = block;
             } else {
-                dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (father=%p) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->father, emu);
+                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);
                 // block is here, let's run it!
                 native_prolog(emu, block->block);
-                block = NULL;
             }
             if(emu->fork) {
                 int forktype = emu->fork;
diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c
index 9da18cf6..890b2397 100755
--- a/src/dynarec/dynarec_native.c
+++ b/src/dynarec/dynarec_native.c
@@ -23,6 +23,7 @@
 
 #include "dynarec_native.h"
 #include "dynarec_arch.h"
+#include "dynarec_next.h"
 
 void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
     uint8_t *ip = (uint8_t*)inst->addr;
@@ -279,7 +280,7 @@ int Table64(dynarec_native_t *dyn, uint64_t val)
     // not found, add it
     if(idx==-1) {
         if(dyn->table64size == dyn->table64cap) {
-            dyn->table64cap+=4;
+            dyn->table64cap+=16;
             dyn->table64 = (uint64_t*)customRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
         }
         idx = dyn->table64size++;
@@ -385,9 +386,12 @@ void CancelBlock64()
         return;
     customFree(helper->next);
     customFree(helper->insts);
+    customFree(helper->instsize);
     customFree(helper->table64);
-    if(helper->dynablock && helper->dynablock->block)
-        FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
+    if(helper->dynablock && helper->dynablock->actual_block)
+        FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->actual_block, helper->dynablock->size);
+    else if(helper->dynablock && helper->block)
+        FreeDynarecMap(helper->dynablock, (uintptr_t)helper->block-sizeof(void*), helper->dynablock->size);
 }
 
 uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr);
@@ -395,15 +399,38 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr);
 uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr);
 uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr);
 
+void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
+    block->isize = 0;
+    block->done = 0;
+    size_t sz = 4*sizeof(void*);
+    void* actual_p = (void*)AllocDynarecMap(block, sz);
+    void* p = actual_p + sizeof(void*);
+    if(actual_p==NULL) {
+        dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
+        CancelBlock64();
+        return NULL;
+    }
+    block->size = sz;
+    block->actual_block = actual_p;
+    block->block = p;
+    block->jmpnext = p;
+    *(dynablock_t**)actual_p = block;
+    *(void**)(p+2*sizeof(void*)) = native_epilog;
+    CreateJmpNext(block->jmpnext, p+2*sizeof(void*));
+    block->need_test = 0;
+    // all done...
+    __clear_cache(actual_p, actual_p+sz);   // need to clear the cache before execution...
+    return block;
+}
+
 void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     if(IsInHotPage(addr)) {
         dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
         return NULL;
     }
     if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
-        dynarec_log(LOG_INFO, "Stopping block in no-dynarec zone\n");
-        block->done = 1;
-        return (void*)block;
+        dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
+        return CreateEmptyBlock(block, addr);
     }
     // protect the 1st page
     protectDB(addr, 1);
@@ -425,7 +452,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     if(!helper.size) {
         dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
         CancelBlock64();
-        return (void*)block;
+        return CreateEmptyBlock(block, addr);;
     }
     if(!isprotectedDB(addr, 1)) {
         dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
@@ -458,44 +485,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
         }
     // fill predecessors with the jump address
     fillPredecessors(&helper);
-    // check for the optionnal barriers now
-    /*for(int i=helper.size-1; i>=0; --i) {
-        if(helper.insts[i].barrier_maybe) {
-            // out-of-block jump
-            if(helper.insts[i].x64.jmp_insts == -1) {
-                // nothing for now
-            } else {
-                // inside block jump
-                int k = helper.insts[i].x64.jmp_insts;
-                if(k>i) {
-                    // jump in the future
-                    if(helper.insts[k].pred_sz>1) {
-                        // with multiple flow, put a barrier
-                        helper.insts[k].x64.barrier|=BARRIER_FLAGS;
-                    }
-                } else {
-                    // jump back
-                    helper.insts[k].x64.barrier|=BARRIER_FLAGS;
-                }
-            }
-    	}
-    }*/
-    // check to remove useless barrier, in case of jump when destination doesn't needs flags
-    /*for(int i=helper.size-1; i>=0; --i) {
-        int k;
-        if(helper.insts[i].x64.jmp
-        && ((k=helper.insts[i].x64.jmp_insts)>=0)
-        && helper.insts[k].x64.barrier&BARRIER_FLAGS) {
-            //TODO: optimize FPU barrier too
-            if((!helper.insts[k].x64.need_flags)
-             ||(helper.insts[k].x64.set_flags==X_ALL
-                  && helper.insts[k].x64.state_flags==SF_SET)
-             ||(helper.insts[k].x64.state_flags==SF_SET_PENDING)) {
-                //if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
-                helper.insts[k].x64.barrier &= ~BARRIER_FLAGS; // remove flag barrier
-             }
-        }
-    }*/
+
     int pos = helper.size;
     while (pos>=0)
         pos = updateNeed(&helper, pos, 0);
@@ -505,10 +495,28 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     
     // pass 2, instruction size
     native_pass2(&helper, addr);
+    // keep size of instructions for signal handling
+    size_t insts_rsize = 0;
+    {
+        size_t insts_size = 0;
+        size_t cap = 1;
+        for(int i=0; i<helper.size; ++i)
+            cap += 1 + ((helper.insts[i].x64.size>helper.insts[i].size)?helper.insts[i].x64.size:helper.insts[i].size)/15;
+        helper.instsize = (instsize_t*)customCalloc(cap, sizeof(instsize_t));
+        for(int i=0; i<helper.size; ++i)
+            helper.instsize = addInst(helper.instsize, &insts_size, &cap, helper.insts[i].x64.size, helper.insts[i].size/4);
+        helper.instsize = addInst(helper.instsize, &insts_size, &cap, 0, 0);    // add a "end of block" mark, just in case
+        insts_rsize = insts_size*sizeof(instsize_t);
+    }
+    insts_rsize = (insts_rsize+7)&~7;   // round the size...
     // ok, now allocate mapped memory, with executable flag on
-    size_t sz = helper.native_size + helper.table64size*sizeof(uint64_t);
-    void* p = (void*)AllocDynarecMap(block, sz);
-    if(p==NULL) {
+    size_t sz = sizeof(void*) + helper.native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize;
+    //           dynablock_t*     block (arm insts)            table64                       jmpnext code       instsize
+    void* actual_p = (void*)AllocDynarecMap(block, sz);
+    void* p = actual_p + sizeof(void*);
+    void* next = p + helper.native_size + helper.table64size*sizeof(uint64_t);
+    void* instsize = next + 4*sizeof(void*);
+    if(actual_p==NULL) {
         dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
         CancelBlock64();
         return NULL;
@@ -516,11 +524,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     helper.block = p;
     helper.native_start = (uintptr_t)p;
     helper.tablestart = helper.native_start + helper.native_size;
-    if(helper.sons_size) {
-        helper.sons_x64 = (uintptr_t*)alloca(helper.sons_size*sizeof(uintptr_t));
-        helper.sons_native = (void**)alloca(helper.sons_size*sizeof(void*));
-    }
-    int pass2_sons_size = helper.sons_size;
+    *(dynablock_t**)actual_p = block;
     // pass 3, emit (log emit native opcode)
     if(box64_dynarec_dump) {
         dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize); 
@@ -550,30 +554,29 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     if(helper.table64size) {
         memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
     }
-    // all done...
-    __clear_cache(p, p+sz);   // need to clear the cache before execution...
     // keep size of instructions for signal handling
-    {
-        size_t cap = 1;
-        for(int i=0; i<helper.size; ++i)
-            cap += 1 + ((helper.insts[i].x64.size>helper.insts[i].size)?helper.insts[i].x64.size:helper.insts[i].size)/15;
-        size_t size = 0;
-        block->instsize = (instsize_t*)customCalloc(cap, sizeof(instsize_t));
-        for(int i=0; i<helper.size; ++i)
-            block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x64.size, helper.insts[i].size/4);
-        block->instsize = addInst(block->instsize, &size, &cap, 0, 0);    // add a "end of block" mark, just in case
-    }
+    memcpy(instsize, helper.instsize, insts_rsize);
+    block->instsize = instsize;
     // ok, free the helper now
     customFree(helper.insts);
     helper.insts = NULL;
     customFree(helper.table64);
     helper.table64 = NULL;
+    customFree(helper.instsize);
+    helper.instsize = NULL;
     block->size = sz;
     block->isize = helper.size;
+    block->actual_block = actual_p;
     block->block = p;
+    block->jmpnext = next+sizeof(void*);
+    *(dynablock_t**)next = block;
+    *(void**)(next+2*sizeof(void*)) = native_next;
+    CreateJmpNext(block->jmpnext, next+2*sizeof(void*));
     block->need_test = 0;
     //block->x64_addr = (void*)start;
     block->x64_size = end-start;
+    // all done...
+    __clear_cache(actual_p, actual_p+sz);   // need to clear the cache before execution...
     block->hash = X31_hash_code(block->x64_addr, block->x64_size);
     // Check if something changed, to abbort if it as
     if((block->hash != hash)) {
@@ -587,36 +590,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
         return NULL;
         //protectDB(addr, end-addr);
     }
-    // fill sons if any
-    dynablock_t** sons = NULL;
-    int sons_size = 0;
-    if(pass2_sons_size != helper.sons_size)
-        dynarec_log(LOG_NONE, "Warning, sons size difference bitween pass2:%d and pass3:%d\n", pass2_sons_size, helper.sons_size);
-    if(helper.sons_size) {
-        sons = (dynablock_t**)customCalloc(helper.sons_size, sizeof(dynablock_t*));
-        for (int i=0; i<helper.sons_size; ++i) {
-            int created = 1;
-            dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x64[i], &created);
-            if(created) {    // avoid breaking a working block!
-                son->block = helper.sons_native[i];
-                son->x64_addr = (void*)helper.sons_x64[i];
-                son->x64_size = end-helper.sons_x64[i];
-                if(!son->x64_size) {printf_log(LOG_NONE, "Warning, son with null x64 size! (@%p / Native=%p)", son->x64_addr, son->block);}
-                son->father = block;
-                son->size = sz + son->block - block->block; // update size count, for debugging
-                //son->done = 1;
-                if(!son->parent)
-                    son->parent = block->parent;
-                sons[sons_size] = son;
-                ++sons_size;
-            }
-        }
-        if(sons_size) {
-            block->sons = sons;
-            block->sons_size = sons_size;
-        } else
-            customFree(sons);
-    }
     current_helper = NULL;
     //block->done = 1;
     return (void*)block;
diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index b3357f8d..7ab25a6f 100755
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -37,7 +37,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
     rex_t rex;
     int rep;    // 0 none, 1=F2 prefix, 2=F3 prefix
     int need_epilog = 1;
-    dyn->sons_size = 0;
     // Clean up (because there are multiple passes)
     dyn->f.pending = 0;
     dyn->f.dfnone = 0;
@@ -248,6 +247,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
         jump_to_epilog(dyn, ip, 0, ninst);  // no linker here, it's an unknow instruction
     }
     FINI;
-    MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
+    MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
     return addr;
 }
diff --git a/src/dynarec/dynarec_next.h b/src/dynarec/dynarec_next.h
new file mode 100644
index 00000000..19d426b8
--- /dev/null
+++ b/src/dynarec/dynarec_next.h
@@ -0,0 +1,22 @@
+#ifndef __DYNAREC_NEXT_H__
+#define __DYNAREC_NEXT_H__
+
+#ifdef ARM64
+void arm64_next(void) EXPORTDYN;
+void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
+void arm64_epilog() EXPORTDYN;
+#define native_next         arm64_next
+#define native_prolog       arm64_prolog
+#define native_epilog       arm64_epilog
+#elif defined(LA464)
+void la464_next(void) EXPORTDYN;
+void la464_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
+void la464_epilog() EXPORTDYN;
+#define native_next         la464_next
+#define native_prolog       la464_prolog
+#define native_epilog       la464_epilog
+#else
+#error Unsupported architecture
+#endif
+
+#endif //__DYNAREC_NEXT_H__
\ No newline at end of file