about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-02-11 11:52:58 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-02-11 11:52:58 +0100
commita69e81f0345b5e317e08faa010325c9a01232d09 (patch)
tree7e39461036e935382ee051688120d425eab842a3 /src
parent5c01fbabac658d7d567efdff333a10bb2be5ca09 (diff)
downloadbox64-a69e81f0345b5e317e08faa010325c9a01232d09.tar.gz
box64-a69e81f0345b5e317e08faa010325c9a01232d09.zip
[ARM64_DYNAREC] Improved FFREE/FXAM opcodes (helps 32bits games like SeriousSam2)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_d9.c10
-rw-r--r--src/dynarec/arm64/dynarec_arm64_dd.c11
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c11
3 files changed, 29 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_d9.c b/src/dynarec/arm64/dynarec_arm64_d9.c
index c97b2410..f0fa18ac 100644
--- a/src/dynarec/arm64/dynarec_arm64_d9.c
+++ b/src/dynarec/arm64/dynarec_arm64_d9.c
@@ -160,8 +160,16 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     }
                     ANDw_mask(x4, x4, 0, 3);    // (emu->top + i)&7
                 }
+                // load tag
+                ADDx_U12(x1, xEmu, offsetof(x64emu_t, p_regs));
+                LDRw_REG_LSL2(x3, x1, x2);
+                CMPSw_U12(x3, 0b11);    // empty
+                MOV32w(x3, 0b100000100000000);
+                CSELx(x4, x3, x4, cEQ); // empty: C3,C2,C0 = 101
+                B_MARK3(cEQ);
+                // load x2 with ST0 anyway, for sign extraction
                 ADDx_REG_LSL(x1, xEmu, x4, 3);
-                LDRx_U12(x2, x1, offsetof(x64emu_t, x87)); // load x2 with ST0 anyway, for sign extraction
+                LDRx_U12(x2, x1, offsetof(x64emu_t, x87));
             } else {
                 // simply move from cache reg to x2
                 v1 = dyn->n.x87reg[i1];
diff --git a/src/dynarec/arm64/dynarec_arm64_dd.c b/src/dynarec/arm64/dynarec_arm64_dd.c
index 89221653..42a6f634 100644
--- a/src/dynarec/arm64/dynarec_arm64_dd.c
+++ b/src/dynarec/arm64/dynarec_arm64_dd.c
@@ -51,10 +51,21 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xC6:
         case 0xC7:
             INST_NAME("FFREE STx");
+            #if 1
+            x87_forget(dyn, ninst, x1, x2, nextop&7);
+            // empty tags
+            MOVZw(x3, 0b11);
+            ADDx_U12(x1, xEmu, offsetof(x64emu_t, p_regs));
+            LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
+            ADDw_U12(x2, x2, nextop&7);
+            ANDw_mask(x2, x2, 0, 2);    // mask=7
+            STRw_REG_LSL2(x3, x1, x2);
+            #else
             MESSAGE(LOG_DUMP, "Need Optimization\n");
             x87_purgecache(dyn, ninst, 0, x1, x2, x3);
             MOV32w(x1, nextop&7);
             CALL(fpu_do_free, -1);
+            #endif
             break;
         case 0xD0:
         case 0xD1:
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index cf737369..88008fe8 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -1014,7 +1014,13 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
             }
         }
 }
-
+static int x87_is_stcached(dynarec_arm_t* dyn, int st)
+{
+    for (int i=0; i<8; ++i)
+        if(dyn->n.x87cache[i] == st)
+            return 1;
+    return 0;
+}
 void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3)
 {
     int ret = 0;
@@ -1047,7 +1053,8 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
             for (int i=0; i<a; ++i) {
                 SUBw_U12(s2, s2, 1);
                 ANDw_mask(s2, s2, 0, 2); //mask=7    // (emu->top + st)&7
-                STRw_REG_LSL2(s3, s1, s2);
+                if(x87_is_stcached(dyn, i)) // to handle ffree
+                    STRw_REG_LSL2(s3, s1, s2);
             }
         } else {
             // empty tags