about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/dynarec_native_pass.c9
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_1.c12
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c59
-rw-r--r--src/dynarec/rv64/dynarec_rv64_functions.c18
-rw-r--r--src/dynarec/rv64/dynarec_rv64_functions.h1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h5
-rw-r--r--src/dynarec/rv64/dynarec_rv64_pass0.h3
7 files changed, 68 insertions, 39 deletions
diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index 5df1dce2..43d07719 100644
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -176,7 +176,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
         #if STEP > 0
         if(dyn->insts[ninst].x64.has_next && dyn->insts[next].x64.barrier) {
             if(dyn->insts[next].x64.barrier&BARRIER_FLOAT) {
-                fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
+                #ifdef RV64
+                uint8_t tmp1, tmp2, tmp3;
+                if(dyn->insts[next].nat_flags_fusion) get_free_scratch(dyn, next, &tmp1, &tmp2, &tmp3, x1, x2, x3, x4, x5);
+                else { tmp1=x1; tmp2=x2; tmp3=x3; }
+                fpu_purgecache(dyn, ninst, 0, tmp1, tmp2, tmp3);
+                #else
+                fpu_purgecache(dyn, next, 0, x1, x2, x3);
+                #endif
             }
             if(dyn->insts[next].x64.barrier&BARRIER_FLAGS) {
                 dyn->f.pending = 0;
diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c
index 1d2d6dbc..9940d5ec 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_1.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_1.c
@@ -30,7 +30,7 @@ int isSimpleWrapper(wrapper_t fun);
 uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
 {
     uint8_t nextop, opcode;
-    uint8_t gd, ed;
+    uint8_t gd, ed, tmp1, tmp2, tmp3;
     int8_t i8;
     int32_t i32, tmp;
     int64_t i64, j64;
@@ -308,7 +308,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             break;
 
 #define GO(GETFLAGS, NO, YES, NATNO, NATYES, F)                                             \
-    READFLAGS_FUSION(F, 1);                                                                 \
+    READFLAGS_FUSION(F, x1, x2, x3, x4, x5);                                                \
     i8 = F8S;                                                                               \
     BARRIER(BARRIER_MAYBE);                                                                 \
     JUMP(addr + i8, 1);                                                                     \
@@ -321,14 +321,14 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         if (dyn->insts[ninst].nat_flags_fusion) {                                           \
             NATIVEJUMP_safe(NATNO, i32);                                                    \
         } else {                                                                            \
-            B##NO##_safe(x1, i32);                                                          \
+            B##NO##_safe(tmp1, i32);                                                        \
         }                                                                                   \
         if (dyn->insts[ninst].x64.jmp_insts == -1) {                                        \
             if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT))                           \
-                fpu_purgecache(dyn, ninst, 1, x1, x2, x3);                                  \
+                fpu_purgecache(dyn, ninst, 1, tmp1, tmp2, tmp3);                            \
             jump_to_next(dyn, addr + i8, 0, ninst, rex.is32bits);                           \
         } else {                                                                            \
-            CacheTransform(dyn, ninst, cacheupd, x1, x2, x3);                               \
+            CacheTransform(dyn, ninst, cacheupd, tmp1, tmp2, tmp3);                         \
             i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
             B(i32);                                                                         \
         }                                                                                   \
@@ -338,7 +338,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         if (dyn->insts[ninst].nat_flags_fusion) {                                           \
             NATIVEJUMP_safe(NATYES, i32);                                                   \
         } else {                                                                            \
-            B##YES##_safe(x1, i32);                                                         \
+            B##YES##_safe(tmp1, i32);                                                       \
         }                                                                                   \
     }
             GOCOND(0x70, "J", "ib");
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index d0d79725..9838d9b8 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -36,6 +36,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     uint8_t wb1, wback, wb2, gback;
     uint8_t eb1, eb2;
     uint8_t gb1, gb2;
+    uint8_t tmp1, tmp2, tmp3;
     int32_t i32, i32_;
     int cacheupd = 0;
     int v0, v1;
@@ -899,30 +900,30 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             break;
 
