about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_00.c12
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_0f.c3
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.h11
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_private.h1
-rw-r--r--src/dynarec/dynarec_native_functions.c2
-rwxr-xr-xsrc/dynarec/dynarec_native_pass.c12
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c2
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h11
-rw-r--r--src/dynarec/rv64/dynarec_rv64_private.h1
-rwxr-xr-xsrc/emu/x64emu_private.h3
-rwxr-xr-xsrc/emu/x64run.c8
-rw-r--r--src/emu/x64test.c41
-rwxr-xr-xsrc/libtools/signals.c9
14 files changed, 81 insertions, 39 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 7a91dcf1..2c82d929 100755
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -500,7 +500,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x57:
             INST_NAME("PUSH reg");
             if(dyn->doublepush) {
-                dyn->test = 0;
+                NOTEST(x1);
                 dyn->doublepush = 0;
             } else {
                 gd = xRAX+(opcode&0x07)+(rex.b<<3);
@@ -525,7 +525,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     }
                     PUSH2(gd, u32);
                     dyn->doublepush = 1;
-                    dyn->test = 0;  // disable test for this OP
+                    NOTEST(x1);  // disable test for this OP
                 } else {
                     PUSH1(gd);
                 }   
@@ -541,7 +541,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x5F:
             INST_NAME("POP reg");
             if(dyn->doublepop) {
-                dyn->test = 0;
+                NOTEST(x1);
                 dyn->doublepop = 0;
             } else {
                 gd = xRAX+(opcode&0x07)+(rex.b<<3);
@@ -566,7 +566,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         }
                     }
                     dyn->doublepop = 1;
-                    dyn->test = 0;  // disable test for this OP
+                    NOTEST(x1);  // disable test for this OP
                 } else {
                     if(gd == xRSP) {
                         POP1(x1);
@@ -1749,7 +1749,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 
         case 0xCC:
             SETFLAGS(X_ALL, SF_SET);    // Hack, set all flags (to an unknown state...)
-            dyn->test = 0;
+            NOTEST(x1);
             if(PK(0)=='S' && PK(1)=='C') {
                 addr+=2;
                 BARRIER(BARRIER_FLOAT);
@@ -2216,7 +2216,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     }
                     PUSH1(x2);
                     MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
-                    dyn->test=0;    // disable test as this hack dos 2 instructions for 1
+                    NOTEST(x1);    // disable test as this hack dos 2 instructions for 1
                     // calling a native function
                     sse_purge07cache(dyn, ninst, x3);
                     if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall)
diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c
index 8b817c9e..d0f055f2 100755
--- a/src/dynarec/arm64/dynarec_arm64_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_0f.c
@@ -75,6 +75,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 

         case 0x05:

             INST_NAME("SYSCALL");

+            NOTEST(x1);

             SMEND();

             GETIP(addr);

             STORE_XEMU_CALL(xRIP);

@@ -329,6 +330,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 

         case 0x31:

             INST_NAME("RDTSC");

+            NOTEST(x1);

             MESSAGE(LOG_DUMP, "Need Optimization\n");

             CALL(ReadTSC, xRAX);   // will return the u64 in xEAX

             LSRx(xRDX, xRAX, 32);

@@ -1069,6 +1071,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             

         case 0xA2:

             INST_NAME("CPUID");

+            NOTEST(x1);

             MOVx_REG(x1, xRAX);

             CALL_(my_cpuid, -1, 0);

             break;

diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index acc9a0c5..64f05583 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1301,4 +1301,15 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             , cNE, cEQ, X_SF|X_OF|X_ZF)                     \
         break
 
