about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-04-30 22:36:48 +0800
committerGitHub <noreply@github.com>2024-04-30 16:36:48 +0200
commit86e9a38384902d4aca09c7d314932d03989726a5 (patch)
tree2f3b04918c17789f5df9ca19ef25a28d292cfc5d /src
parent322f97ddbca4c3fba969a354d634f97db5f197cc (diff)
downloadbox64-86e9a38384902d4aca09c7d314932d03989726a5.tar.gz
box64-86e9a38384902d4aca09c7d314932d03989726a5.zip
[COSIM] Added thread-safe tests (#1477)
* [COSIM] Added thread-safe tests

* Added more notest

* Run cosim in CI

* Disable tests for RISC-V for now

* Simplify

* Initialize notest
Diffstat (limited to 'src')
-rw-r--r--src/box64context.c5
-rw-r--r--src/core.c6
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_0f.c1
-rw-r--r--src/dynarec/dynarec_native_pass.c6
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c2
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_1.c1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c1
-rw-r--r--src/emu/x64emu_private.h1
-rw-r--r--src/emu/x64run.c53
-rw-r--r--src/emu/x64run0f.c28
-rw-r--r--src/emu/x64run64.c3
-rw-r--r--src/emu/x64run66.c3
-rw-r--r--src/emu/x64run67.c7
-rw-r--r--src/emu/x64test.c25
-rw-r--r--src/include/dynarec.h3
18 files changed, 138 insertions, 11 deletions
diff --git a/src/box64context.c b/src/box64context.c
index 33a0d10b..5d5155fa 100644
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -22,6 +22,7 @@
 #include "rcfile.h"
 #include "gltools.h"
 #include "rbtree.h"
+#include "dynarec.h"
 
 EXPORTDYN
 void initAllHelpers(box64context_t* context)
@@ -212,6 +213,10 @@ box64context_t *NewBox64Context(int argc)
 
     init_custommem_helper(context);
 
+    #ifdef DYNAREC
+    x64test_init();
+    #endif
+
     context->maplib = NewLibrarian(context);
     context->local_maplib = NewLibrarian(context);
     context->versym = NewDictionnary();
diff --git a/src/core.c b/src/core.c
index 9e61cb49..7b8b954c 100644
--- a/src/core.c
+++ b/src/core.c
@@ -781,7 +781,7 @@ void LoadLogEnv()
     p = getenv("BOX64_DYNAREC_TEST");
     if(p) {
         if(strlen(p)==1) {
-            if(p[0]>='0' && p[0]<='1')
+            if(p[0]>='0' && p[0]<='2')
                 box64_dynarec_test = p[0]-'0';
         }
         if(box64_dynarec_test) {
@@ -790,7 +790,9 @@ void LoadLogEnv()
             box64_dynarec_x87double = 1;
             box64_dynarec_div0 = 1;
             box64_dynarec_callret = 0;
-            printf_log(LOG_INFO, "Dynarec will compare it's execution with the interpreter (super slow, only for testing)\n");
+            printf_log(LOG_INFO, "Dynarec will compare it's execution with the interpreter%s (%s slow, only for testing)\n",
+                                 box64_dynarec_test == 2 ? " thread-safely" : "",
+                                 box64_dynarec_test == 2 ? "extremely" : "super");
         }
     }
 
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 82b832a8..7f0aff2f 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -996,6 +996,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;
 
         #define GO(GETFLAGS, NO, YES, F)                                \
+            if (box64_dynarec_test == 2) { NOTEST(x1); }                \
             READFLAGS(F);                                               \
             i8 = F8S;                                                   \
             BARRIER(BARRIER_MAYBE);                                     \
@@ -3094,6 +3095,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xE9:
         case 0xEB:
             BARRIER(BARRIER_MAYBE);
+            if (box64_dynarec_test == 2) { NOTEST(x1); }
             if(opcode==0xEB && PK(0)==0xFF) {
                 INST_NAME("JMP ib");
                 MESSAGE(LOG_DEBUG, "Hack for EB FF opcode");
diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c
index 9ae17ea5..37ce5743 100644
--- a/src/dynarec/arm64/dynarec_arm64_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_0f.c
@@ -1551,6 +1551,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;

 

         #define GO(GETFLAGS, NO, YES, F)   \

+            if (box64_dynarec_test == 2) { NOTEST(x1); }                \

             READFLAGS(F);                                               \

             i32_ = F32S;                                                \

             BARRIER(BARRIER_MAYBE);                                     \

diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index 71d26d50..e03b6655 100644
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -102,7 +102,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
                 }
             }
             reset_n = -1;
