about summary refs log tree commit diff stats
path: root/src/dynarec/dynarec_native.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-04-16 10:50:12 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-04-16 10:50:12 +0200
commit3adf31c85b8bb4366d063fbe8f7d9fc36084366d (patch)
tree42d8fb12e6079f362c54226a862cabd8b1980ad9 /src/dynarec/dynarec_native.c
parent9b2c6caf22e6dc91ad72f4d90116b80237bd3487 (diff)
downloadbox64-3adf31c85b8bb4366d063fbe8f7d9fc36084366d.tar.gz
box64-3adf31c85b8bb4366d063fbe8f7d9fc36084366d.zip
[DYNAREC] General fixes and improvment for multithread and jit program. Helps Java, mono and Unity3d program... (should help #519, #464, #433, #272, #232, #193, #112...)
Diffstat (limited to 'src/dynarec/dynarec_native.c')
-rwxr-xr-xsrc/dynarec/dynarec_native.c82
1 files changed, 42 insertions, 40 deletions
diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c
index c57b7d64..64d28342 100755
--- a/src/dynarec/dynarec_native.c
+++ b/src/dynarec/dynarec_native.c
@@ -267,7 +267,7 @@ void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size)
 }
 
 // add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
-int Table64(dynarec_native_t *dyn, uint64_t val)
+int Table64(dynarec_native_t *dyn, uint64_t val, int pass)
 {
     // find the value if already present
     int idx = -1;
@@ -278,10 +278,12 @@ int Table64(dynarec_native_t *dyn, uint64_t val)
     if(idx==-1) {
         if(dyn->table64size == dyn->table64cap) {
             dyn->table64cap+=16;
-            dyn->table64 = (uint64_t*)customRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
+            if(pass<3)  // do not resize on pass3, it's not the same type of memory anymore
+                dyn->table64 = (uint64_t*)customRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
         }
         idx = dyn->table64size++;
-        dyn->table64[idx] = val;
+        if(dyn->table64size <= dyn->table64cap)
+            dyn->table64[idx] = val;
     }
     // calculate offset
     int delta = dyn->tablestart + idx*sizeof(uint64_t) - (uintptr_t)dyn->block;
@@ -381,19 +383,17 @@ void CancelBlock64(int need_lock)
         mutex_lock(&my_context->mutex_dyndump);
     dynarec_native_t* helper = (dynarec_native_t*)current_helper;
     current_helper = NULL;
-    if(!helper) {
-        if(need_lock)
-            mutex_unlock(&my_context->mutex_dyndump);
-        return;
+    if(helper) {
+        customFree(helper->next);
+        customFree(helper->insts);
+        customFree(helper->predecessor);
+        if(helper->table64 && (helper->table64!=(uint64_t*)helper->tablestart))
+            customFree(helper->table64);
+        if(helper->dynablock && helper->dynablock->actual_block) {
+            FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
+            helper->dynablock->actual_block = NULL;
+        }
     }
-    customFree(helper->next);
-    customFree(helper->insts);
-    customFree(helper->predecessor);
-    customFree(helper->table64);
-    if(helper->dynablock && helper->dynablock->actual_block)
-        FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
-    else if(helper->dynablock && helper->block)
-        FreeDynarecMap((uintptr_t)helper->block-sizeof(void*));
     if(need_lock)
         mutex_unlock(&my_context->mutex_dyndump);
 }
@@ -421,7 +421,6 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
     *(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;
@@ -491,6 +490,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
         if(helper.insts[i].x64.jmp) {
             uintptr_t j = helper.insts[i].x64.jmp;
             if(j<start || j>=end || j==helper.insts[i].x64.addr) {
+                if(j==helper.insts[i].x64.addr) // if there is a loop on some opcode, make the block "always to tested"
+                    helper.always_test = 1;
                 helper.insts[i].x64.jmp_insts = -1;
                 helper.insts[i].x64.need_after |= X_PEND;
             } else {
@@ -525,7 +526,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     size_t sz = sizeof(void*) + 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(sz);
-    void* p = actual_p + sizeof(void*);
+    void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
     void* next = p + native_size + helper.table64size*sizeof(uint64_t);
     void* instsize = next + 4*sizeof(void*);
     if(actual_p==NULL) {
@@ -534,11 +535,16 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
         return NULL;
     }
     helper.block = p;
+    block->actual_block = actual_p;
     helper.native_start = (uintptr_t)p;
     helper.tablestart = helper.native_start + native_size;
+    helper.jmp_next = (uintptr_t)next+sizeof(void*);
     helper.insts_size = 0;  // reset
     helper.instsize = (instsize_t*)instsize;
     *(dynablock_t**)actual_p = block;
+    helper.table64cap = helper.table64size;
+    customFree(helper.table64);
+    helper.table64 = (uint64_t*)helper.tablestart;
     // 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,43 +556,24 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
     helper.native_size = 0;
     helper.table64size = 0; // reset table64 (but not the cap)
     native_pass3(&helper, addr);
-    if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
-        printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
-        uint8_t *dump = (uint8_t*)helper.start;
-        printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
-        for(int i=0; i<helper.size; ++i) {
-            printf_log(LOG_NONE, "%p:", dump);
-            for(; dump<(uint8_t*)helper.insts[i+1].x64.addr; ++dump)
-                printf_log(LOG_NONE, " %02X", *dump);
-            printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
-        }
-        printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
-        printf_log(LOG_NONE, " ------------\n");
-        //TODO: Cancel block and return empty one
-    }
-    // add table64 if needed
-    if(helper.table64size) {
-        memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
-    }
     // keep size of instructions for signal handling
     block->instsize = instsize;
     // ok, free the helper now
     customFree(helper.insts);
     helper.insts = NULL;
-    customFree(helper.table64);
     helper.table64 = NULL;
     helper.instsize = NULL;
     customFree(helper.predecessor);
     helper.predecessor = NULL;
     block->size = sz;
     block->isize = helper.size;
-    block->actual_block = actual_p;
     block->block = p;
     block->jmpnext = next+sizeof(void*);
+    block->always_test = helper.always_test;
+    block->dirty = block->always_test;
     *(dynablock_t**)next = block;
     *(void**)(next+3*sizeof(void*)) = native_next;
     CreateJmpNext(block->jmpnext, next+3*sizeof(void*));
-    block->need_test = 0;
     //block->x64_addr = (void*)start;
     block->x64_size = end-start;
     // all done...
@@ -599,10 +586,25 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
         CancelBlock64(0);
         return NULL;
     }
+    if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
+        printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
+        uint8_t *dump = (uint8_t*)helper.start;
+        printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
+        for(int i=0; i<helper.size; ++i) {
+            printf_log(LOG_NONE, "%p:", dump);
+            for(; dump<(uint8_t*)helper.insts[i+1].x64.addr; ++dump)
+                printf_log(LOG_NONE, " %02X", *dump);
+            printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
+        }
+        printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
+        printf_log(LOG_NONE, " ------------\n");
+        CancelBlock64(0);
+        return NULL;
+    }
     if(!isprotectedDB(addr, end-addr)) {
-        dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
+        dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x64_addr, block->x64_size);
         AddHotPage(addr);
-        block->need_test = 1;
+        block->dirty = 1;
         //protectDB(addr, end-addr);
     }
     current_helper = NULL;