about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-03-18 04:58:29 +0800
committerGitHub <noreply@github.com>2025-03-17 21:58:29 +0100
commit546238681eb8d5b3d80cf1d77075dcbff82de72a (patch)
tree7bb747bde4005a9742f48f29122858cfaf948fa4 /src
parent87327b182f6fd6eefd2620e0b1775e3fedd33459 (diff)
downloadbox64-546238681eb8d5b3d80cf1d77075dcbff82de72a.tar.gz
box64-546238681eb8d5b3d80cf1d77075dcbff82de72a.zip
[RV64_DYNAREC] More minor changes and fixes to x87 opcodes (#2443)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_da.c36
-rw-r--r--src/dynarec/rv64/dynarec_rv64_db.c66
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dd.c11
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c37
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h4
5 files changed, 63 insertions, 91 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_da.c b/src/dynarec/rv64/dynarec_rv64_da.c
index 165ae3c8..97058a60 100644
--- a/src/dynarec/rv64/dynarec_rv64_da.c
+++ b/src/dynarec/rv64/dynarec_rv64_da.c
@@ -45,14 +45,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
     if (MODREG)
         switch (nextop) {
-            case 0xC0:
-            case 0xC1:
-            case 0xC2:
-            case 0xC3:
-            case 0xC4:
-            case 0xC5:
-            case 0xC6:
-            case 0xC7:
+            case 0xC0 ... 0xC7:
                 INST_NAME("FCMOVB ST0, STx");
                 READFLAGS(X_CF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -64,14 +57,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 else
                     FMVD(v1, v2);
                 break;
-            case 0xC8:
-            case 0xC9:
-            case 0xCA:
-            case 0xCB:
-            case 0xCC:
-            case 0xCD:
-            case 0xCE:
-            case 0xCF:
+            case 0xC8 ... 0xCF:
                 INST_NAME("FCMOVE ST0, STx");
                 READFLAGS(X_ZF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -83,14 +69,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 else
                     FMVD(v1, v2);
                 break;
-            case 0xD0:
-            case 0xD1:
-            case 0xD2:
-            case 0xD3:
-            case 0xD4:
-            case 0xD5:
-            case 0xD6:
-            case 0xD7:
+            case 0xD0 ... 0xD7:
                 INST_NAME("FCMOVBE ST0, STx");
                 READFLAGS(X_CF | X_ZF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -102,14 +81,7 @@ uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 else
                     FMVD(v1, v2);
                 break;
-            case 0xD8:
-            case 0xD9:
-            case 0xDA:
-            case 0xDB:
-            case 0xDC:
-            case 0xDD:
-            case 0xDE:
-            case 0xDF:
+            case 0xD8 ... 0xDF:
                 INST_NAME("FCMOVU ST0, STx");
                 READFLAGS(X_PF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
diff --git a/src/dynarec/rv64/dynarec_rv64_db.c b/src/dynarec/rv64/dynarec_rv64_db.c
index 45fcd1e0..3aa4b9b2 100644
--- a/src/dynarec/rv64/dynarec_rv64_db.c
+++ b/src/dynarec/rv64/dynarec_rv64_db.c
@@ -46,14 +46,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
     if (MODREG)
         switch (nextop) {
-            case 0xC0:
-            case 0xC1:
-            case 0xC2:
-            case 0xC3:
-            case 0xC4:
-            case 0xC5:
-            case 0xC6:
-            case 0xC7:
+            case 0xC0 ... 0xC7:
                 INST_NAME("FCMOVNB ST0, STx");
                 READFLAGS(X_CF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -66,14 +59,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     FMVD(v1, v2); // F_CF==0
                 }
                 break;
-            case 0xC8:
-            case 0xC9:
-            case 0xCA:
-            case 0xCB:
-            case 0xCC:
-            case 0xCD:
-            case 0xCE:
-            case 0xCF:
+            case 0xC8 ... 0xCF:
                 INST_NAME("FCMOVNE ST0, STx");
                 READFLAGS(X_ZF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -86,14 +72,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     FMVD(v1, v2); // F_ZF==0
                 }
                 break;
-            case 0xD0:
-            case 0xD1:
-            case 0xD2:
-            case 0xD3:
-            case 0xD4:
-            case 0xD5:
-            case 0xD6:
-            case 0xD7:
+            case 0xD0 ... 0xD7:
                 INST_NAME("FCMOVNBE ST0, STx");
                 READFLAGS(X_CF | X_ZF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -106,14 +85,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     FMVD(v1, v2); // F_CF==0 & F_ZF==0
                 }
                 break;
-            case 0xD8:
-            case 0xD9:
-            case 0xDA:
-            case 0xDB:
-            case 0xDC:
-            case 0xDD:
-            case 0xDE:
-            case 0xDF:
+            case 0xD8 ... 0xDF:
                 INST_NAME("FCMOVNU ST0, STx");
                 READFLAGS(X_PF);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -143,14 +115,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 x87_purgecache(dyn, ninst, 0, x1, x2, x3);
                 CALL(reset_fpu, -1, 0, 0);
                 break;
-            case 0xE8:
-            case 0xE9:
-            case 0xEA:
-            case 0xEB:
-            case 0xEC:
-            case 0xED:
-            case 0xEE:
-            case 0xEF:
+            case 0xE8 ... 0xEF:
                 INST_NAME("FUCOMI ST0, STx");
                 SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -162,14 +127,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
 
                 break;
-            case 0xF0:
-            case 0xF1:
-            case 0xF2:
-            case 0xF3:
-            case 0xF4:
-            case 0xF5:
-            case 0xF6:
-            case 0xF7:
+            case 0xF0 ... 0xF7:
                 INST_NAME("FCOMI ST0, STx");
                 SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
                 v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
@@ -234,12 +192,14 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
                 MARK2;
                 SW(x4, wback, fixedaddress);
+                x87_restoreround(dyn, ninst, u8);
                 X87_POP_OR_FAIL(dyn, ninst, x3);
                 break;
             case 5:
                 INST_NAME("FLD tbyte");
                 addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0);
                 if ((PK(0) == 0xDB && ((PK(1) >> 3) & 7) == 7) || (!rex.is32bits && PK(0) >= 0x40 && PK(0) <= 0x4f && PK(1) == 0xDB && ((PK(2) >> 3) & 7) == 7)) {
+                    NOTEST(x5);
                     // the FLD is immediatly followed by an FSTP
                     LD(x5, ed, fixedaddress + 0);
                     LH(x6, ed, fixedaddress + 8);
@@ -262,11 +222,9 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     } else {
                         ADDI(x1, ed, fixedaddress);
                         X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
-                        // sync top
-                        s0 = x87_stackcount(dyn, ninst, x3);
+                        x87_reflectcount(dyn, ninst, x3, x4);
                         CALL(native_fld, -1, x1, 0);
-                        // go back with the top & stack counter
-                        x87_unstackcount(dyn, ninst, x3, s0);
+                        x87_unreflectcount(dyn, ninst, x3, x4);
                     }
                 }
                 break;
@@ -279,9 +237,9 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 } else {
                     x87_forget(dyn, ninst, x1, x3, 0);
                     addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
-                    s0 = x87_stackcount(dyn, ninst, x3);
+                    x87_reflectcount(dyn, ninst, x3, x4);
                     CALL(native_fstp, -1, ed, 0);
-                    x87_unstackcount(dyn, ninst, x3, s0);
+                    x87_unreflectcount(dyn, ninst, x3, x4);
                 }
                 X87_POP_OR_FAIL(dyn, ninst, x3);
                 break;
diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c
index 4a1e527d..c21030ca 100644
--- a/src/dynarec/rv64/dynarec_rv64_dd.c
+++ b/src/dynarec/rv64/dynarec_rv64_dd.c
@@ -45,11 +45,20 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     if (MODREG)
         switch (nextop) {
             case 0xC0 ... 0xC7:
-                INST_NAME("FFREE STx");
+#if 1
+                if ((nextop & 7) == 0 && PK(0) == 0xD9 && PK(1) == 0xF7) {
+                    MESSAGE(LOG_DUMP, "Hack for FFREE ST0 / FINCSTP\n");
+                    x87_do_pop(dyn, ninst, x1);
+                    addr += 2;
+                    SKIPTEST(x1);
+                } else
+                    x87_free(dyn, ninst, x1, x2, x3, nextop & 7);
+#else
                 MESSAGE(LOG_DUMP, "Need Optimization\n");
                 x87_purgecache(dyn, ninst, 0, x1, x2, x3);
                 MOV32w(x1, nextop & 7);
                 CALL(fpu_do_free, -1, x1, 0);
+#endif
                 break;
             case 0xD0 ... 0xD7:
                 INST_NAME("FST ST0, STx");
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 4f3286fa..31b35811 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -1166,6 +1166,35 @@ void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, in
     MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
 }
 
+
+void x87_reflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2)
+{
+    // Synch top and stack count
+    int a = dyn->e.x87stack;
+    if (a) {
+        MESSAGE(LOG_DUMP, "\tSync x87 Count of %d-----\n", a);
+        // Add x87stack to emu fpu_stack
+        LW(s2, xEmu, offsetof(x64emu_t, fpu_stack));
+        ADDI(s2, s2, a);
+        SW(s2, xEmu, offsetof(x64emu_t, fpu_stack));
+        // Sub x87stack to top, with and 7
+        LW(s2, xEmu, offsetof(x64emu_t, top));
+        SUBI(s2, s2, a);
+        ANDI(s2, s2, 7);
+        SW(s2, xEmu, offsetof(x64emu_t, top));
+        // update tags
+        LH(s1, xEmu, offsetof(x64emu_t, fpu_tags));
+        if (a > 0) {
+            SLLI(s1, s1, a * 2);
+        } else {
+            MOV32w(s2, 0xffff0000);
+            OR(s1, s1, s2);
+            SRLI(s1, s1, -a * 2);
+        }
+        SH(s1, xEmu, offsetof(x64emu_t, fpu_tags));
+    }
+}
+
 static void x87_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3)
 {
     // Sync top and stack count
@@ -1221,7 +1250,7 @@ static void x87_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int
         }
 }
 
-static void x87_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3)
+void x87_unreflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2)
 {
     // revert top and stack count
     int a = dyn->e.x87stack;
@@ -1238,8 +1267,8 @@ static void x87_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, i
         // update tags
         LH(s1, xEmu, offsetof(x64emu_t, fpu_tags));
         if (a > 0) {
-            MOV32w(s3, 0xffff0000);
-            OR(s1, s1, s3);
+            MOV32w(s2, 0xffff0000);
+            OR(s1, s1, s2);
             SRLI(s1, s1, a * 2);
         } else {
             SLLI(s1, s1, -a * 2);
@@ -2847,7 +2876,7 @@ void fpu_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3)
 void fpu_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3)
 {
     // need to undo the top and stack tracking that must not be reflected permanently yet
-    x87_unreflectcache(dyn, ninst, s1, s2, s3);
+    x87_unreflectcount(dyn, ninst, s1, s2);
 }
 
 void emit_pf(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4)
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 1183feb7..684357bf 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1391,6 +1391,8 @@ void* rv64_next(void);
 #define sse_purgecache      STEPNAME(sse_purgecache)
 #define fpu_reflectcache    STEPNAME(fpu_reflectcache)
 #define fpu_unreflectcache  STEPNAME(fpu_unreflectcache)
+#define x87_reflectcount    STEPNAME(x87_reflectcount)
+#define x87_unreflectcount  STEPNAME(x87_unreflectcount)
 #define avx_purge_ymm       STEPNAME(avx_purge_ymm)
 
 #define CacheTransform STEPNAME(CacheTransform)
@@ -1647,6 +1649,8 @@ void mmx_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1);
 void x87_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1, int s2, int s3);
 void fpu_reflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3);
 void fpu_unreflectcache(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3);
+void x87_reflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2);
+void x87_unreflectcount(dynarec_rv64_t* dyn, int ninst, int s1, int s2);
 void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07);
 void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07);