-#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F)                                              \
-    READFLAGS_FUSION(F, 0);                                                                  \
-    if (!dyn->insts[ninst].nat_flags_fusion) {                                               \
-        GETFLAGS;                                                                            \
-    }                                                                                        \
-    nextop = F8;                                                                             \
-    GETGD;                                                                                   \
-    if (MODREG) {                                                                            \
-        ed = TO_NAT((nextop & 7) + (rex.b << 3));                                            \
-        if (dyn->insts[ninst].nat_flags_fusion) {                                            \
-            NATIVEJUMP(NATNO, 8);                                                            \
-        } else {                                                                             \
-            B##NO(x1, 8);                                                                    \
-        }                                                                                    \
-        MV(gd, ed);                                                                          \
-    } else {                                                                                 \
-        addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); \
-        if (dyn->insts[ninst].nat_flags_fusion) {                                            \
-            NATIVEJUMP(NATNO, 8);                                                            \
-        } else {                                                                             \
-            B##NO(x1, 8);                                                                    \
-        }                                                                                    \
-        LDxw(gd, ed, fixedaddress);                                                          \
-    }                                                                                        \
+#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F)                                                     \
+    READFLAGS_FUSION(F, x1, x2, x3, x4, x5);                                                        \
+    if (!dyn->insts[ninst].nat_flags_fusion) {                                                      \
+        GETFLAGS;                                                                                   \
+    }                                                                                               \
+    nextop = F8;                                                                                    \
+    GETGD;                                                                                          \
+    if (MODREG) {                                                                                   \
+        ed = TO_NAT((nextop & 7) + (rex.b << 3));                                                   \
+        if (dyn->insts[ninst].nat_flags_fusion) {                                                   \
+            NATIVEJUMP(NATNO, 8);                                                                   \
+        } else {                                                                                    \
+            B##NO(tmp1, 8);                                                                         \
+        }                                                                                           \
+        MV(gd, ed);                                                                                 \
+    } else {                                                                                        \
+        addr = geted(dyn, addr, ninst, nextop, &ed, tmp2, tmp3, &fixedaddress, rex, NULL, 1, 0);    \
+        if (dyn->insts[ninst].nat_flags_fusion) {                                                   \
+            NATIVEJUMP(NATNO, 8);                                                                   \
+        } else {                                                                                    \
+            B##NO(tmp1, 8);                                                                         \
+        }                                                                                           \
+        LDxw(gd, ed, fixedaddress);                                                                 \
+    }                                                                                               \
     if (!rex.w) ZEROUP(gd);
 
             GOCOND(0x40, "CMOV", "Gd, Ed");
@@ -1671,7 +1672,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, NATNO, NATYES, F)                                             \
-    READFLAGS_FUSION(F, 1);                                                                 \
+    READFLAGS_FUSION(F, x1, x2, x3, x4, x5);                                                \
     i32_ = F32S;                                                                            \
     if (rex.is32bits)                                                                       \
         j64 = (uint32_t)(addr + i32_);                                                      \
@@ -1688,14 +1689,14 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         if (dyn->insts[ninst].nat_flags_fusion) {                                           \
             NATIVEJUMP_safe(NATNO, i32);                                                    \
         } else {                                                                            \
-            B##NO##_safe(x1, i32);                                                          \
+            B##NO##_safe(tmp1, i32);                                                        \
         }                                                                                   \
         if (dyn->insts[ninst].x64.jmp_insts == -1) {                                        \
             if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT))                           \
-                fpu_purgecache(dyn, ninst, 1, x1, x2, x3);                                  \
+                fpu_purgecache(dyn, ninst, 1, tmp1, tmp2, tmp3);                            \
             jump_to_next(dyn, j64, 0, ninst, rex.is32bits);                                 \
         } else {                                                                            \
-            CacheTransform(dyn, ninst, cacheupd, x1, x2, x3);                               \
+            CacheTransform(dyn, ninst, cacheupd, tmp1, tmp2, tmp3);                         \
             i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
             B(i32);                                                                         \
         }                                                                                   \
@@ -1705,7 +1706,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         if (dyn->insts[ninst].nat_flags_fusion) {                                           \
             NATIVEJUMP_safe(NATYES, i32);                                                   \
         } else {                                                                            \
-            B##YES##_safe(x1, i32);                                                         \
+            B##YES##_safe(tmp1, i32);                                                       \
         }                                                                                   \
     }
             GOCOND(0x80, "J", "Id");
diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c
index 22dda2ef..d74effaf 100644
--- a/src/dynarec/rv64/dynarec_rv64_functions.c
+++ b/src/dynarec/rv64/dynarec_rv64_functions.c
@@ -812,3 +812,21 @@ void updateNativeFlags(dynarec_rv64_t* dyn)
                 dyn->insts[i].nat_flags_fusion = 0;
         }
 }
+
+void get_free_scratch(dynarec_rv64_t* dyn, int ninst, uint8_t* tmp1, uint8_t* tmp2, uint8_t* tmp3, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t s4, uint8_t s5)
+{
+    uint8_t n1 = dyn->insts[ninst].nat_flags_op1;
+    uint8_t n2 = dyn->insts[ninst].nat_flags_op2;
+    uint8_t tmp[5] = {0};
+    int idx = 0;
+    #define GO(s) if((s!=n1) && (s!=n2)) tmp[idx++] = s
+    GO(s1);
+    GO(s2);
+    GO(s3);
+    GO(s4);
+    GO(s5);
+    #undef GO
+    *tmp1 = tmp[0];
+    *tmp2 = tmp[1];
+    *tmp3 = tmp[2];
+}
\ No newline at end of file
diff --git a/src/dynarec/rv64/dynarec_rv64_functions.h b/src/dynarec/rv64/dynarec_rv64_functions.h
index b61b904a..668c24a9 100644
--- a/src/dynarec/rv64/dynarec_rv64_functions.h
+++ b/src/dynarec/rv64/dynarec_rv64_functions.h
@@ -68,4 +68,5 @@ void fpu_reset_ninst(dynarec_native_t* dyn, int ninst);
 int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st);
 
 void updateNativeFlags(dynarec_rv64_t* dyn);
+void get_free_scratch(dynarec_rv64_t* dyn, int ninst, uint8_t* tmp1, uint8_t* tmp2, uint8_t* tmp3, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t s4, uint8_t s5);
 #endif //__DYNAREC_RV64_FUNCTIONS_H__
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 2127dfec..ee61c13d 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1021,7 +1021,10 @@
 #endif
 
 #ifndef READFLAGS_FUSION
-#define READFLAGS_FUSION(A, checkbarrier) READFLAGS(A)
+#define READFLAGS_FUSION(A, s1, s2, s3, s4, s5)                                                                     \
+    if(dyn->insts[ninst].nat_flags_fusion) get_free_scratch(dyn, ninst, &tmp1, &tmp2, &tmp3, s1, s2, s3, s4, s5);   \
+    else { tmp1=s1; tmp2=s2; tmp3=s3; }                                                                             \
+    READFLAGS(A)
 #endif
 
 #define NAT_FLAGS_OPS(op1, op2)                    \
diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h
index 3747a7e2..3ecaad3e 100644
--- a/src/dynarec/rv64/dynarec_rv64_pass0.h
+++ b/src/dynarec/rv64/dynarec_rv64_pass0.h
@@ -14,7 +14,7 @@
     dyn->f.dfnone = 1;                   \
     dyn->f.pending = SF_SET
 
-#define READFLAGS_FUSION(A, checkbarrier)                                                                       \
+#define READFLAGS_FUSION(A, s1, s2, s3, s4, s5)                                                                 \
     if (box64_dynarec_nativeflags && ninst > 0 && !dyn->insts[ninst - 1].nat_flags_nofusion) {                  \
         if ((A) == (X_ZF))                                                                                      \
             dyn->insts[ninst].nat_flags_fusion = 1;                                                             \
@@ -22,7 +22,6 @@
             dyn->insts[ninst].nat_flags_fusion = 1;                                                             \
         else if (dyn->insts[ninst - 1].nat_flags_sign && ((A) == (X_SF | X_OF) || (A) == (X_SF | X_OF | X_ZF))) \
             dyn->insts[ninst].nat_flags_fusion = 1;                                                             \
-        if (checkbarrier && fpu_needpurgecache(dyn, ninst)) dyn->insts[ninst].nat_flags_fusion = 0;             \
     }                                                                                                           \
     READFLAGS(A);