about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-03-15 19:11:19 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-03-15 19:11:19 +0000
commitf64d21e8c294f3160ec0493f69affb2ad695e4d8 (patch)
tree84de2ae531f857de113eeb90d05f4af2ae0cd34f /src
parentd5284a570430af9ea1666c87b2da70e7c0e97ad4 (diff)
downloadbox64-f64d21e8c294f3160ec0493f69affb2ad695e4d8.tar.gz
box64-f64d21e8c294f3160ec0493f69affb2ad695e4d8.zip
[RV64_DYNAREC] Implemented a solutionfor the problematic F_OF flag (use F_OF2 now)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_math.c2
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h54
-rw-r--r--src/dynarec/rv64/rv64_emitter.h3
-rw-r--r--src/dynarec/rv64/rv64_epilog.S6
-rw-r--r--src/dynarec/rv64/rv64_prolog.S5
6 files changed, 68 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c
index 51491555..c151cfab 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_math.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c
@@ -98,7 +98,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
             XOR(s3, s3, s4);
             ANDI(s3, s3, 1); // OF: xor of two MSB's of cc
             BEQZ(s3, 4);
-            ORI(xFlags, xFlags, 1 << F_OF);
+            ORI(xFlags, xFlags, 1 << F_OF2);
         }
     }
     IFX(X_SF) {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index f44a7ffe..36800a31 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -245,6 +245,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav
     if(savereg==0)
         savereg = x6;
     if(saveflags) {
+        FLAGS_ADJUST_TO11(xFlags, reg);
         SD(xFlags, xEmu, offsetof(x64emu_t, eflags));
     }
     fpu_pushcache(dyn, ninst, reg, 0);
@@ -288,6 +289,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav
     fpu_popcache(dyn, ninst, reg, 0);
     if(saveflags) {
         LD(xFlags, xEmu, offsetof(x64emu_t, eflags));
+        FLAGS_ADJUST_FROM11(xFlags, reg);
     }
     SET_NODF();
     dyn->last_ip = 0;
@@ -296,6 +298,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav
 void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w)
 {
     MAYUSE(fnc);
+    FLAGS_ADJUST_TO11(xFlags, x3);
     SD(xFlags, xEmu, offsetof(x64emu_t, eflags));
     fpu_pushcache(dyn, ninst, x3, 1);
     // x5..x8, x10..x17, x28..x31 those needs to be saved by caller
@@ -351,6 +354,7 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w)
 
     fpu_popcache(dyn, ninst, x3, 1);
     LD(xFlags, xEmu, offsetof(x64emu_t, eflags));
+    FLAGS_ADJUST_FROM11(xFlags, x3);
     SET_NODF();
 }
 
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index a38fdf46..c50a3e20 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -176,7 +176,7 @@
 #define SET_NODF()          dyn->f.dfnone = 0
 #define SET_DFOK()          dyn->f.dfnone = 1
 
-#define CLEAR_FLAGS() IFX(X_ALL) {ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_CF) | (1UL<<F_OF) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF)));}
+#define CLEAR_FLAGS() IFX(X_ALL) {ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_CF) | (1UL<<F_OF2) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF)));}
 
 #define CALC_SUB_FLAGS(op1_, op2, res, scratch1, scratch2, width)         \
     IFX(X_AF | X_CF | X_OF) {                                             \
@@ -210,22 +210,61 @@
             XOR(scratch1, scratch1, scratch2);                            \
             ANDI(scratch1, scratch1, 1);                                  \
             BEQZ(scratch1, 4);                                            \
-            ORI(xFlags, xFlags, 1 << F_OF);                               \
+            ORI(xFlags, xFlags, 1 << F_OF2);                              \
         }                                                                 \
     }
 
+// Adjust the xFlags bit 11 -> bit 5, result in reg (can be xFlags, but not s1)
+#define FLAGS_ADJUST_FROM11(reg, s1)\
+    ANDI(reg, xFlags, ~(1<<5));     \
+    SRLI(s1, reg, 11-5);            \
+    ANDI(s1, s1, 1<<5);             \
+    OR(reg, reg, s1)
+
+// Adjust the xFlags bit 5 -> bit 11, source in reg (can be xFlags, but not s1)
+#define FLAGS_ADJUST_TO11(reg, s1)  \
+    MOV64x(s1, ~(1<<11));           \
+    AND(xFlags, reg, s1);           \
+    ANDI(s1, xFlags, 1<<5);         \
+    SLLI(s1, s1, 11-5);             \
+    OR(xFlags, xFlags, s1)
+
 #ifndef MAYSETFLAGS
 #define MAYSETFLAGS()
 #endif
 
 #ifndef READFLAGS
 #define READFLAGS(A) \
