about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-03-29 10:04:19 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-03-29 10:04:19 +0100
commite7b71cba5fe8ef92cc50266ed380203b7b2ed4ef (patch)
treee307f89f7a5986dc617727a0dd2933a19c6d513f /src
parentd2817e72468bf460c8758f6ee6bdd804cf317f90 (diff)
downloadbox64-e7b71cba5fe8ef92cc50266ed380203b7b2ed4ef.tar.gz
box64-e7b71cba5fe8ef92cc50266ed380203b7b2ed4ef.zip
[ARM64_DYNAREC] Fixed a potential issue with SSE regs when internal jumping to a native call
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_functions.c21
-rw-r--r--src/dynarec/arm64/dynarec_arm64_private.h6
2 files changed, 24 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c
index dbc084dd..6b8013af 100644
--- a/src/dynarec/arm64/dynarec_arm64_functions.c
+++ b/src/dynarec/arm64/dynarec_arm64_functions.c
@@ -65,6 +65,8 @@ void fpu_reset_scratch(dynarec_arm_t* dyn)
     dyn->n.ymm_regs = 0;
     dyn->n.ymm_write = 0;
     dyn->n.ymm_removed = 0;
+    dyn->n.xmm_write = 0;
+    dyn->n.xmm_removed = 0;
 }
 // Get a x87 double reg
 int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n)
@@ -96,6 +98,11 @@ void fpu_free_reg(dynarec_arm_t* dyn, int reg)
         else
             dyn->n.ymm_regs |= ((uint64_t)(reg-EMM0))<<(dyn->n.neoncache[reg].n*4);
     }
+    if(dyn->n.neoncache[reg].t==NEON_CACHE_XMMR || dyn->n.neoncache[reg].t==NEON_CACHE_XMMW) {
+        dyn->n.xmm_removed |= 1<<dyn->n.neoncache[reg].n;
+        if(dyn->n.neoncache[reg].t==NEON_CACHE_XMMW)
+            dyn->n.xmm_write |= 1<<dyn->n.neoncache[reg].n;
+    }
     if(dyn->n.neoncache[reg].t!=NEON_CACHE_ST_F && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_D && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_I64)
         dyn->n.neoncache[reg].v = 0;
     if(dyn->n.fpu_scratch && reg==SCRATCH0+dyn->n.fpu_scratch-1)
@@ -174,6 +181,8 @@ static void fpu_reset_reg_neoncache(neoncache_t* n)
     n->ymm_removed = 0;
     n->ymm_used = 0;
     n->ymm_write = 0;
+    n->xmm_removed = 0;
+    n->xmm_write = 0;
 
 }
 void fpu_reset_reg(dynarec_arm_t* dyn)
@@ -578,7 +587,17 @@ void neoncacheUnwind(neoncache_t* cache)
             cache->fpuused[i] = 0;
         }
     }
-    // add back removed YMM
+    // add back removed XMM
+    if(cache->xmm_removed) {
+        for(int i=0; i<16; ++i)
+            if(cache->xmm_removed&(1<<i)) {
+                int reg = (i<8)?(XMM0+i):(XMM8+i-8);
+                cache->neoncache[reg].t = (cache->xmm_write&(1<<i))?NEON_CACHE_XMMW:NEON_CACHE_XMMR;
+                cache->neoncache[reg].n = i;
+            }
+        cache->xmm_write = cache->xmm_removed = 0;
+    }
+        // add back removed YMM
     if(cache->ymm_removed) {
         for(int i=0; i<16; ++i)
             if(cache->ymm_removed&(1<<i)) {
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index b88a9ad1..740e7e9e 100644
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -72,10 +72,12 @@ typedef struct neoncache_s {
     int8_t              mmxcount;       // number of mmx register used (not both mmx and x87 at the same time)
     int8_t              fpu_scratch;    // scratch counter
     int8_t              fpu_reg;        // x87/sse/mmx reg counter
+    uint16_t            xmm_write;      // 1bit of xmmXX removed write
+    uint16_t            xmm_removed;    // 1bit if xmmXX was removed
     uint16_t            ymm_used;       // mask of the ymm regs used in this opcode
+    uint16_t            ymm_write;      // 1bit of ymmXX removed write
+    uint16_t            ymm_removed;    // 1bit if ymmXX was removed
     uint64_t            ymm_regs;       // 4bits (0-15) position of 16 ymmXX regs removed
-    uint16_t            ymm_write;      // 1bits of ymmXX removed write
-    uint16_t            ymm_removed;    // 1bits if ymmXX was removed
 } neoncache_t;
 
 typedef struct flagcache_s {