-        } 
+        }
         #if STEP > 0
         else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
             dyn->last_ip = 0;   // reset IP if some jump are coming here
@@ -122,9 +122,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
             READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
         }
         if(box64_dynarec_test) {
-            MESSAGE(LOG_DUMP, "TEST INIT ----\n");
+            MESSAGE(LOG_DUMP, "TEST STEP ----\n");
             fpu_reflectcache(dyn, ninst, x1, x2, x3);
-            GO_TRACE(x64test_init, 1, x5);
+            GO_TRACE(x64test_step, 1, x5);
             fpu_unreflectcache(dyn, ninst, x1, x2, x3);
             MESSAGE(LOG_DUMP, "----------\n");
         }
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index 64e8ba5f..721f3864 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -511,6 +511,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             break;
 
         #define GO(GETFLAGS, NO, YES, F, I)                                                         \
+            if (box64_dynarec_test == 2) { NOTEST(x1); }                                            \
             READFLAGS(F);                                                                           \
             i8 = F8S;                                                                               \
             BARRIER(BARRIER_MAYBE);                                                                 \
@@ -1601,6 +1602,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0xE9:
         case 0xEB:
             BARRIER(BARRIER_MAYBE);
+            if (box64_dynarec_test == 2) { NOTEST(x1); }
             if (opcode == 0xE9) {
                 INST_NAME("JMP Id");
                 i32 = F32S;
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 4aee3a5d..65bf7881 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -257,6 +257,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             break;
 
         #define GO(GETFLAGS, NO, YES, F, I)                                                         \
+            if (box64_dynarec_test == 2) { NOTEST(x1); }                                            \
             READFLAGS(F);                                                                           \
             i32_ = F32S;                                                                            \
             BARRIER(BARRIER_MAYBE);                                                                 \
diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c
index 621bbfce..cab04708 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_1.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_1.c
@@ -289,6 +289,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             break;
 
         #define GO(GETFLAGS, NO, YES, F)                                \
+            if (box64_dynarec_test == 2) { NOTEST(x1); }                \
             READFLAGS(F);                                               \
             i8 = F8S;                                                   \
             BARRIER(BARRIER_MAYBE);                                     \
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 015c2df9..0294c944 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -947,6 +947,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0xE9:
         case 0xEB:
             BARRIER(BARRIER_MAYBE);
+            if (box64_dynarec_test == 2) { NOTEST(x1); }
             if(opcode==0xE9) {
                 INST_NAME("JMP Id");
                 i32 = F32S;
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index a7c54e58..d0cac627 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -1210,6 +1210,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             SD(x3, wback, fixedaddress);
             break;
 #define GO(GETFLAGS, NO, YES, F)                                                            \
+    if (box64_dynarec_test == 2) { NOTEST(x1); }                                            \
     READFLAGS(F);                                                                           \
     i32_ = F32S;                                                                            \
     BARRIER(BARRIER_MAYBE);                                                                 \
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 7ae9e1bd..223c6768 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -37,6 +37,7 @@ typedef struct x64test_s {
     int         memsize;
     int         test;
     int         clean;
+    int         notest;
     uint8_t     mem[16];
 } x64test_t;
 
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 6d1ed141..d7950424 100644
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -557,14 +557,19 @@ x64emurun:
         case 0x6D:                      /* INSD DX */
         case 0x6E:                      /* OUTSB DX */
         case 0x6F:                      /* OUTSD DX */
-            #ifndef TEST_INTERPRETOR
+            #ifndef TEST_INTERPRETER
             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
+            #else
+            test->notest = 1;
             #endif
             break;
 
         GOCOND(0x70
             ,   tmp8s = F8S; CHECK_FLAGS(emu);
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             ,   addr += tmp8s;
             ,,STEP2
             )                           /* Jxx Ib */
@@ -1328,10 +1333,16 @@ x64emurun:
             addr = rex.is32bits?Pop32(emu):Pop64(emu);
             R_RSP += tmp16u;
             STEP2
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
         case 0xC3:                      /* RET */
             addr = rex.is32bits?Pop32(emu):Pop64(emu);
             STEP2
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
         case 0xC4:                      /* LES Gd,Ed */
             if(rex.is32bits && !(PK(0)&0x80)) {
@@ -1438,6 +1449,8 @@ x64emurun:
             x64Int3(emu, &addr);
             if(emu->quit) goto fini;    // R_RIP is up to date when returning from x64Int3
             addr = R_RIP;
+            #else
+            test->notest = 1;
             #endif
             break;
         case 0xCD:                      /* INT n */
@@ -1459,11 +1472,15 @@ x64emurun:
                 #ifndef TEST_INTERPRETER
                 x86Syscall(emu);
                 STEP;
+                #else
+                test->notest = 1;
                 #endif
             } else {
                 #ifndef TEST_INTERPRETER
                 emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
                 STEP;
+                #else
+                test->notest = 1;
                 #endif
             }
             break;
@@ -1496,6 +1513,8 @@ x64emurun:
             #ifndef TEST_INTERPRETER
             if(is32bits)
                 running32bits = 1;
+            #else
+            test->notest = 1;
             #endif
             break;
         case 0xD0:                      /* GRP2 Eb,1 */
@@ -1741,6 +1760,8 @@ x64emurun:
             #ifndef TEST_INTERPRETER
             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
+            #else
+            test->notest = 1;
             #endif
             break;
         case 0xE8:                      /* CALL Id */
@@ -1755,6 +1776,9 @@ x64emurun:
                 addr += tmp32s;
             addr = (uintptr_t)getAlternate((void*)addr);
             STEP2
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
         case 0xE9:                      /* JMP Id */
             tmp32s = F32S; // jmp is relative
@@ -1764,12 +1788,18 @@ x64emurun:
                 addr += tmp32s;
             addr = (uintptr_t)getAlternate((void*)addr);
             STEP2
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
 
         case 0xEB:                      /* JMP Ib */
             tmp32s = F8S; // jump is relative
             addr += tmp32s;
             STEP2
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
         case 0xEC:                      /* IN AL, DX */
         case 0xED:                      /* IN EAX, DX */
@@ -1779,6 +1809,8 @@ x64emurun:
             #ifndef TEST_INTERPRETER
             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
+            #else
+            test->notest = 1;
             #endif
             break;
         case 0xF0:                      /* LOCK prefix */
@@ -1802,6 +1834,8 @@ x64emurun:
             #ifndef TEST_INTERPRETER
             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
+            #else
+            test->notest = 1;
             #endif
             break;
         case 0xF5:                      /* CMC */
@@ -1839,6 +1873,9 @@ x64emurun:
                     if(!EB->byte[0])
                         emit_div0(emu, (void*)R_RIP, 0);
                     idiv8(emu, EB->byte[0]);
+                    #ifdef TEST_INTERPRETER
+                    test->notest = 1;
+                    #endif
                     break;
             }
             break;
@@ -1874,6 +1911,9 @@ x64emurun:
                         if(!ED->q[0])
                             emit_div0(emu, (void*)R_RIP, 0);
                         idiv64(emu, ED->q[0]);
+                        #ifdef TEST_INTERPRETER
+                        test->notest = 1;
+                        #endif
                         break;
                 }
             } else {
@@ -1934,11 +1974,17 @@ x64emurun:
             // this is a privilege opcode
             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
         case 0xFB:                      /* STI */
             // this is a privilege opcode
             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
             STEP;
+            #ifdef TEST_INTERPRETER
+            test->notest = 1;
+            #endif
             break;
         case 0xFC:                      /* CLD */
             CLEAR_FLAG(F_DF);
@@ -1997,6 +2043,9 @@ x64emurun:
                     }
                     addr = tmp64u;
                     STEP2
