about summary refs log tree commit diff stats
path: root/src/dynarec
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c30
-rw-r--r--src/dynarec/arm64/dynarec_arm64_64.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c4
-rw-r--r--src/dynarec/arm64/dynarec_arm64_consts.c7
-rw-r--r--src/dynarec/arm64/dynarec_arm64_consts.h1
-rw-r--r--src/dynarec/arm64/dynarec_arm64_f20f.c4
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c23
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h57
-rw-r--r--src/dynarec/arm64/dynarec_arm64_pass2.h18
-rw-r--r--src/dynarec/arm64/dynarec_arm64_pass3.h16
-rw-r--r--src/dynarec/dynablock.c17
-rw-r--r--src/dynarec/dynablock_private.h4
-rw-r--r--src/dynarec/dynacache_reloc.c84
-rw-r--r--src/dynarec/dynacache_reloc.h4
-rw-r--r--src/dynarec/dynarec_native.c67
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c8
17 files changed, 251 insertions, 97 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 75d963af..219fa44c 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -3365,7 +3365,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 #endif
             }
             #if STEP < 2
-            if (!rex.is32bits && IsNativeCall(addr + i32, rex.is32bits, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
+            if (!rex.is32bits  && !dyn->need_reloc && IsNativeCall(addr + i32, rex.is32bits, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
                 tmp = dyn->insts[ninst].pass2choice = 3;
             else
                 tmp = dyn->insts[ninst].pass2choice = i32?0:1;
@@ -3377,8 +3377,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     SETFLAGS(X_ALL, SF_SET_NODF);    // Hack to set flags to "dont'care" state
                     if(dyn->last_ip && (addr-dyn->last_ip<0x1000)) {
                         ADDx_U12(x2, xRIP, addr-dyn->last_ip);
+                    } else if(dyn->last_ip && (dyn->last_ip-addr<0x1000)) {
+                        SUBx_U12(x2, xRIP, dyn->last_ip-addr);
                     } else {
-                        MOV64x(x2, addr);
+                        if(dyn->need_reloc) {
+                            TABLE64(x2, addr);
+                        } else {
+                            MOV64x(x2, addr);
+                        }
                     }
                     PUSH1(x2);
                     MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetBridgeName((void*)(dyn->insts[ninst].natcall - 1)) ?: GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall - 1)), dyn->insts[ninst].retn);
@@ -3406,6 +3412,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         CALL_S(const_int3, -1);
                         SMWRITE2();
                         LOAD_XEMU_CALL(xRIP);
+                        // in case of dyn->need_reloc, the previous GETIP_ will end up in a TABLE64 that will generate a RELOC_CANCELBLOCK as natcall will be out of the mmap space anyway
                         MOV64x(x3, dyn->insts[ninst].natcall);
                         ADDx_U12(x3, x3, 2+8+8);
                         CMPSx_REG(xRIP, x3);
@@ -3424,7 +3431,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 1:
                     // this is call to next step, so just push the return address to the stack
-                    MOV64x(x2, addr);
+                    if(dyn->need_reloc) {
+                        TABLE64(x2, addr);
+                    } else {
+                        MOV64x(x2, addr);
+                    }
                     PUSH1z(x2);
                     break;
                 default:
@@ -3434,7 +3445,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         SETFLAGS(X_ALL, SF_SET_NODF);    // Hack to set flags to "dont'care" state
                     }
                     // regular call
-                    MOV64x(x2, addr);
+                    if(dyn->need_reloc) {
+                        TABLE64(x2, addr);
+                    } else {
+                        MOV64x(x2, addr);
+                    }
                     fpu_purgecache(dyn, ninst, 1, x1, x3, x4);
                     PUSH1z(x2);
                     if (BOX64DRENV(dynarec_callret)) {
@@ -3471,7 +3486,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         // jumps out of current dynablock...
                         MARK;
                         j64 = getJumpTableAddress64(addr);
-                        MOV64x(x4, j64);
+                        if(dyn->need_reloc) {
+                            AddRelocTable64JmpTbl(dyn, ninst, addr, STEP);
+                            TABLE64_(x4, j64);
+                        } else {
+                            MOV64x(x4, j64);
+                        }
                         LDRx_U12(x4, x4, 0);
                         BR(x4);
                     }
diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c
index de10a343..63f0b6af 100644
--- a/src/dynarec/arm64/dynarec_arm64_64.c
+++ b/src/dynarec/arm64/dynarec_arm64_64.c
@@ -1648,7 +1648,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         MARK;
                         j64 = getJumpTableAddress64(addr);
                         if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
