about summary refs log tree commit diff stats
path: root/src/dynarec
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-05-17 08:13:07 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-05-17 08:13:07 +0000
commitbc40c86f10727f447380d37c60c99533eef899bc (patch)
treec1fc13552cca7f6d2822b24a09bc9ca961739d30 /src/dynarec
parentd61f3e79e23ed0c2139361091603fd4dc627bccb (diff)
downloadbox64-bc40c86f10727f447380d37c60c99533eef899bc.tar.gz
box64-bc40c86f10727f447380d37c60c99533eef899bc.zip
[RV64_DYNAREC] Fixed SSE reg Cache when a SSE change type (SS/SD/Vector)
Diffstat (limited to 'src/dynarec')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_functions.c11
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c16
-rw-r--r--src/dynarec/rv64/dynarec_rv64_pass0.h1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_pass1.h1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_private.h10
5 files changed, 38 insertions, 1 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c
index bdb6fc00..7abec870 100644
--- a/src/dynarec/rv64/dynarec_rv64_functions.c
+++ b/src/dynarec/rv64/dynarec_rv64_functions.c
@@ -346,12 +346,21 @@ void extcacheUnwind(extcache_t* cache)
         cache->combined1 = cache->combined2 = 0;
     }
     if(cache->news) {
-        // reove the newly created extcache
+        // remove the newly created extcache
         for(int i=0; i<24; ++i)
             if(cache->news&(1<<i))
                 cache->extcache[i].v = 0;
         cache->news = 0;
     }
+    // add/change bad regs
+    for(int i=0; i<16; ++i) {
+        if(cache->olds[i].changed) {
+            cache->extcache[i].t = cache->olds[i].single?EXT_CACHE_SS:EXT_CACHE_SD;
+        } else if(cache->olds[i].purged) {
+            cache->extcache[i].n = i;
+            cache->extcache[i].t = cache->olds[i].single?EXT_CACHE_SS:EXT_CACHE_SD;
+        }
+    }
     if(cache->stack_push) {
         // unpush
         for(int j=0; j<24; ++j) {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 2743ec71..19caa8b2 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -1306,6 +1306,10 @@ int sse_get_reg(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single)
         // forget / reload if change of size
         if(dyn->e.ssecache[a].single!=single) {
             sse_forget_reg(dyn, ninst, a);
+            // update olds after the forget...
+            dyn->e.olds[a].changed = 1;
+            dyn->e.olds[a].purged = 0;
+            dyn->e.olds[a].single = 1-single;
             return sse_get_reg(dyn, ninst, s1, a, single);
         }
         return dyn->e.ssecache[a].reg;
@@ -1329,6 +1333,10 @@ int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single)
             // need to wipe the half high 32bits of old Double because we now have a single
             //SW(xZR, xEmu, offsetof(x64emu_t, xmm[a])+4);
         }
+        dyn->e.olds[a].changed = 1;
+        dyn->e.olds[a].purged = 0;
+        dyn->e.olds[a].reg = EXTIDX(dyn->e.ssecache[a].reg);
+        dyn->e.olds[a].single = 1-single;
         dyn->e.ssecache[a].single = single;
         dyn->e.extcache[EXTIDX(dyn->e.ssecache[a].reg)].t = single?EXT_CACHE_SS:EXT_CACHE_SD;
         return dyn->e.ssecache[a].reg;
@@ -1347,6 +1355,10 @@ void sse_forget_reg(dynarec_rv64_t* dyn, int ninst, int a)
     else
         FSD(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
     fpu_free_reg(dyn, dyn->e.ssecache[a].reg);
+    dyn->e.olds[a].changed = 0;
+    dyn->e.olds[a].purged = 1;
+    dyn->e.olds[a].reg = dyn->e.ssecache[a].reg;
+    dyn->e.olds[a].single = dyn->e.ssecache[a].single;
     dyn->e.ssecache[a].v = -1;
     return;
 }
@@ -1388,6 +1400,10 @@ static void sse_purgecache(dynarec_rv64_t* dyn, int ninst, int next, int s1)
                 FSD(dyn->e.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
             if(!next) {
                 fpu_free_reg(dyn, dyn->e.ssecache[i].reg);
+                dyn->e.olds[i].changed = 0;
+                dyn->e.olds[i].purged = 1;
+                dyn->e.olds[i].reg = dyn->e.ssecache[i].reg;
+                dyn->e.olds[i].single = dyn->e.ssecache[i].single;
                 dyn->e.ssecache[i].v = -1;
             }
         }
diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h
index debb052f..fc461f0a 100644
--- a/src/dynarec/rv64/dynarec_rv64_pass0.h
+++ b/src/dynarec/rv64/dynarec_rv64_pass0.h
@@ -29,6 +29,7 @@
         dyn->insts[ninst].x64.addr = ip;        \
         dyn->e.combined1 = dyn->e.combined2 = 0;\
         dyn->e.swapped = 0; dyn->e.barrier = 0; \
+        for(int i=0; i<16; ++i) dyn->e.olds[i].v = 0;\
         dyn->insts[ninst].f_entry = dyn->f;     \
         if(ninst) {dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr;}
 
diff --git a/src/dynarec/rv64/dynarec_rv64_pass1.h b/src/dynarec/rv64/dynarec_rv64_pass1.h
index c818c26c..34d0a468 100644
--- a/src/dynarec/rv64/dynarec_rv64_pass1.h
+++ b/src/dynarec/rv64/dynarec_rv64_pass1.h
@@ -5,6 +5,7 @@
 #define NEW_INST                                \
         dyn->insts[ninst].f_entry = dyn->f;     \
         dyn->e.combined1 = dyn->e.combined2 = 0;\
+        for(int i=0; i<16; ++i) dyn->e.olds[i].v = 0;\
         dyn->e.swapped = 0; dyn->e.barrier = 0
 
 #define INST_EPILOG                             \
diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h
index 08182afd..b9cbb2af 100644
--- a/src/dynarec/rv64/dynarec_rv64_private.h
+++ b/src/dynarec/rv64/dynarec_rv64_private.h
@@ -31,6 +31,15 @@ typedef union sse_cache_s {
         uint8_t     single:1;
     };
 } sse_cache_t;
+typedef union sse_old_s {
+    int8_t      v;
+    struct {
+        uint8_t     changed:1;
+        uint8_t     purged:1;
+        uint8_t     reg:4;
+        uint8_t     single:1;
+    };
+} sse_old_t;
 typedef struct extcache_s {
     // ext cache
     ext_cache_t         extcache[24];
@@ -43,6 +52,7 @@ typedef struct extcache_s {
     uint8_t             swapped;        // the combined reg were swapped
     uint8_t             barrier;        // is there a barrier at instruction epilog?
     uint32_t            news;           // bitmask, wich neoncache are new for this opcode
+    sse_old_t           olds[16];       // SSE regs has changed or has been removed
     // fpu cache
     int8_t              x87cache[8];    // cache status for the 8 x87 register behind the fpu stack
     int8_t              x87reg[8];      // reg used for x87cache entry