+                    #ifdef TEST_INTERPRETER
+                    test->notest = 1;
+                    #endif
                     break;
                 case 3:                 /* CALL FAR Ed */
                     GETET(0);
@@ -2021,6 +2070,8 @@ x64emurun:
                         #ifndef TEST_INTERPRETER
                         if(is32bits)
                             running32bits = 1;
+                        #else
+                        test->notest = 1;
                         #endif
                     }
                     break;
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index e9c2c761..7517603b 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -93,6 +93,8 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
                 case 0xD0:

                     #ifndef TEST_INTERPRETER

                     emit_signal(emu, SIGILL, (void*)R_RIP, 0);

+                    #else

+                    test->notest = 1;

                     #endif

                     break;

                 case 0xE0:

@@ -112,6 +114,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
                     R_RAX = tmp64u & 0xffffffff;

                     R_RDX = tmp64u >> 32;

                     R_RCX = 0;  // should be low of IA32_TSC

+                    #ifdef TEST_INTERPRETER

+                    test->notest = 1;

+                    #endif

                     break;

                 default:

                     return 0;

@@ -146,6 +151,8 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
             #ifndef TEST_INTERPRETER

             R_RIP = addr;

             x64Syscall(emu);

+            #else

+            test->notest = 1;

             #endif

             break;

         case 0x06:                      /* CLTS */