-                        TABLE64(x4, j64);
+                        TABLE64_(x4, j64);
                         LDRx_U12(x4, x4, 0);
                         BR(x4);
                     }
diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c
index f44cb687..e6755147 100644
--- a/src/dynarec/arm64/dynarec_arm64_67.c
+++ b/src/dynarec/arm64/dynarec_arm64_67.c
@@ -1749,7 +1749,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         MARK;

                         j64 = getJumpTableAddress64(addr);

                         if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);

-                        TABLE64(x4, j64);

+                        TABLE64_(x4, j64);

                         LDRx_U12(x4, x4, 0);

                         BR(x4);

                     }

diff --git a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
index d1953a79..ab644ee8 100644
--- a/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c
@@ -509,9 +509,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
             INST_NAME("VADDSUBPS Gx, Vx, Ex");
             nextop = F8;
             q0 = fpu_get_scratch(dyn, ninst);
-            static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
-            MAYUSE(addsubps);
-            MOV64x(x2, (uintptr_t)&addsubps);
+            TABLE64C(x2, const_4f_m1_1_m1_1);
             VLDR128_U12(q0, x2, 0);
             for(int l=0; l<1+vex.l; ++l) {
                 if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
diff --git a/src/dynarec/arm64/dynarec_arm64_consts.c b/src/dynarec/arm64/dynarec_arm64_consts.c
index ce59c954..d30c0bd2 100644
--- a/src/dynarec/arm64/dynarec_arm64_consts.c
+++ b/src/dynarec/arm64/dynarec_arm64_consts.c
@@ -21,6 +21,7 @@
 #include "emu/x87emu_private.h"
 #include "emu/x64compstrings.h"
 #include "x64test.h"
+#include "dynarec/dynarec_next.h"
 
 static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
 static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
@@ -30,9 +31,6 @@ static const double addsubpd[2] = {-1., 1.};
 static const float subaddps[4] = {1.f, -1.f, 1.f, -1.f};
 static const double subaddpd[2] = {1., -1.};
 
-void arm64_epilog(void);
-void* arm64_next(x64emu_t* emu, uintptr_t addr);
-
 #ifndef HAVE_TRACE
 void PrintTrace() {}
 #endif
@@ -84,6 +82,7 @@ uintptr_t getConst(arm64_consts_t which)
         case const_native_fld: return (uintptr_t)native_fld;
         case const_native_fstp: return (uintptr_t)native_fstp;
         case const_native_frstor: return (uintptr_t)native_frstor;
+        case const_native_next: return (uintptr_t)native_next;
         case const_int3: return (uintptr_t)EmuInt3;
         case const_x86syscall: return (uintptr_t)EmuX86Syscall;
         case const_x64syscall: return (uintptr_t)EmuX64Syscall;
@@ -122,7 +121,7 @@ uintptr_t getConst(arm64_consts_t which)
         case const_sse42_compare_string_implicit_len: return (uintptr_t)sse42_compare_string_implicit_len;
         case const_x64test_step: return (uintptr_t)x64test_step;
         case const_printtrace: return (uintptr_t)PrintTrace;
-        case const_epilog: return (uintptr_t)arm64_epilog;
+        case const_epilog: return (uintptr_t)native_epilog;
         case const_jmptbl32: return getJumpTable32();
         case const_jmptbl48: return getJumpTable48();
         case const_jmptbl64: return getJumpTable64();
diff --git a/src/dynarec/arm64/dynarec_arm64_consts.h b/src/dynarec/arm64/dynarec_arm64_consts.h
index 71e2bdce..9ba65aca 100644
--- a/src/dynarec/arm64/dynarec_arm64_consts.h
+++ b/src/dynarec/arm64/dynarec_arm64_consts.h
@@ -46,6 +46,7 @@ typedef enum arm64_consts_s {
     const_native_fld,
     const_native_fstp,
     const_native_frstor,
+    const_native_next,
     const_int3,
     const_x86syscall,
     const_x64syscall,
diff --git a/src/dynarec/arm64/dynarec_arm64_f20f.c b/src/dynarec/arm64/dynarec_arm64_f20f.c
index 6e13def9..e6289479 100644
--- a/src/dynarec/arm64/dynarec_arm64_f20f.c
+++ b/src/dynarec/arm64/dynarec_arm64_f20f.c
@@ -523,9 +523,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             GETGX(v0, 1);

             GETEX(v1, 0, 0);

             q0 = fpu_get_scratch(dyn, ninst);

-            static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};

-            MAYUSE(addsubps);

-            MOV64x(x2, (uintptr_t)&addsubps);   // no need to use table64, as box64 is loaded in low memory

+            TABLE64C(x2, const_4f_m1_1_m1_1);

             VLDR128_U12(q0, x2, 0);

             VFMLAQS(v0, v1, q0);

             break;

diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index d4817803..e6ee1b70 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -101,7 +101,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
             } else if(tmp<0 && tmp>-0x1000) {
                 GETIP(addr+delta);
                 SUBx_U12(ret, xRIP, -tmp);
-            } else if(tmp+addr+delta<0x1000000000000LL) {  // 3 opcodes to load immediate is cheap enough
+            } else if((tmp+addr+delta<0x1000000000000LL) && !dyn->need_reloc) {  // 3 opcodes to load immediate is cheap enough
                 MOV64x(ret, tmp+addr+delta);
             } else {
                 MOV64x(ret, tmp);
@@ -575,7 +575,11 @@ static int indirect_lookup(dynarec_arm_t* dyn, int ninst, int is32bits, int s1,
         LSRx_IMM(s1, xRIP, 48);
         CBNZw(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block);
         // load table
-        MOV64x(s2, getConst(const_jmptbl48));    // this is a static value, so will be a low address
+        if(dyn->need_reloc) {
+            TABLE64C(s2, const_jmptbl48);
+        } else {
+            MOV64x(s2, getConst(const_jmptbl48));    // this is a static value, so will be a low address
+        }
         #ifdef JMPTABL_SHIFT4
         UBFXx(s1, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
         LDRx_REG_LSL3(s2, s2, s1);
@@ -751,7 +755,11 @@ void iret_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int ninst, int is32bits, i
     MOVx_REG(xRSP, x3);
     MARKSEG;
     // Ret....
-    MOV64x(x2, getConst(const_epilog));  // epilog on purpose, CS might have changed!
+    // epilog on purpose, CS might have changed!
+    if(dyn->need_reloc)
+        TABLE64C(x2, const_epilog);
+    else
+        MOV64x(x2, getConst(const_epilog));
     BR(x2);
     CLEARIP();
 }
@@ -880,8 +888,13 @@ void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
     MOVx_REG(x4, xR8);
     MOVx_REG(x5, xR9);
     // native call
-    // fnc is indirect, to help with relocation (but PltResolver might be an issue here)
-    TABLE64(16, *(uintptr_t*)fnc);    // using x16 as scratch regs for call address
+    if(dyn->need_reloc) {
+        // fnc is indirect, to help with relocation (but PltResolver might be an issue here)
+        TABLE64(16, (uintptr_t)fnc);
+        LDRx_U12(16, 16, 0);
+    } else {
+        TABLE64_(16, *(uintptr_t*)fnc);    // using x16 as scratch regs for call address
+    }
     BLR(16);
     // put return value in x64 regs
     if(w>0) {
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 8806777c..63418126 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1229,31 +1229,40 @@
 #define GETIP_(A) MOV64x(xRIP, A)
 #else
 // put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later...
-#define GETIP(A)                                        \
-    if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) {     \
-        uint64_t _delta_ip = (A)-dyn->last_ip;          \
-        dyn->last_ip += _delta_ip;                      \
-        if(_delta_ip) {                                 \
-            ADDx_U12(xRIP, xRIP, _delta_ip);            \
-        }                                               \
-    } else {                                            \
-        dyn->last_ip = (A);                             \
-        if(dyn->need_reloc) {                           \
-            TABLE64(xRIP, dyn->last_ip);                \
-        } else {                                        \
-            MOV64x(xRIP, dyn->last_ip);                 \
-        }                                               \
+#define GETIP(A)                                            \
+    if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) {         \
+        uint64_t _delta_ip = (A)-dyn->last_ip;              \
+        dyn->last_ip += _delta_ip;                          \
+        if(_delta_ip) {                                     \
+            ADDx_U12(xRIP, xRIP, _delta_ip);                \
+        }                                                   \
+    } else if(dyn->last_ip && (dyn->last_ip-(A))<0x1000) {  \
+        uint64_t _delta_ip = dyn->last_ip-(A);              \
+        dyn->last_ip -= _delta_ip;                          \
+        if(_delta_ip) {                                     \
+            SUBx_U12(xRIP, xRIP, _delta_ip);                \
+        }                                                   \
+    } else {                                                \
+        dyn->last_ip = (A);                                 \
+        if(dyn->need_reloc) {                               \
+            TABLE64(xRIP, dyn->last_ip);                    \
+        } else {                                            \
+            MOV64x(xRIP, dyn->last_ip);                     \
+        }                                                   \
     }
-#define GETIP_(A)                                       \
-    if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) {     \
-        uint64_t _delta_ip = (A)-dyn->last_ip;          \
-        if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}\
-    } else {                                            \
-        if(dyn->need_reloc) {                           \
-            TABLE64(xRIP, (A));                         \
-        } else {                                        \
-            MOV64x(xRIP, (A));                          \
-        }                                               \
+#define GETIP_(A)                                           \
+    if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) {         \
+        uint64_t _delta_ip = (A)-dyn->last_ip;              \
+        if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}    \
+    } else if(dyn->last_ip && (dyn->last_ip-(A))<0x1000) {  \
+        uint64_t _delta_ip = dyn->last_ip-(A);              \
+        if(_delta_ip) {SUBx_U12(xRIP, xRIP, _delta_ip);}    \
+    } else {                                                \
+        if(dyn->need_reloc) {                               \
+            TABLE64(xRIP, (A));                             \
+        } else {                                            \
+            MOV64x(xRIP, (A));                              \
+        }                                                   \
     }
 #endif
 #define CLEARIP()   dyn->last_ip=0