+#define NOTEST(s1)                                          \
+    if(box64_dynarec_test) {                                \
+        if(offsetof(x64emu_t, test.test)<(1<<12)) {         \
+            STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.test));\
+        } else {                                            \
+            MOV32w(s1, offsetof(x64emu_t, test.test));      \
+            ADDx_REG(s1, xEmu, s1);                         \
+            STRw_U12(xZR, s1, 0);                           \
+        }                                                   \
+    }
+
 #endif //__DYNAREC_ARM64_HELPER_H__
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index 82747067..15705634 100755
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -106,7 +106,6 @@ typedef struct dynarec_arm_s {
     size_t              insts_size; // size of the instruction size array (calculated)
     uint8_t             smread;    // for strongmem model emulation
     uint8_t             smwrite;    // for strongmem model emulation
-    int8_t              test;       // test the opcode?
     uintptr_t           forward;    // address of the last end of code while testing forward
     uintptr_t           forward_to; // address of the next jump to (to check if everything is ok)
     int32_t             forward_size;   // size at the forward point
diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c
index 2cf87003..42c7fba8 100644
--- a/src/dynarec/dynarec_native_functions.c
+++ b/src/dynarec/dynarec_native_functions.c
@@ -153,6 +153,8 @@ void native_fld(x64emu_t* emu, uint8_t* ed)
 
 void native_ud(x64emu_t* emu)
 {
+    if(box64_dynarec_test)
+        emu->test.test = 0;
     emit_signal(emu, SIGILL, (void*)R_RIP, 0);
 }
 
diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index 80da9436..d81ef6ee 100755
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -86,9 +86,8 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
         if(box64_dynarec_test) {
             MESSAGE(LOG_DUMP, "TEST INIT ----\n");
             fpu_reflectcache(dyn, ninst, x1, x2, x3);
-            GO_TRACE(x64test_init, dyn->test);
+            GO_TRACE(x64test_init, 1);
             MESSAGE(LOG_DUMP, "----------\n");
-            dyn->test = 1;
         }
 #ifdef HAVE_TRACE
         else if(my_context->dec && box64_dynarec_trace) {
@@ -122,13 +121,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
 
         addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog);
 
-        if(dyn->test) {
-            MESSAGE(LOG_DUMP, "TEST CHECK ----\n");
-            fpu_reflectcache(dyn, ninst, x1, x2, x3);
-            GO_TRACE(x64test_check, 1);
-            MESSAGE(LOG_DUMP, "----------\n");
-        }
-
         INST_EPILOG;
 
         int next = ninst+1;
@@ -262,12 +254,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
             dyn->insts[ninst].x64.need_after |= X_PEND;
             #endif
             ++ninst;
+            NOTEST(x3);
             fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
             jump_to_next(dyn, addr, 0, ninst);
             ok=0; need_epilog=0;
         }
     }
     if(need_epilog) {
+        NOTEST(x3);
         fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
         jump_to_epilog(dyn, ip, 0, ninst);  // no linker here, it's an unknow instruction
     }
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c
index 2b62f097..4dab2b01 100644
--- a/src/dynarec/rv64/dynarec_rv64_00.c
+++ b/src/dynarec/rv64/dynarec_rv64_00.c
@@ -1270,7 +1270,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
         case 0xCC:
             SETFLAGS(X_ALL, SF_SET);    // Hack, set all flags (to an unknown state...)