@@ -160,12 +167,16 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
             // this is a privilege opcode...

             #ifndef TEST_INTERPRETER

             emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);

+            #else

+            test->notest = 1;

             #endif

             break;

 

         case 0x0B:                      /* UD2 */

             #ifndef TEST_INTERPRETER

             emit_signal(emu, SIGILL, (void*)R_RIP, 0);

+            #else

+            test->notest = 1;

             #endif

             break;

 

@@ -183,6 +194,8 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         case 0x0E:                      /* FEMMS */

             #ifndef TEST_INTERPRETER

             emit_signal(emu, SIGILL, (void*)R_RIP, 0);

+            #else

+            test->notest = 1;

             #endif

             break;

 

@@ -374,6 +387,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
                 tmp64u<<=box64_rdtsc_shift;

             R_RDX = tmp64u>>32;

             R_RAX = tmp64u&0xFFFFFFFF;

+            #ifdef TEST_INTERPRETER

+            test->notest = 1;

+            #endif

             break;

 

         case 0x38:  // these are some SSE3 opcodes

@@ -581,6 +597,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
                 else

                     GX->f[i] = 1.0f/sqrtf(EX->f[i]);

             }

+            #ifdef TEST_INTERPRETER

+            test->notest = 1;

+            #endif

             break;

         case 0x53:                      /* RCPPS Gx, Ex */

             nextop = F8;

@@ -588,6 +607,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
             GETGX;

             for(int i=0; i<4; ++i)

                 GX->f[i] = 1.0f/EX->f[i];

+            #ifdef TEST_INTERPRETER

+            test->notest = 1;

+            #endif

             break;

         case 0x54:                      /* ANDPS Gx, Ex */

             nextop = F8;

@@ -953,6 +975,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
             break;

         GOCOND(0x80

             , tmp32s = F32S; CHECK_FLAGS(emu);

+            #ifdef TEST_INTERPRETER

+            test->notest = 1;

+            #endif

             , addr += tmp32s;

             ,,

         )                               /* 0x80 -> 0x8F Jxx */ //STEP3

@@ -979,6 +1004,9 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
         case 0xA2:                      /* CPUID */

             tmp32u = R_EAX;

             my_cpuid(emu, tmp32u);

+            #ifdef TEST_INTERPRETER

+            test->notest = 1;

+            #endif

             break;

         case 0xA3:                      /* BT Ed,Gd */

             CHECK_FLAGS(emu);

diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c
index 39479f20..e1032fb8 100644
--- a/src/emu/x64run64.c
+++ b/src/emu/x64run64.c
@@ -732,6 +732,9 @@ uintptr_t Run64(x64emu_t *emu, rex_t rex, int seg, uintptr_t addr)
                         break;

                     case 7:                 /* IDIV Ed */

                         idiv64(emu, ED->q[0]);

+                        #ifdef TEST_INTERPRETER

+                        test->notest = 1;