diff --git a/src/dynarec/arm64/dynarec_arm64_pass2.h b/src/dynarec/arm64/dynarec_arm64_pass2.h
index 6bedf76a..90abb349 100644
--- a/src/dynarec/arm64/dynarec_arm64_pass2.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass2.h
@@ -15,19 +15,19 @@
         }
 #define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size; 
 #define INST_NAME(name) 
-#define TABLE64(A, V)   {                                                       \
-                if(dyn->need_reloc && !isTable64(dyn, (V)))                     \
+#define TABLE64(A, V)   do {                                                    \
+                if(dyn->need_reloc)                                             \
                         AddRelocTable64Addr(dyn, ninst, (V), 2);                \
                 Table64(dyn, (V), 2); EMIT(0);                                  \
-        }
-#define TABLE64_(A, V)   {                                                      \
+        } while(0)
+#define TABLE64_(A, V)  do {                                                    \
                 Table64(dyn, (V), 2); EMIT(0);                                  \
-        }
-#define TABLE64C(A, V)  {                                                       \
-                if(dyn->need_reloc && !isTable64(dyn, getConst(V)))             \
+        } while(0)
+#define TABLE64C(A, V)  do {                                                    \
+                if(dyn->need_reloc)                                             \
                         AddRelocTable64Const(dyn, ninst, (V), 2);               \
                 Table64(dyn, getConst(V), 2); EMIT(0);                          \
