about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-04-19 20:37:08 +0000
committerptitSeb <sebastien.chev@gmail.com>2023-04-19 20:37:20 +0000
commitd0ae6a9a7da7d77f17b97b41c14951a4af0f9c70 (patch)
treed1f7c8c30287cad9a49a0a2ea6b1a13a400070b6 /src
parent9aca360fe5bb1496324cfcbf2a41fafcf5f2fc63 (diff)
downloadbox64-d0ae6a9a7da7d77f17b97b41c14951a4af0f9c70.tar.gz
box64-d0ae6a9a7da7d77f17b97b41c14951a4af0f9c70.zip
[RV64_DYNAREC] Various fixes on many opcodes
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_2.c11
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c10
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c2
-rw-r--r--src/dynarec/rv64/dynarec_rv64_660f.c3
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c8
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f0.c7
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f30f.c20
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h15
9 files changed, 47 insertions, 33 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c
index f7572790..c02b1796 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_2.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_2.c
@@ -193,8 +193,13 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     if(i64) {
                         MOV64xw(x2, i64);
                         emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
-                    } else
+                    } else {
+                        if(!rex.w && MODREG) {
+                            AND(x1, ed, xMASK);
+                            ed = x1;
+                        }
                         emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
+                    }
                     break;
             }
             break;
@@ -429,8 +434,8 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0x9C:
             INST_NAME("PUSHF");
             READFLAGS(X_ALL);
-            FLAGS_ADJUST_TO11(xFlags, x2);
-            PUSH1(xFlags);
+            FLAGS_ADJUST_TO11(x3, xFlags, x2);
+            PUSH1(x3);
             break;
         case 0x9D:
             INST_NAME("POPF");
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 11b0ac5e..f6c2a4ed 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -775,7 +775,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         MUL(xRAX, xRAX, ed);
                         if(gd!=xRDX) {MV(xRDX, gd);}
                     } else {
-                        MUL(xRDX, xRAX, ed);  //64 <- 32x32
+                        AND(x3, xRAX, xMASK);
+                        if(MODREG) {
+                            AND(x4, ed, xMASK);
+                            ed = x4;
+                        }
+                        MUL(xRDX, x3, ed);  //64 <- 32x32
                         AND(xRAX, xRDX, xMASK);
                         SRLI(xRDX, xRDX, 32);
                     }
@@ -793,7 +798,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         MUL(xRAX, xRAX, ed);
                         if(gd!=xRDX) {MV(xRDX, gd);}
                     } else {
-                        MUL(xRDX, xRAX, ed);  //64 <- 32x32
+                        ADDIW(x3, xRAX, 0); // sign extend 32bits-> 64bits
+                        MUL(xRDX, x3, ed);  //64 <- 32x32
                         AND(xRAX, xRDX, xMASK);
                         SRLI(xRDX, xRDX, 32);
                     }
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index adcfc5fe..40e52e63 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -635,6 +635,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     case 0:
                         INST_NAME("FXSAVE Ed");
                         MESSAGE(LOG_DUMP, "Need Optimization\n");
+                        SKIPTEST(x1);
                         fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
                         if(MODREG) {
                             DEFAULT;
@@ -647,6 +648,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     case 1:
                         INST_NAME("FXRSTOR Ed");
                         MESSAGE(LOG_DUMP, "Need Optimization\n");
+                        SKIPTEST(x1);
                         fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
                         if(MODREG) {
                             DEFAULT;
diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c
index fa391f82..20a5b441 100644
--- a/src/dynarec/rv64/dynarec_rv64_660f.c
+++ b/src/dynarec/rv64/dynarec_rv64_660f.c
@@ -173,7 +173,8 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     GETGX(x1);
                     GETEX(x2, 0);
                     sse_forget_reg(dyn, ninst, x5);
-                    ADDI(x5, xEmu, offsetof(x64emu_t, xmm[x5]));
+
+                    ADDI(x5, xEmu, offsetof(x64emu_t, scratch));
 
                     // perserve gd
                     LD(x3, gback, 0);
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
index 5d346059..79ebe6cb 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -324,9 +324,12 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
         SET_DFNONE();
     }
 
-    if(c>=-2048 && c<=2047)
+    if(c>=-2048 && c<=2047) {
         ANDI(s3, s1, c);
-    else {
+        IFX(X_SF|X_ZF) {
+            if (!rex.w && c<0) ZEROUP(s3);
+        }
+    } else {
         MOV64xw(s3, c);
         AND(s3, s1, s3); // res = s1 & s2
     }
@@ -335,7 +338,6 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
         SDxw(s3, xEmu, offsetof(x64emu_t, res));
     }
     IFX(X_SF) {
-        if (!rex.w) ZEROUP(s3);
         SRLI(s4, s3, rex.w?63:31);
         BEQZ(s4, 8);
         ORI(xFlags, xFlags, 1 << F_SF);
diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c
index 781990ac..ff15db2b 100644
--- a/src/dynarec/rv64/dynarec_rv64_f0.c
+++ b/src/dynarec/rv64/dynarec_rv64_f0.c
@@ -89,7 +89,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             SETFLAGS(X_ALL, SF_SET_PENDING);
                             nextop = F8;
                             GETGD;
-                            SMDMB();
                             if (MODREG) {
                                 ed = xRAX+(nextop&7)+(rex.b<<3);
                                 wback = 0;
@@ -100,12 +99,12 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                                 MV(ed, gd);
                                 MARK2;
                                 MVxw(xRAX, x1);
-                                B_NEXT_nocond;
                             } else {
+                                SMDMB();
                                 addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
                                 MARKLOCK;
                                 LRxw(x1, wback, 1, 1);
-                                SUB(x3, x1, xRAX);
+                                SUBxw(x3, x1, xRAX);
                                 BNE_MARK(x3, xZR);
                                 // EAX == Ed
                                 SCxw(x4, gd, wback, 1, 1);
@@ -113,8 +112,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                                 MARK;
                                 UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6);}
                                 MVxw(xRAX, x1);
+                                SMDMB();
                             }