+                        #endif

                         break;

                 }

             } else {

diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c
index b9f8e924..536583bc 100644
--- a/src/emu/x64run66.c
+++ b/src/emu/x64run66.c
@@ -837,6 +837,9 @@ uintptr_t Run66(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
                     break;

                 case 7:                 /* IDIV Ed */

                     idiv64(emu, ED->q[0]);

+                    #ifdef TEST_INTERPRETER

+                    test->notest = 1;

+                    #endif

                     break;

             }

         } else {

diff --git a/src/emu/x64run67.c b/src/emu/x64run67.c
index 842d6740..9cdcba3b 100644
--- a/src/emu/x64run67.c
+++ b/src/emu/x64run67.c
@@ -111,7 +111,11 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
     GO(0x00, add)                   /* ADD 0x00 -> 0x05 */

     GO(0x08, or)                    /*  OR 0x08 -> 0x0D */

     case 0x0F:

+        #ifdef TEST_INTERPRETER

+        return Test670F(test, rex, rep, addr);

+        #else

         return Run670F(emu, rex, rep, addr);

+        #endif

     GO(0x10, adc)                   /* ADC 0x10 -> 0x15 */

     GO(0x18, sbb)                   /* SBB 0x18 -> 0x1D */

     GO(0x20, and)                   /* AND 0x20 -> 0x25 */

@@ -405,6 +409,9 @@ uintptr_t Run67(x64emu_t *emu, rex_t rex, int rep, uintptr_t addr)
                     break;

                 case 7:                 /* IDIV Ed */

                     idiv64(emu, ED->q[0]);

+                    #ifdef TEST_INTERPRETER

+                    test->notest = 1;

+                    #endif

                     break;

             }

         } else {

diff --git a/src/emu/x64test.c b/src/emu/x64test.c
index 447cd384..ea97500c 100644
--- a/src/emu/x64test.c
+++ b/src/emu/x64test.c
@@ -22,6 +22,8 @@
 #include "bridge.h"
 #include "signals.h"
 
+static pthread_mutex_t mutex_global_test;
+
 void print_banner(x64emu_t* ref)
 {
     printf_log(LOG_NONE, "Warning, difference between %s Interpreter and Dynarec in %p (%02x %02x %02x %02x %02x %02x %02x %02x)\n"\
@@ -131,18 +133,20 @@ void x64test_check(x64emu_t* ref, uintptr_t ip)
 }
 #undef BANNER
 
-void x64test_init(x64emu_t* ref, uintptr_t ip)
+void x64test_step(x64emu_t* ref, uintptr_t ip)
 {
     x64test_t* test = &ref->test;
     if(!test->test) {
         test->clean = 0;
         return;
     }
-    // check if test as a valid emu struct
+    // check if test is a valid emu struct
     if(!test->emu) {
         test->emu = NewX64Emu(my_context, ip, (uintptr_t)ref->init_stack, ref->size_stack, 0);
         CopyEmu(test->emu, ref);
     } else {
+        if (box64_dynarec_test == 2 && test->test && test->clean)
+            pthread_mutex_unlock(&mutex_global_test);
         // check if IP is same, else, sync
         uintptr_t prev_ip = test->emu->ip.q[0];
         if(test->clean)
@@ -151,10 +155,23 @@ void x64test_init(x64emu_t* ref, uintptr_t ip)
             CopyEmu(test->emu, ref);
         }
     }
-    // Do a Dry single Step
+    // do a dry single step
     test->memsize = 0;
     test->clean = 1;
+    test->notest = 0;
     ref->old_ip = ip;
+
+    if (box64_dynarec_test == 2) pthread_mutex_lock(&mutex_global_test);
     RunTest(test);
-    // this will be anakyzed next step
+    if (box64_dynarec_test == 2 && test->notest) pthread_mutex_unlock(&mutex_global_test);
+    // this will be analyzed next step
 }
+
+void x64test_init()
+{
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+    pthread_mutex_init(&mutex_global_test, &attr);
+    pthread_mutexattr_destroy(&attr);
+}
\ No newline at end of file
diff --git a/src/include/dynarec.h b/src/include/dynarec.h
index 64da6041..bf72349c 100644
--- a/src/include/dynarec.h
+++ b/src/include/dynarec.h
@@ -5,7 +5,8 @@ typedef struct x64emu_s x64emu_t;
 
 void DynaCall(x64emu_t* emu, uintptr_t addr); // try to use DynaRec... Fallback to EmuCall if no dynarec available
 
-void x64test_init(x64emu_t* ref, uintptr_t ip);
+void x64test_init();
+void x64test_step(x64emu_t* ref, uintptr_t ip);
 void x64test_check(x64emu_t* ref, uintptr_t ip);
 
 #endif // __DYNAREC_H_
\ No newline at end of file