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/dynarec_arch.h13
-rw-r--r--src/dynarec/la64/dynarec_la64_functions.c67
-rw-r--r--src/dynarec/la64/dynarec_la64_functions.h3
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.c19
-rw-r--r--src/dynarec/la64/dynarec_la64_pass0.h13
-rw-r--r--src/dynarec/la64/dynarec_la64_pass1.h12
-rw-r--r--src/dynarec/rv64/dynarec_rv64_functions.c2
-rw-r--r--src/include/dynarec_la64.h10
-rw-r--r--src/include/dynarec_rv64.h10
9 files changed, 103 insertions, 46 deletions
diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h
index 26207428..f89125a7 100644
--- a/src/dynarec/dynarec_arch.h
+++ b/src/dynarec/dynarec_arch.h
@@ -22,16 +22,17 @@
 #define instruction_native_t        instruction_la64_t

 #define dynarec_native_t            dynarec_la64_t

 

-#define ADDITIONNAL_DEFINITION()

+#define ADDITIONNAL_DEFINITION() \

+    int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);

 

-// TODO

-#define OTHER_CACHE()

+#define OTHER_CACHE() \

+    if (fpuCacheNeedsTransform(dyn, ninst)) ret |= 2;

 

 #include "la64/la64_printer.h"

 #include "la64/dynarec_la64_private.h"

 #include "la64/dynarec_la64_functions.h"

-// TODO

-#define MAXBLOCK_SIZE ((1<<19)-200)

+// Limit here is unconditionnal jump, that is signed 28bits

+#define MAXBLOCK_SIZE ((1 << 27) - 200)

 #elif defined(RV64)

 

 #define instruction_native_t        instruction_rv64_t

@@ -46,7 +47,7 @@
 #include "rv64/rv64_printer.h"

 #include "rv64/dynarec_rv64_private.h"

 #include "rv64/dynarec_rv64_functions.h"

-// Limit here is unconditionnal jump, thjat is signed 21bits

+// Limit here is unconditionnal jump, that is signed 21bits

 #define MAXBLOCK_SIZE ((1<<20)-200)

 #else

 #error Unsupported platform

diff --git a/src/dynarec/la64/dynarec_la64_functions.c b/src/dynarec/la64/dynarec_la64_functions.c
index 01eaee06..7568b453 100644
--- a/src/dynarec/la64/dynarec_la64_functions.c
+++ b/src/dynarec/la64/dynarec_la64_functions.c
@@ -20,7 +20,7 @@
 #include "emu/x87emu_private.h"
 #include "x64trace.h"
 #include "signals.h"
-#include "dynarec_la64.h"
+#include "dynarec_native.h"
 #include "dynarec_la64_private.h"
 #include "dynarec_la64_functions.h"
 #include "custommem.h"
@@ -82,6 +82,71 @@ void fpu_reset_reg(dynarec_la64_t* dyn)
     fpu_reset_reg_lsxcache(&dyn->lsx);
 }
 