-                            SMDMB();
                             break;
                         default:
                             DEFAULT;
diff --git a/src/dynarec/rv64/dynarec_rv64_f30f.c b/src/dynarec/rv64/dynarec_rv64_f30f.c
index bce8879f..e942e9b5 100644
--- a/src/dynarec/rv64/dynarec_rv64_f30f.c
+++ b/src/dynarec/rv64/dynarec_rv64_f30f.c
@@ -289,47 +289,45 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             }
             BNE_MARK(ed, xZR);
             MOV32w(gd, rex.w?64:32);
-            B_MARK2_nocond;
-            MARK;
             ANDI(xFlags, xFlags, ~(1<<F_ZF));
+            ORI(xFlags, xFlags, 1<<F_CF);
+            B_NEXT_nocond;
+            MARK;
             if(ed!=gd)
                 u8 = gd;
             else
                 u8 = x1;
-            ADDI(u8, xZR, 0);
+            ADDI(u8, xZR, rex.w?63:31);
             if(rex.w) {
                 MV(x2, ed);
                 SRLI(x3, x2, 32);
                 BEQZ(x3, 4+2*4);
-                ADDI(u8, u8, 32);
+                SUBI(u8, u8, 32);
                 MV(x2, x3);
             } else {
                 AND(x2, ed, xMASK);
             }
             SRLI(x3, x2, 16);
             BEQZ(x3, 4+2*4);
-            ADDI(u8, u8, 16);
+            SUBI(u8, u8, 16);
             MV(x2, x3);
             SRLI(x3, x2, 8);
             BEQZ(x3, 4+2*4);
-            ADDI(u8, u8, 8);
+            SUBI(u8, u8, 8);
             MV(x2, x3);
             SRLI(x3, x2, 4);
             BEQZ(x3, 4+2*4);
-            ADDI(u8, u8, 4);
+            SUBI(u8, u8, 4);
             MV(x2, x3);
             ANDI(x2, x2, 0b1111); 
             TABLE64(x3, (uintptr_t)&lead0tab);
             ADD(x3, x3, x2);
             LBU(x2, x3, 0);
-            ADD(gd, u8, x2);
+            SUB(gd, u8, x2);
             MARK2;
             ANDI(xFlags, xFlags, ~((1<<F_ZF) | (1<<F_CF)));
             BNE(gd, xZR, 4+4);
             ORI(xFlags, xFlags, 1<<F_ZF);
-            MOV32w(x2, rex.w?64:32);
-            BNE(gd, x2, 4+4);
-            ORI(xFlags, xFlags, 1<<F_CF);
             break;
 
         case 0xC2:
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 6d7e5e91..a395871d 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -389,7 +389,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);
+        FLAGS_ADJUST_TO11(xFlags, xFlags, reg);
         SD(xFlags, xEmu, offsetof(x64emu_t, eflags));
     }
     fpu_pushcache(dyn, ninst, reg, 0);
@@ -442,7 +442,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);
+    FLAGS_ADJUST_TO11(xFlags, 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
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 867190e1..95fc3f87 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -604,13 +604,14 @@
     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)
+// Adjust the xFlags bit 5 -> bit 11, src and dst can be the same (and can be xFlags, but not s1)
+#define FLAGS_ADJUST_TO11(dst, src, s1) \
+    MOV64x(s1, ~(1<<11));               \
+    AND(dst, src, s1);                  \
+    ANDI(s1, dst, 1<<5);                \
+    SLLI(s1, s1, 11-5);                 \
+    ANDI(dst, dst, ~(1<<5));            \
+    OR(dst, dst, s1)
 
 #ifndef MAYSETFLAGS
 #define MAYSETFLAGS()