-
+    if(((A)!=X_PEND && dyn->f.pending!=SF_SET)          \
+    && (dyn->f.pending!=SF_SET_PENDING)) {              \
+        if(dyn->f.pending!=SF_PENDING) {                \
+            LD(x3, xEmu, offsetof(x64emu_t, df));       \
+            j64 = (GETMARKF)-(dyn->native_size);        \
+            BEQ(x3, xZR, j64);                          \
+        }                                               \
+        CALL_(UpdateFlags, -1, 0);                      \
+        FLAGS_ADJUST_FROM11(xFlags, x3);                \
+        MARKF;                                          \
+        dyn->f.pending = SF_SET;                        \
+        SET_DFOK();                                     \
+    }
 #endif
 
 #ifndef SETFLAGS
 #define SETFLAGS(A, B)                                                                          \
-
+    if(dyn->f.pending!=SF_SET                                                                   \
+    && ((B)&SF_SUB)                                                                             \
+    && (dyn->insts[ninst].x64.gen_flags&(~(A))))                                                \
+        READFLAGS(((dyn->insts[ninst].x64.gen_flags&X_PEND)?X_ALL:dyn->insts[ninst].x64.gen_flags)&(~(A)));\
+    if(dyn->insts[ninst].x64.gen_flags) switch(B) {                                             \
+        case SF_SUBSET:                                                                         \
+        case SF_SET: dyn->f.pending = SF_SET; break;                                            \
+        case SF_PENDING: dyn->f.pending = SF_PENDING; break;                                    \
+        case SF_SUBSET_PENDING:                                                                 \
+        case SF_SET_PENDING:                                                                    \
+            dyn->f.pending = (dyn->insts[ninst].x64.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET;    \
+            break;                                                                              \
+    } else dyn->f.pending = SF_SET
 #endif
 #ifndef JUMP
 #define JUMP(A, C)
@@ -236,7 +275,12 @@
 #ifndef BARRIER_NEXT
 #define BARRIER_NEXT(A)
 #endif
-
+#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A, xEmu, offsetof(x64emu_t, op1));}
+#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A, xEmu, offsetof(x64emu_t, op2));}
+#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A1, xEmu, offsetof(x64emu_t, op1));SDxw(A2, 0, offsetof(x64emu_t, op2));}
+#define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A, xEmu, offsetof(x64emu_t, res));}
+#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)}
+#define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags)
 #ifndef DEFAULT
 #define DEFAULT      *ok = -1; BARRIER(2)
 #endif
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index cd8e594b..566613fe 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -101,6 +101,9 @@ f28–31  ft8–11  FP temporaries                  Caller
 #define xZR     0
 #define wZR     xZR
 
+// replacement for F_OF internaly, using a reserved bit. Need to use F_OF2 internaly, never F_OF directly!
+#define F_OF2   F_res3
+
 // split a 32bits value in 20bits + 12bits, adjust the upper part is 12bits is negative
 #define SPLIT20(A)  (((A)+0x800)>>12)
 #define SPLIT12(A)  ((A)&0xfff)
diff --git a/src/dynarec/rv64/rv64_epilog.S b/src/dynarec/rv64/rv64_epilog.S
index af04279b..cf40153c 100644
--- a/src/dynarec/rv64/rv64_epilog.S
+++ b/src/dynarec/rv64/rv64_epilog.S
@@ -25,6 +25,12 @@ rv64_epilog:
     sd      x29, 104(a0)
     sd      x30, 112(a0)
     sd      x31, 120(a0)
+    // adjust flags bit 5 -> bit 11
+    li      x7, ~(1<<11)
+    and     x5, x5, x7
+    andi    x7, x5, 1<<5
+    slli    x7, x7, 11-5
+    or      x5, x5, x7
     sd      x5, 128(a0)     //xFlags
     sd      x6, 136(a0)     // put back reg value in emu, including EIP (so x27 must be EIP now)
     //restore all used register
diff --git a/src/dynarec/rv64/rv64_prolog.S b/src/dynarec/rv64/rv64_prolog.S
index 229910b9..dd99cfec 100644
--- a/src/dynarec/rv64/rv64_prolog.S
+++ b/src/dynarec/rv64/rv64_prolog.S
@@ -46,6 +46,11 @@ rv64_prolog:
     ld      x31, 120(a0)
     ld      x5, 128(a0)     //xFlags
     ld      x6, 136(a0)     // xRIP
+    // // adjust flags bit 11 -> bit 5
+    andi    x5, x5, ~(1<<5)    // probably not usefull?
+    srli    x7, x5, 11-5
+    andi    x7, x7, 1<<5
+    or      x5, x5, x7
     // setup xMASK
     xori    x7, x0, -1
     srli    x7, x7, 32