+static int isCacheEmpty(dynarec_native_t* dyn, int ninst)
+{
+    if (dyn->insts[ninst].lsx.stack_next) {
+        return 0;
+    }
+    for (int i = 0; i < 24; ++i)
+        if (dyn->insts[ninst].lsx.lsxcache[i].v) { // there is something at ninst for i
+            if (!(
+                    (dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_F
+                        || dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_D
+                        || dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_I64)
+                    && dyn->insts[ninst].lsx.lsxcache[i].n < dyn->insts[ninst].lsx.stack_pop))
+                return 0;
+        }
+    return 1;
+}
+
+int fpuCacheNeedsTransform(dynarec_la64_t* dyn, int ninst)
+{
+    int i2 = dyn->insts[ninst].x64.jmp_insts;
+    if (i2 < 0)
+        return 1;
+    if ((dyn->insts[i2].x64.barrier & BARRIER_FLOAT))
+        // if the barrier as already been apply, no transform needed
+        return ((dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) ? 0 : (isCacheEmpty(dyn, ninst) ? 0 : 1);
+    int ret = 0;
+    if (!i2) { // just purge
+        if (dyn->insts[ninst].lsx.stack_next) {
+            return 1;
+        }
+        for (int i = 0; i < 24 && !ret; ++i)
+            if (dyn->insts[ninst].lsx.lsxcache[i].v) { // there is something at ninst for i
+                if (!(
+                        (dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_F
+                            || dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_D
+                            || dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_I64)
+                        && dyn->insts[ninst].lsx.lsxcache[i].n < dyn->insts[ninst].lsx.stack_pop))
+                    ret = 1;
+            }
+        return ret;
+    }
+    // Check if ninst can be compatible to i2
+    if (dyn->insts[ninst].lsx.stack_next != dyn->insts[i2].lsx.stack - dyn->insts[i2].lsx.stack_push) {
+        return 1;
+    }
+    lsxcache_t cache_i2 = dyn->insts[i2].lsx;
+    lsxcacheUnwind(&cache_i2);
+
+    for (int i = 0; i < 24; ++i) {
+        if (dyn->insts[ninst].lsx.lsxcache[i].v) { // there is something at ninst for i
+            if (!cache_i2.lsxcache[i].v) {         // but there is nothing at i2 for i
+                ret = 1;
+            } else if (dyn->insts[ninst].lsx.lsxcache[i].v != cache_i2.lsxcache[i].v) { // there is something different
+                if (dyn->insts[ninst].lsx.lsxcache[i].n != cache_i2.lsxcache[i].n) {    // not the same x64 reg
+                    ret = 1;
+                } else if (dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_XMMR && cache_i2.lsxcache[i].t == LSX_CACHE_XMMW) { /* nothing */
+                } else
+                    ret = 1;
+            }
+        } else if (cache_i2.lsxcache[i].v)
+            ret = 1;
+    }
+    return ret;
+}
+
 void lsxcacheUnwind(lsxcache_t* cache)
 {
     if (cache->swapped) {
diff --git a/src/dynarec/la64/dynarec_la64_functions.h b/src/dynarec/la64/dynarec_la64_functions.h
index 2badba4d..b674983f 100644
--- a/src/dynarec/la64/dynarec_la64_functions.h
+++ b/src/dynarec/la64/dynarec_la64_functions.h
@@ -19,6 +19,9 @@ void fpu_free_reg(dynarec_la64_t* dyn, int reg);
 // Reset fpu regs counter
 void fpu_reset_reg(dynarec_la64_t* dyn);
 
+// FPU Cache transformation (for loops) // Specific, need to be written by backend
+int fpuCacheNeedsTransform(dynarec_la64_t* dyn, int ninst);
+
 // Undo the changes of a lsxcache to get the status before the instruction
 void lsxcacheUnwind(lsxcache_t* cache);
 
diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c
index 917b0d6c..8965002d 100644
--- a/src/dynarec/la64/dynarec_la64_helper.c
+++ b/src/dynarec/la64/dynarec_la64_helper.c
@@ -10,6 +10,7 @@
 #include "dynarec.h"
 #include "emu/x64emu_private.h"
 #include "emu/x64run_private.h"
+#include "la64_emitter.h"
 #include "x64run.h"
 #include "x64emu.h"
 #include "box64stack.h"
@@ -25,6 +26,8 @@
 #include "dynarec_la64_functions.h"
 #include "dynarec_la64_helper.h"
 
+#define SCRATCH 31
+
 static uintptr_t geted_32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, int* l, int i12);
 
 /* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
@@ -848,7 +851,6 @@ static void swapCache(dynarec_la64_t* dyn, int ninst, int i, int j, lsxcache_t*
     MESSAGE(LOG_DUMP, "\t  - Swapping %d <-> %d\n", i, j);
     // There is no VSWP in Arm64 NEON to swap 2 register contents!
     // so use a scratch...
-#define SCRATCH 31
     if (quad) {
         VOR_V(SCRATCH, i, i);
         VOR_V(i, j, j);
@@ -861,7 +863,6 @@ static void swapCache(dynarec_la64_t* dyn, int ninst, int i, int j, lsxcache_t*
         VXOR_V(j, j, j);
         VEXTRINS_D(j, SCRATCH, 0);
     }
-#undef SCRATCH
     tmp.v = cache->lsxcache[i].v;
     cache->lsxcache[i].v = cache->lsxcache[j].v;
     cache->lsxcache[j].v = tmp.v;
@@ -895,7 +896,9 @@ static void loadCache(dynarec_la64_t* dyn, int ninst, int stack_cnt, int s1, int
             break;
         case LSX_CACHE_MM:
             MESSAGE(LOG_DUMP, "\t  - Loading %s\n", getCacheName(t, n));
-            VLD(i, xEmu, offsetof(x64emu_t, mmx[n]));
+            FLD_D(SCRATCH, xEmu, offsetof(x64emu_t, mmx[n]));
+            VXOR_V(i, i, i);
+            VEXTRINS_D(i, SCRATCH, 0);
             break;
         case LSX_CACHE_ST_D:
         case LSX_CACHE_ST_F:
@@ -925,7 +928,7 @@ static void unloadCache(dynarec_la64_t* dyn, int ninst, int stack_cnt, int s1, i
             break;
         case LSX_CACHE_MM:
             MESSAGE(LOG_DUMP, "\t  - Unloading %s\n", getCacheName(t, n));
-            VST(i, xEmu, offsetof(x64emu_t, mmx[n]));
+            FST_D(i, xEmu, offsetof(x64emu_t, mmx[n]));
             break;
         case LSX_CACHE_ST_D:
         case LSX_CACHE_ST_F:
@@ -1070,7 +1073,7 @@ static void flagsCacheTransform(dynarec_la64_t* dyn, int ninst, int s1)
     if(dyn->f.dfnone)  // flags are fully known, nothing we can do more
         return;
     MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
-    int go = 0;
+    int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
     switch (dyn->insts[jmp].f_entry.pending) {
         case SF_UNKNOWN: break;
         case SF_SET:
@@ -1088,12 +1091,10 @@ static void flagsCacheTransform(dynarec_la64_t* dyn, int ninst, int s1)
             && dyn->f.pending!=SF_SET_PENDING
             && dyn->f.pending!=SF_PENDING)
                 go = 1;
-            else
-                go = (dyn->insts[jmp].f_entry.dfnone  == dyn->f.dfnone)?0:1;
+            else if (dyn->insts[jmp].f_entry.dfnone !=dyn->f.dfnone)
+                go = 1;
             break;
     }
-    if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
-        go = 1;
     if(go) {
         if(dyn->f.pending!=SF_PENDING) {
             LD_W(s1, xEmu, offsetof(x64emu_t, df));
diff --git a/src/dynarec/la64/dynarec_la64_pass0.h b/src/dynarec/la64/dynarec_la64_pass0.h
index 1eef76bf..99a897a6 100644
--- a/src/dynarec/la64/dynarec_la64_pass0.h
+++ b/src/dynarec/la64/dynarec_la64_pass0.h
@@ -24,14 +24,17 @@
     } else                                         \
         dyn->insts[ninst].barrier_maybe = 1
 #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
-#define NEW_INST                                                                                                  \
-    ++dyn->size;                                                                                                  \
-    memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t));                                                  \
-    dyn->insts[ninst].x64.addr = ip;                                                                              \
-    dyn->insts[ninst].f_entry = dyn->f;                                                                           \
+#define NEW_INST                                 \
+    ++dyn->size;                                 \
+    dyn->insts[ninst].x64.addr = ip;             \
+    dyn->lsx.combined1 = dyn->lsx.combined2 = 0; \
+    dyn->lsx.swapped = 0;                        \
+    dyn->lsx.barrier = 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; }
 #define INST_EPILOG                    \
     dyn->insts[ninst].f_exit = dyn->f; \
+    dyn->insts[ninst].lsx = dyn->lsx;  \
     dyn->insts[ninst].x64.has_next = (ok > 0) ? 1 : 0;
 #define INST_NAME(name)
 #define DEFAULT                                                                                                                                     \
diff --git a/src/dynarec/la64/dynarec_la64_pass1.h b/src/dynarec/la64/dynarec_la64_pass1.h
index 7d616b22..af69ceca 100644
--- a/src/dynarec/la64/dynarec_la64_pass1.h
+++ b/src/dynarec/la64/dynarec_la64_pass1.h
@@ -2,10 +2,14 @@
 #define FINI
 #define MESSAGE(A, ...)
 #define EMIT(A)
-#define NEW_INST \
-    dyn->insts[ninst].f_entry = dyn->f;
+#define NEW_INST                                 \
+    dyn->insts[ninst].f_entry = dyn->f;          \
+    dyn->lsx.combined1 = dyn->lsx.combined2 = 0; \
+    dyn->lsx.swapped = 0;                        \
+    dyn->lsx.barrier = 0
 
-#define INST_EPILOG \
+#define INST_EPILOG                   \
+    dyn->insts[ninst].lsx = dyn->lsx; \
     dyn->insts[ninst].f_exit = dyn->f
 
-#define INST_NAME(name)
\ No newline at end of file
+#define INST_NAME(name)
diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c
index b016e45b..9965b438 100644
--- a/src/dynarec/rv64/dynarec_rv64_functions.c
+++ b/src/dynarec/rv64/dynarec_rv64_functions.c
@@ -20,7 +20,7 @@
 #include "emu/x87emu_private.h"
 #include "x64trace.h"
 #include "signals.h"
-#include "dynarec_rv64.h"
+#include "dynarec_native.h"
 #include "dynarec_rv64_private.h"
 #include "dynarec_rv64_functions.h"
 #include "custommem.h"
diff --git a/src/include/dynarec_la64.h b/src/include/dynarec_la64.h
deleted file mode 100644
index cf8946f0..00000000
--- a/src/include/dynarec_la64.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __DYNAREC_LA64_H_
-#define __DYNAREC_LA64_H_
-
-typedef struct dynablock_s dynablock_t;
-typedef struct x64emu_s x64emu_t;
-
-void CancelBlock64(void);
-void* FillBlock64(dynablock_t* block, uintptr_t addr);
-
-#endif //__DYNAREC_LA64_H_
\ No newline at end of file
diff --git a/src/include/dynarec_rv64.h b/src/include/dynarec_rv64.h
deleted file mode 100644
index dd3b734e..00000000
--- a/src/include/dynarec_rv64.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __DYNAREC_RV64_H_
-#define __DYNAREC_RV64_H_
-
-typedef struct dynablock_s dynablock_t;
-typedef struct x64emu_s x64emu_t;
-
-void CancelBlock64(void);
-void* FillBlock64(dynablock_t* block, uintptr_t addr);
-
-#endif //__DYNAREC_RV64_H_
\ No newline at end of file