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/arm64/dynarec_arm64_db.c6
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c40
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h7
3 files changed, 48 insertions, 5 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_db.c b/src/dynarec/arm64/dynarec_arm64_db.c
index 91d72634..0bcd3de6 100644
--- a/src/dynarec/arm64/dynarec_arm64_db.c
+++ b/src/dynarec/arm64/dynarec_arm64_db.c
@@ -309,10 +309,10 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         }
                         X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
                         // sync top
-                        s0 = x87_stackcount(dyn, ninst, x3);
+                        x87_reflectcount(dyn, ninst, x3, x4);
                         CALL(native_fld, -1);
                         // go back with the top & stack counter
-                        x87_unstackcount(dyn, ninst, x3, s0);
+                        x87_unreflectcount(dyn, ninst, x3, x4);
                     }
                 }
                 break;
@@ -327,7 +327,9 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         x87_forget(dyn, ninst, x1, x3, 0);
                         addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
                         if(ed!=x1) {MOVx_REG(x1, ed);}
+                        x87_reflectcount(dyn, ninst, x3, x4);
                         CALL(native_fstp, -1);
+                        x87_unreflectcount(dyn, ninst, x3, x4);
                     } else {
                         // Painfully long, straight conversion from the C code, shoud be optimized
                         v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index f7428872..313345e8 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -1188,7 +1188,41 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
     }
     MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
 }
-
+void x87_reflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2)
+{
+    // Synch top & stack counter
+    int a = dyn->n.x87stack;
+    if(a) {
+        MESSAGE(LOG_DUMP, "\tSync x87 Count of %d-----\n", a);
+        // Add x87stack to emu fpu_stack
+        LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
+        if(a>0) {
+            ADDw_U12(s2, s2, a);
+        } else {
+            SUBw_U12(s2, s2, -a);
+        }
+        STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
+        // Sub x87stack to top, with and 7
+        LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
+        if(a>0) {
+            SUBw_U12(s2, s2, a);
+        } else {
+            ADDw_U12(s2, s2, -a);
+        }
+        ANDw_mask(s2, s2, 0, 2);  //mask=7
+        STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
+        // update tags
+        LDRH_U12(s1, xEmu, offsetof(x64emu_t, fpu_tags));
+        if(a>0) {
+            LSLw_IMM(s1, s1, a*2);
+        } else {
+            ORRw_mask(s1, s1, 0b010000, 0b001111);  // 0xffff0000
+            LSRw_IMM(s1, s1, -a*2);
+        }
+        STRH_U12(s1, xEmu, offsetof(x64emu_t, fpu_tags));
+        MESSAGE(LOG_DUMP, "\t-----Sync x87 Count\n");
+    }
+}
 static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
 {
     // Synch top & stack counter
@@ -1248,7 +1282,7 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
         }
 }
 
-static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
+void x87_unreflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2)
 {
     // go back with the top & stack counter
     int a = dyn->n.x87stack;
@@ -2504,7 +2538,7 @@ void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
 void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
 {
     // need to undo some things on the x87 tracking
-    x87_unreflectcache(dyn, ninst, s1, s2, s3);
+    x87_unreflectcount(dyn, ninst, s1, s2);
 }
 
 void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4)
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 91349ac9..f5a7104f 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -1404,6 +1404,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define fpu_purgecache  STEPNAME(fpu_purgecache)
 #define mmx_purgecache  STEPNAME(mmx_purgecache)
 #define x87_purgecache  STEPNAME(x87_purgecache)
+#define x87_reflectcount STEPNAME(x87_reflectcount)
+#define x87_unreflectcount STEPNAME(x87_unreflectcount)
 #define fpu_reflectcache STEPNAME(fpu_reflectcache)
 #define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
 #define avx_purge_ymm   STEPNAME(avx_purge_ymm)
@@ -1641,6 +1643,11 @@ void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
 void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
 // purge x87 cache
 void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
+// temporarily set x87 stack count for C functions
+void x87_reflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2);
+// restore count after
+void x87_unreflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2);
+// global fpu helper
 void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
 void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
 void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);