-            dyn->test=0;
+            NOTEST(x1);
             if(PK(0)=='S' && PK(1)=='C') {
                 addr+=2;
                 BARRIER(BARRIER_FLOAT);
@@ -1464,7 +1464,7 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             switch(tmp) {
                 case 3:
                     SETFLAGS(X_ALL, SF_SET);    // Hack to set flags to "dont'care" state
-                    dyn->test = 0;
+                    NOTEST(x1);
                     BARRIER(BARRIER_FULL);
                     //BARRIER_NEXT(BARRIER_FULL);
                     if(dyn->last_ip && (addr-dyn->last_ip<0x1000)) {
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 74f3379a..965f4fea 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -73,6 +73,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
         case 0x05:
             INST_NAME("SYSCALL");
+            NOTEST(x1);
             SMEND();
             GETIP(addr);
             STORE_XEMU_CALL();
@@ -314,6 +315,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             
         case 0xA2:
             INST_NAME("CPUID");
+            NOTEST(x1);
             MV(A1, xRAX);
             CALL_(my_cpuid, -1, 0);
             // BX and DX are not synchronized durring the call, so need to force the update
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 3c3d11e5..e8ad11ab 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1106,4 +1106,15 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             , NEZ, EQZ, X_SF|X_OF|X_ZF)                     \
         break
 
+#define NOTEST(s1)                                          \
+    if(box64_dynarec_test) {                                \
+        if(offsetof(x64emu_t, test.test)<2048) {            \
+            SW(xZR, xEmu, offsetof(x64emu_t, test.test));   \
+        } else {                                            \
+            MOV32w(s1, offsetof(x64emu_t, test.test));      \
+            ADD(s1, xEmu, s1);                              \
+            SW(xZR, s1, 0);                                 \
+        }                                                   \
+    }
+
 #endif //__DYNAREC_RV64_HELPER_H__
diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h
index e6fc7f63..3d6205d9 100644
--- a/src/dynarec/rv64/dynarec_rv64_private.h
+++ b/src/dynarec/rv64/dynarec_rv64_private.h
@@ -107,7 +107,6 @@ typedef struct dynarec_rv64_s {
     size_t              insts_size; // size of the instruction size array (calculated)
     uint8_t             smread;    // for strongmem model emulation
     uint8_t             smwrite;    // for strongmem model emulation
-    int8_t              test;       // test the opcode?
     uintptr_t           forward;    // address of the last end of code while testing forward
     uintptr_t           forward_to; // address of the next jump to (to check if everything is ok)
     int32_t             forward_size;   // size at the forward point
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 3393986c..3fb43df3 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -31,6 +31,7 @@ typedef struct x64test_s {
     x64emu_t*   emu;
     uintptr_t   memaddr;
     int         memsize;
+    int         test;
     uint8_t     mem[16];
 } x64test_t;
 
@@ -86,6 +87,7 @@ typedef struct x64emu_s {
     int         quitonlongjmp;  // quit if longjmp is called
     int         quitonexit;     // quit if exit/_exit is called
     int         longjmp;        // if quit because of longjmp
+    x64test_t   test;       // used for dynarec testing
     // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
     uint64_t    scratch[200];
     // local stack, do be deleted when emu is freed
@@ -96,7 +98,6 @@ typedef struct x64emu_s {
     x64_ucontext_t *uc_link; // to handle setcontext
 
     int         type;       // EMUTYPE_xxx define
-    x64test_t   test;
 } x64emu_t;
 
 #define EMUTYPE_NONE    0
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 0f982a77..f064dfd1 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -1581,9 +1581,9 @@ x64emurun:
             break;
         case 0xFF:                      /* GRP 5 Ed */
             nextop = F8;
-            GETED(0);
             switch((nextop>>3)&7) {
                 case 0:                 /* INC Ed */
+                    GETED(0);
                     if(rex.w)
                         ED->q[0] = inc64(emu, ED->q[0]);
                     else {
@@ -1594,6 +1594,7 @@ x64emurun:
                     }
                     break;
                 case 1:                 /* DEC Ed */
+                    GETED(0);
                     if(rex.w)
                         ED->q[0] = dec64(emu, ED->q[0]);
                     else {
@@ -1604,12 +1605,14 @@ x64emurun:
                     }
                     break;
                 case 2:                 /* CALL NEAR Ed */
+                    GETE8(0);
                     tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
                     Push(emu, addr);
                     addr = tmp64u;
                     STEP2
                     break;
                 case 3:                 /* CALL FAR Ed */
+                    GETET(0);
                     if(MODREG) {
                         printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
                         emu->quit=1;
@@ -1624,10 +1627,12 @@ x64emurun:
                     }
                     break;
                 case 4:                 /* JMP NEAR Ed */
+                    GETE8(0);
                     addr = (uintptr_t)getAlternate((void*)ED->q[0]);
                     STEP2
                     break;
                 case 5:                 /* JMP FAR Ed */
+                    GETET(0);
                     if(MODREG) {
                         printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)R_RIP, opcode, nextop, PK(2), PK(3));
                         emu->quit=1;
@@ -1640,6 +1645,7 @@ x64emurun:
                     }
                     break;
                 case 6:                 /* Push Ed */
+                    GETE8(0);
                     tmp64u = ED->q[0];  // rex.w ignored
                     #ifdef TEST_INTERPRETER
                     R_RSP -=8;
diff --git a/src/emu/x64test.c b/src/emu/x64test.c
index f58e68c4..ee241597 100644
--- a/src/emu/x64test.c
+++ b/src/emu/x64test.c
@@ -7,6 +7,7 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <stddef.h>
 
 #include "debug.h"
 #include "box64stack.h"
@@ -21,23 +22,6 @@
 #include "bridge.h"
 #include "signals.h"
 
-void x64test_init(x64emu_t* ref, uintptr_t ip, int ok)
-{
-    x64test_t* test = &ref->test;
-    // check if test as 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);
-    }
-    // check if IP is same, else, sync
-    if(ip != test->emu->ip.q[0] || !ok) {
-        CopyEmu(test->emu, ref);
-    }
-    // Do a Dry single Step
-    test->memsize = 0;
-    RunTest(test);
-}
-
 void print_banner(x64emu_t* ref)
 {
     printf_log(LOG_NONE, "Warning, difference between Interpreter and Dynarec in %p\n=======================================\n", (void*)ref->ip.q[0]);
@@ -134,9 +118,30 @@ void x64test_check(x64emu_t* ref, uintptr_t ip)
             printf_log(LOG_NONE, " |");
             for(int i=0; i<test->memsize; ++i)
                 printf_log(LOG_NONE, " %02x", ((uint8_t*)test->memaddr)[i]);
+            printf_log(LOG_NONE, "\n");
         }
     }
     if(banner)  // there was an error, re-sync!
         CopyEmu(emu, ref);
 }
-#undef BANNER
\ No newline at end of file
+#undef BANNER
+
+void x64test_init(x64emu_t* ref, uintptr_t ip)
+{
+    x64test_t* test = &ref->test;
+    // check if test as 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(test->test) {
+        x64test_check(ref, ip);
+    }
+    // check if IP is same, else, sync
+    if(ip != test->emu->ip.q[0] || !test->test) {
+        CopyEmu(test->emu, ref);
+    }
+    // Do a Dry single Step
+    test->memsize = 0;
+    test->test = 1;
+    RunTest(test);
+}
diff --git a/src/libtools/signals.c b/src/libtools/signals.c
index 9526f49b..df715a0f 100755
--- a/src/libtools/signals.c
+++ b/src/libtools/signals.c
@@ -291,6 +291,10 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc
 #endif
 
     x64emu_t *emu = thread_get_emu();
+    #ifdef DYNAREC
+    if(box64_dynarec_test)
+        emu->test.test = 0;
+    #endif
 
     printf_log(LOG_DEBUG, "%04d|signal function handler %p called, RSP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
     
@@ -326,6 +330,11 @@ uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc
 
     emu->quitonlongjmp = oldquitonlongjmp;
 
+    #ifdef DYNAREC
+    if(box64_dynarec_test)
+        emu->test.test = 0;
+    #endif
+
     if(emu->longjmp) {
         // longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
         emu->longjmp = 0;