about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-02-13 18:38:19 +0800
committerGitHub <noreply@github.com>2025-02-13 11:38:19 +0100
commit95bdaf6eca65f3b45422c83abcf152c7022e6a26 (patch)
tree5bc0a1db9eb913a7db303474b3023c789705797f /src
parent9dc10bdc476e2a29f0755c5727e83f506a86a6f6 (diff)
downloadbox64-95bdaf6eca65f3b45422c83abcf152c7022e6a26.tar.gz
box64-95bdaf6eca65f3b45422c83abcf152c7022e6a26.zip
[RV64_DYNAREC] Minor fixes and improvements to TEST opcodes (#2352)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c14
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_tests.c59
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
3 files changed, 61 insertions, 14 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 0764618e..a3e4aee6 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -1111,10 +1111,18 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 case 1:
                     INST_NAME("TEST Eb, Ib");
                     SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
-                    GETEB(x1, 1);
+                    if (MODREG && (rex.rex || (((nextop & 7) >> 2) == 0))) {
+                        // quick path for low 8bit registers
+                        if (rex.rex)
+                            ed = TO_NAT((nextop & 7) + (rex.b << 3));
+                        else
+                            ed = TO_NAT(nextop & 3);
+                    } else {
+                        GETEB(x1, 1);
+                        ed = x1;
+                    }
                     u8 = F8;
-                    MOV32w(x2, u8);
-                    emit_test8(dyn, ninst, x1, x2, x6, x4, x5);
+                    emit_test8c(dyn, ninst, ed, u8, x6, x4, x5);
                     break;
                 case 2:
                     INST_NAME("NOT Eb");
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
index b122736c..1fa0b8ab 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c
@@ -333,6 +333,42 @@ void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
     }
 }
 
+// emit TEST8 instruction, from test s1, c, using s3, s4 and s5 as scratch
+void emit_test8c(dynarec_rv64_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4, int s5)
+{
+    CLEAR_FLAGS();
+    IFX_PENDOR0 {
+        SET_DF(s3, d_tst8);
+    } else {
+        SET_DFNONE();
+    }
+
+    ANDI(s3, s1, c); // res = s1 & c
+
+    IFX_PENDOR0 {
+        SD(s3, xEmu, offsetof(x64emu_t, res));
+    }
+
+    if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
+
+    IFX (X_SF) {
+        SRLI(s4, s3, 7);
+        SET_FLAGS_NEZ(s4, F_SF, s5);
+    }
+    IFX (X_ZF) {
+        SET_FLAGS_EQZ(s3, F_ZF, s5);
+    }
+    IFX (X_PF) {
+        emit_pf(dyn, ninst, s3, s4, s5);
+    }
+
+    NAT_FLAGS_ENABLE_SIGN();
+    if (dyn->insts[ninst].nat_flags_fusion && dyn->insts[ninst].nat_flags_needsign) {
+        SLLI(s3, s3, 56);
+        SRAI(s3, s3, 56);
+    }
+}
+
 // emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
 void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
 {
@@ -387,8 +423,6 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
 
     IFX (X_SF | X_ZF) {
         if (!rex.w) ZEROUP(s3);
-    } else if (dyn->insts[ninst].nat_flags_fusion) {
-        if (!rex.w) ZEROUP(s3);
     }
 
     if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
@@ -407,10 +441,11 @@ void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
     NAT_FLAGS_ENABLE_SIGN();
     if (dyn->insts[ninst].nat_flags_fusion && !rex.w) {
         if (dyn->insts[ninst].nat_flags_needsign) {
-            SLLI(s3, s3, 32);
-            SRAI(s3, s3, 32);
+            SEXT_W(s3, s3);
         } else {
-            ZEROUP(s3);
+            IFX (X_SF | X_ZF) {
+            } else
+                ZEROUP(s3);
         }
     }
 }
@@ -427,14 +462,15 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
 
     if (c >= -2048 && c <= 2047) {
         ANDI(s3, s1, c);
-        IFX (X_SF | X_ZF) {
-            if (!rex.w && c < 0) ZEROUP(s3);
-        }
     } else {
         MOV64xw(s3, c);
         AND(s3, s1, s3); // res = s1 & s2
     }
 
+    IFX (X_SF | X_ZF) {
+        if (!rex.w && c < 0) ZEROUP(s3);
+    }
+
     IFX_PENDOR0 {
         SDxw(s3, xEmu, offsetof(x64emu_t, res));
     }
@@ -455,10 +491,11 @@ void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
     NAT_FLAGS_ENABLE_SIGN();
     if (dyn->insts[ninst].nat_flags_fusion && !rex.w) {
         if (dyn->insts[ninst].nat_flags_needsign) {
-            SLLI(s3, s3, 32);
-            SRAI(s3, s3, 32);
+            SEXT_W(s3, s3);
         } else {
-            ZEROUP(s3);
+            IFX (X_SF | X_ZF) {
+            } else if (c < 0)
+                ZEROUP(s3);
         }
     }
 }
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 26820441..ca1e40d0 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1240,6 +1240,7 @@ void* rv64_next(void);
 #define emit_cmp16_0        STEPNAME(emit_cmp16_0)
 #define emit_cmp32_0        STEPNAME(emit_cmp32_0)
 #define emit_test8          STEPNAME(emit_test8)
+#define emit_test8c         STEPNAME(emit_test8c)
 #define emit_test16         STEPNAME(emit_test16)
 #define emit_test32         STEPNAME(emit_test32)
 #define emit_test32c        STEPNAME(emit_test32)
@@ -1411,6 +1412,7 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);
 void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4);
 void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
 void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
+void emit_test8c(dynarec_rv64_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4, int s5);
 void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_test32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
 void emit_test32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);