-        }
-#define FTABLE64(A, V)  {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);}
+        } while(0)
+#define FTABLE64(A, V)  do {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);} while(0)
 #define CALLRET_RET()   do {dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
 #define CALLRET_LOOP()   do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
\ No newline at end of file
diff --git a/src/dynarec/arm64/dynarec_arm64_pass3.h b/src/dynarec/arm64/dynarec_arm64_pass3.h
index 5930c410..c59d2aee 100644
--- a/src/dynarec/arm64/dynarec_arm64_pass3.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass3.h
@@ -24,22 +24,22 @@
     }
 #define INST_EPILOG
 #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex)
-#define TABLE64(A, V)   {                                                                   \
-                if(dyn->need_reloc && !isTable64(dyn, (V)))                                 \
+#define TABLE64(A, V)  do {                                                                 \
+                if(dyn->need_reloc)                                                         \
                         AddRelocTable64Addr(dyn, ninst, (V), 3);                            \
                 int val64offset = Table64(dyn, (V), 3);                                     \
                 MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset); \
-            }
+            } while(0)
 #define TABLE64_(A, V)   {                                                                  \
                 int val64offset = Table64(dyn, (V), 3);                                     \
                 MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset); \
             }
-#define TABLE64C(A, V)  {                                                                   \
-                if(dyn->need_reloc && !isTable64(dyn, getConst(V)))                         \
+#define TABLE64C(A, V) do {                                                                 \
+                if(dyn->need_reloc)                                                         \
                         AddRelocTable64Const(dyn, ninst, (V), 3);                           \
                 int val64offset = Table64(dyn, getConst(V), 3);                             \
-                MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset); \
-            }
-#define FTABLE64(A, V)  {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q, 3); MESSAGE(LOG_DUMP, "  FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);}
+                MESSAGE(LOG_DUMP, "  Table64C: 0x%lx\n", (V)); LDRx_literal(A, val64offset);\
+            } while(0)
+#define FTABLE64(A, V)  do {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q, 3); MESSAGE(LOG_DUMP, "  FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);} while(0)
 #define CALLRET_RET()   do {dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
 #define CALLRET_LOOP()   do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c
index b5a81020..b804eff2 100644
--- a/src/dynarec/dynablock.c
+++ b/src/dynarec/dynablock.c
@@ -85,14 +85,15 @@ void FreeInvalidDynablock(dynablock_t* db, int need_lock)
     }
 }
 
-void FreeDynablock(dynablock_t* db, int need_lock)
+void FreeDynablock(dynablock_t* db, int need_lock, int need_remove)
 {
     if(db) {
         if(db->gone)
             return; // already in the process of deletion!
         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);
         // remove jumptable without waiting
-        setJumpTableDefault64(db->x64_addr);
+        if(need_remove)
+            setJumpTableDefault64(db->x64_addr);
         if(need_lock)
             mutex_lock(&my_context->mutex_dyndump);
         dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
@@ -168,7 +169,7 @@ int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
 
     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);
+        FreeDynablock(db, need_lock, 1);
         return 0;
     }
     return 1;
@@ -233,7 +234,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
     if(block) {
         // fill-in jumptable
         if(!addJumpTableIfDefault64(block->x64_addr, block->dirty?block->jmpnext:block->block)) {
-            FreeDynablock(block, 0);
+            FreeDynablock(block, 0, 0);
             block = getDB(addr);
             MarkDynablock(block);   // just in case...
         } else {
@@ -261,9 +262,9 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
     if(is_inhotpage && !BOX64ENV(dynarec_dirty))
         return NULL;
     dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1, is32bits, 1);
-    if(db && db->done && db->block && getNeedTest(addr)) {
+    if(db && db->done && db->block && (db->dirty || getNeedTest(addr))) {
         if (db->always_test) SchedYield(); // just calm down...
-        uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
+        uint32_t hash = db->dirty?(~db->hash):X31_hash_code(db->x64_addr, db->x64_size);
         if(is_inhotpage && hash!=db->hash)
             return NULL;    // will be handle when hotpage is over
         int need_lock = mutex_trylock(&my_context->mutex_dyndump);
@@ -313,10 +314,10 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr,
     dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p%s\n", (void*)addr, (void*)filladdr, is32bits?" 32bits":"");
     int create = 1;
     dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1, is32bits, 1);
-    if(db && db->done && db->block && getNeedTest(filladdr)) {
+    if(db && db->done && db->block && (db->dirty || getNeedTest(filladdr))) {
         if (db->always_test) SchedYield(); // just calm down...
         int need_lock = mutex_trylock(&my_context->mutex_dyndump);
-        uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
+        uint32_t hash = db->dirty?(~db->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);
diff --git a/src/dynarec/dynablock_private.h b/src/dynarec/dynablock_private.h
index f78d457c..db142c25 100644
--- a/src/dynarec/dynablock_private.h
+++ b/src/dynarec/dynablock_private.h
@@ -17,6 +17,7 @@ typedef struct dynablock_s {
     struct dynablock_s*    previous;   // a previous block that might need to be freed
     void*           x64_addr;
     uintptr_t       x64_size;
+    size_t          native_size;
     int             size;
     uint32_t        hash;
     uint8_t         done;
@@ -31,6 +32,9 @@ typedef struct dynablock_s {
     void*           arch;       // arch dependant per inst info (can be NULL)
     callret_t*      callrets;   // array of callret return, with NOP / UDF depending if the block is clean or dirty
     void*           jmpnext;    // a branch jmpnext code when block is marked
+    size_t          table64size;// to check table64
+    void*           table64;    // to relocate the table64
+    size_t          relocsize;  // number of relocations (should be an int only)
     void*           relocs;     // relocations, when block is loaded
     #ifdef GDBJIT
     void*           gdbjit_block;
diff --git a/src/dynarec/dynacache_reloc.c b/src/dynarec/dynacache_reloc.c
index 7692e007..b145629e 100644
--- a/src/dynarec/dynacache_reloc.c
+++ b/src/dynarec/dynacache_reloc.c
@@ -4,6 +4,7 @@
 #include "os.h"
 #include "dynarec_private.h"
 #include "emu/x64run_private.h"
+#include "dynablock_private.h"
 #include "dynarec_arch.h"
 #include "custommem.h"
 #include "debug.h"
@@ -13,7 +14,7 @@
 #define RELOC_TBL64RETENDBL 3
 #define RELOC_CANCELBLOCK   4
 #define RELOC_TBL64TBLJMPH  5
-#define RELOC_TBL64TBLJMPL  5
+#define RELOC_TBL64TBLJMPL  6
 
 typedef union reloc_s {
     uint8_t type;
@@ -48,6 +49,8 @@ void AddRelocTable64Const(dynarec_native_t* dyn, int ninst, native_consts_t C, i
 {
     if(!dyn->need_reloc)
         return;
+    if(isTable64(dyn, getConst(C)))
+        return;
     if(pass<3)  {
         dyn->reloc_size++;
         return;
@@ -117,12 +120,13 @@ void AddRelocTable64Addr(dynarec_native_t* dyn, int ninst, uintptr_t addr, int p
     }
     if(!ok) return AddRelocCancelBlock(dyn, ninst, pass);
     if(pass<3) {
-        dyn->reloc_size+=2;
+        dyn->reloc_size++;
         return;
     }
     reloc_t reloc = {0};
     reloc.type = RELOC_TBL64ADDR;
     reloc.table64addr.idx = dyn->table64size;
+    dyn->relocs[dyn->reloc_size++] = reloc.x;
 }
 
 
@@ -159,4 +163,80 @@ void AddRelocTable64JmpTbl(dynarec_native_t* dyn, int ninst, uintptr_t addr, int
     reloc.type = RELOC_TBL64TBLJMPL;
     reloc.table64jmptbll.deltal = delta&0xffffff;
     dyn->relocs[dyn->reloc_size++] = reloc.x;
+}
+
+int ApplyRelocs(dynablock_t* block, intptr_t delta_block, intptr_t delta_map, uintptr_t mapping_start)
+{
+    if(!block || !block->relocs || !block->relocsize)
+        return 0;
+    size_t reloc_size = block->relocsize / sizeof(uint32_t);
+    reloc_t *relocs = block->relocs;
+    uint64_t *table64 = block->table64;
+    int idx;
+
+    int i = 0;
+    uintptr_t addr;
+    dynarec_log(LOG_DEBUG, "Will apply %zd reloc to dynablock starting at %p - %p\n", reloc_size, block->x64_addr, block->x64_addr + block->x64_size);
+    while(i<reloc_size) {
+        idx = -1;
+        switch(relocs[i].type) {
+            case RELOC_TBL64C:
+                idx = relocs[i].table64c.idx;
+                table64[idx] = getConst(relocs[i].table64c.C);
+                dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: TABLE64[%d]=Const:%d\n", i, idx, relocs[i].table64c.C);
+                break;
+            case RELOC_TBL64ADDR:
+                idx = relocs[i].table64addr.idx;
+                table64[idx] += delta_map;
+                dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: TABLE64[%d]=Addr in Map, delta=%zd\n", i, idx, delta_map);
+                break;
+            case RELOC_TBL64RETENDBL:
+                idx = relocs[i].table64retendbl.idx;
+                addr = (uintptr_t)block->x64_addr + block->x64_size + relocs[i].table64retendbl.delta;
+                table64[idx] = getJumpTableAddress64(addr);
+                dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: TABLE64[%d]=JmpTable64(%p)\n", i, idx, (void*)addr);
+                break;
+            case RELOC_CANCELBLOCK:
+                dynarec_log(LOG_DEBUG, "\tApply Relocs[%d]: Cancel Block\n", i);
+                block->dirty = 1;
+                block->hash = 0;
+                return 0;
+            case RELOC_TBL64TBLJMPH:
+                if(relocs[i+1].type!=RELOC_TBL64TBLJMPL)
+                    return -2;  // bad sequence
+                idx = relocs[i].table64jmptblh.idx;
+                addr = relocs[i].table64jmptblh.deltah;
+                addr = mapping_start + relocs[i+1].table64jmptbll.deltal + (addr<<24);
+                table64[idx] = getJumpTableAddress64(addr);
+                dynarec_log(LOG_DEBUG, "\tApply Relocs[%d,%d]: TABLE64[%d]=JmpTable64(%p)=%p\n", i, i+1, idx, (void*)addr, getJumpTableAddress64(addr));
+                break;
+            case RELOC_TBL64TBLJMPL:
+                break;
+            default: 
+                dynarec_log(LOG_DEBUG, "\tUnknown Relocs[%d]: %d\n", i, relocs[i].type);
+                return -1;
+        }
+        if(idx!=-1) {
+            if(idx>=block->table64size) {
+                dynarec_log(LOG_NONE, "Warning: Reloc Table64 idx out of range (%d vs %d)\n", idx, block->table64size);
+            }
+        }
+        ++i;
+    }
+    return 0;
+}
+
+int RelocsHaveCancel(dynablock_t* block)
+{
+    if(!block->relocs || !block->relocsize)
+        return 0;
+    size_t reloc_size = block->relocsize/sizeof(uint32_t);
+    for(size_t i=0; i<reloc_size; ++i)
+        if(((reloc_t*)block->relocs)[i].type == RELOC_CANCELBLOCK)
+            return 1;
+    return 0;
+}
+
+uintptr_t RelocGetNext() {
+    return getConst(const_native_next);
 }
\ No newline at end of file
diff --git a/src/dynarec/dynacache_reloc.h b/src/dynarec/dynacache_reloc.h
index fed00562..dc0f63a4 100644
--- a/src/dynarec/dynacache_reloc.h
+++ b/src/dynarec/dynacache_reloc.h
@@ -17,4 +17,8 @@ void AddRelocTable64RetEndBlock(dynarec_native_t* dyn, int ninst, uintptr_t addr
 void AddRelocTable64JmpTbl(dynarec_native_t* dyn, int ninst, uintptr_t addr, int pass);
 void AddRelocCancelBlock(dynarec_native_t* dyn, int ninst, int pass);
 
+int ApplyRelocs(dynablock_t* block, intptr_t delta_block, intptr_t delta_map, uintptr_t mapping_start);
+int RelocsHaveCancel(dynablock_t* block);
+uintptr_t RelocGetNext();
+
 #endif
\ No newline at end of file
diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c
index bba18978..8e142b57 100644
--- a/src/dynarec/dynarec_native.c
+++ b/src/dynarec/dynarec_native.c
@@ -23,6 +23,9 @@
 #include "dynarec_arch.h"
 #include "dynarec_next.h"
 #include "gdbjit.h"
+#include "khash.h"
+
+KHASH_MAP_INIT_INT64(table64, uint32_t)
 
 void printf_x64_instruction(dynarec_native_t* dyn, zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
     uint8_t *ip = (uint8_t*)inst->addr;
@@ -293,36 +296,51 @@ void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size)
     }
 }
 
+static kh_table64_t* khtable64 = NULL;
+
 int isTable64(dynarec_native_t *dyn, uint64_t val)
 {
-    // find the value if already present
-    int idx = -1;
-    for(int i=0; i<dyn->table64size && (idx==-1); ++i)
-        if(dyn->table64[i] == val)
-            idx = i;
-    return (idx!=-1);
+    if(!khtable64)
+        return 0;
+    if(kh_get(table64, khtable64, val)==kh_end(khtable64))
+        return 0;
+    return 1;
 }
 // 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 pass)
 {
+    if(!khtable64)
+        khtable64 = kh_init(table64);
     // find the value if already present
-    int idx = -1;
-    for(int i=0; i<dyn->table64size && (idx==-1); ++i)
-        if(dyn->table64[i] == val)
-            idx = i;
-    // not found, add it
-    if(idx==-1) {
+    khint_t k = kh_get(table64, khtable64, val);
+    uint32_t idx = 0;
+    if(k!=kh_end(khtable64)) {
+        idx = kh_value(khtable64, k);
+    } else {
         idx = dyn->table64size++;
-        if(idx < dyn->table64cap)
-            dyn->table64[idx] = val;
-        else if(pass==3)
-            printf_log(LOG_NONE, "Warning, table64 bigger than expected %d vs %d\n", idx, dyn->table64cap);
+        if(pass==3) {
+            if(idx < dyn->table64cap)
+                dyn->table64[idx] = val;
+            else
+                printf_log(LOG_NONE, "Warning, table64 bigger than expected %d vs %d\n", idx, dyn->table64cap);
+        }
+        int ret;
+        k = kh_put(table64, khtable64, val, &ret);
+        kh_value(khtable64, k) = idx;
     }
     // calculate offset
     int delta = dyn->tablestart + idx*sizeof(uint64_t) - (uintptr_t)dyn->block;
     return delta;
 }
 
+void ResetTable64(dynarec_native_t* dyn)
+{
+    dyn->table64size = 0;
+    if(khtable64) {
+        kh_clear(table64, khtable64);
+    }
+}
+
 static void recurse_mark_alive(dynarec_native_t* dyn, int i)
 {
     if(dyn->insts[i].x64.alive)
@@ -510,7 +528,6 @@ static void updateYmm0s(dynarec_native_t* dyn, int ninst, int max_ninst_reached)
 void* current_helper = NULL;
 static int static_jmps[MAX_INSTS+2];
 static uintptr_t static_next[MAX_INSTS+2];
-static uint64_t static_table64[(MAX_INSTS+3)/4];
 static instruction_native_t static_insts[MAX_INSTS+2] = {0};
 static callret_t static_callrets[MAX_INSTS+2] = {0};
 // TODO: ninst could be a uint16_t instead of an int, that could same some temp. memory
@@ -640,8 +657,9 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     helper.jmp_cap = MAX_INSTS;
     helper.next = static_next;
     helper.next_cap = MAX_INSTS;
-    helper.table64 = static_table64;
-    helper.table64cap = sizeof(static_table64)/sizeof(uint64_t);
+    helper.table64 = NULL;
+    ResetTable64(&helper);
+    helper.table64cap = 0;
     helper.end = addr + SizeFileMapped(addr);
     if(helper.end == helper.start)  // that means there is no mmap with a file associated to the memory
         helper.end = (uintptr_t)~0LL;
@@ -780,7 +798,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     // no need for next anymore
     helper.next_sz = helper.next_cap = 0;
     helper.next = NULL;
-    helper.table64size = 0;
+    ResetTable64(&helper);
     helper.reloc_size = 0;
     // pass 1, float optimizations, first pass for flags
     native_pass1(&helper, addr, alternate, is32bits, inst_max);
@@ -794,7 +812,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
             helper.need_x87check = 0;
     }
     POSTUPDATE_SPECIFICS(&helper);
-    helper.table64size = 0;
+    ResetTable64(&helper);
     helper.reloc_size = 0;
     // pass 2, instruction size
     helper.callrets = static_callrets;
@@ -850,6 +868,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     block->actual_block = actual_p;
     helper.relocs = relocs;
     block->relocs = relocs;
+    block->table64size = helper.table64size;
     helper.native_start = (uintptr_t)p;
     helper.tablestart = (uintptr_t)tablestart;
     helper.jmp_next = (uintptr_t)next+sizeof(void*);
@@ -858,6 +877,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     helper.table64cap = helper.table64size;
     helper.table64 = (uint64_t*)helper.tablestart;
     helper.callrets = (callret_t*)callrets;
+    block->table64 = helper.table64;
     if(callret_size)
         memcpy(helper.callrets, static_callrets, helper.callret_size*sizeof(callret_t));
     helper.callret_size = 0;
@@ -875,7 +895,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     size_t oldinstsize = helper.insts_size;
     int oldsize= helper.size;
     helper.native_size = 0;
-    helper.table64size = 0; // reset table64 (but not the cap)
+    ResetTable64(&helper); // reset table64 (but not the cap)
     helper.insts_size = 0;  // reset
     helper.reloc_size = 0;
     native_pass3(&helper, addr, alternate, is32bits, inst_max);
@@ -899,6 +919,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     block->always_test = helper.always_test;
     block->dirty = block->always_test;
     block->is32bits = is32bits;
+    block->relocsize = helper.reloc_size*sizeof(uint32_t);
     if(arch_size) {
         block->arch_size = arch_size;
         block->arch = ARCH_FILL(&helper, arch, arch_size);
@@ -909,6 +930,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
     }
     block->callret_size = helper.callret_size;
     block->callrets = helper.callrets;
+    block->native_size = native_size;
     *(dynablock_t**)next = block;
     *(void**)(next+3*sizeof(void*)) = native_next;
     CreateJmpNext(block->jmpnext, next+3*sizeof(void*));
@@ -950,6 +972,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int alternate, int is32bits, int inst_m
         return NULL;
     }
     // ok, free the helper now
+    ResetTable64(&helper);
     //dynaFree(helper.insts);
     helper.insts = NULL;
     if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index 20b7a597..43c4f1f5 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -2446,7 +2446,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         // jumps out of current dynablock...
                         MARK;
                         j64 = getJumpTableAddress64(addr);
-                        TABLE64(x4, j64);
+                        if(dyn->need_reloc)
+                            AddRelocTable64JmpTbl(dyn, ninst, addr, STEP);
+                        TABLE64_(x4, j64);
                         LD_D(x4, x4, 0);
                         BR(x4);
                     }
@@ -2842,7 +2844,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         // jumps out of current dynablock...
                         MARK;
                         j64 = getJumpTableAddress64(addr);
-                        TABLE64(x4, j64);
+                        if(dyn->need_reloc)
+                            AddRelocTable64JmpTbl(dyn, ninst, addr, STEP);
+                        TABLE64_(x4, j64);
                         LD_D(x4, x4, 0);
                         BR(x4);
                     }