about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-01-16 20:18:31 +0800
committerGitHub <noreply@github.com>2025-01-16 13:18:31 +0100
commit93bf3081790a24e1e172260d172e2905edfe13cf (patch)
tree3d79f0103c0d6b7fbb101fe0891f9aea2f0e0f16
parent166c4858a1155860c10cf903091df39a576c0e81 (diff)
downloadbox64-93bf3081790a24e1e172260d172e2905edfe13cf.tar.gz
box64-93bf3081790a24e1e172260d172e2905edfe13cf.zip
[RV64_DYNAREC] Optimized 16bit constant ROR opcodes (#2268)
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c25
-rw-r--r--src/dynarec/rv64/dynarec_rv64_emit_shift.c35
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h2
3 files changed, 51 insertions, 11 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 5a35e1f2..dfb4a4b5 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -1077,13 +1077,17 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     break;
                 case 1:
                     INST_NAME("ROR Ew, Ib");
-                    MESSAGE(LOG_DUMP, "Need Optimization\n");
-                    SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
-                    GETEW(x1, 1);
-                    u8 = F8;
-                    MOV32w(x2, u8);
-                    CALL_(ror16, x1, x3, x1, x2);
-                    EWBACK;
+                    if (geted_ib(dyn, addr, ninst, nextop) & 15) {
+                        // removed PENDING on purpose
+                        SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
+                        GETEW(x1, 1);
+                        u8 = (F8) & 0x1f;
+                        emit_ror16c(dyn, ninst, x1, u8, x4, x5);
+                        EWBACK;
+                    } else {
+                        FAKEED;
+                        F8;
+                    }
                     break;
                 case 2:
                     INST_NAME("RCL Ew, Ib");
@@ -1195,11 +1199,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     break;
                 case 1:
                     INST_NAME("ROR Ew, 1");
-                    MOV32w(x2, 1);
-                    MESSAGE(LOG_DUMP, "Need Optimization\n");
-                    SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
+                    // removed PENDING on purpose
+                    SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
                     GETEW(x1, 1);
-                    CALL_(ror16, x1, x3, x1, x2);
+                    emit_ror16c(dyn, ninst, x1, 1, x5, x4);
                     EWBACK;
                     break;
                 case 2:
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
index 8daa62dc..54d4782e 100644
--- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c
+++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c
@@ -1141,6 +1141,41 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
     }
 }
 
+// emit ROR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_ror16c(dynarec_rv64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
+{
+    if (!c) return;
+
+    SET_DFNONE();
+
+    SRLI(s3, s1, c);
+    SLLI(s1, s1, 64 - c);
+    SRLI(s1, s1, 48);
+    OR(s1, s1, s3);
+
+    if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
+
+    IFX (X_CF | X_OF) {
+        ANDI(xFlags, xFlags, ~(1UL << F_CF | 1UL << F_OF2));
+    }
+
+    IFX (X_CF) {
+        SRLI(s3, s1, 15);
+        OR(xFlags, xFlags, s3);
+    }
+
+    IFX (X_OF) {
+        if (c == 1) {
+            SRLI(s3, s1, 14);
+            SRLI(s4, s3, 1);
+            XOR(s3, s3, s4);
+            ANDI(s3, s3, 1);
+            SLLI(s3, s3, F_OF2);
+            OR(xFlags, xFlags, s3);
+        }
+    }
+}
+
 // emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
 void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
 {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index a389f7b1..b58caf0e 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1303,6 +1303,7 @@ void* rv64_next(void);
 #define emit_sar32c         STEPNAME(emit_sar32c)
 #define emit_rol16c         STEPNAME(emit_rol16c)
 #define emit_rol32          STEPNAME(emit_rol32)
+#define emit_ror16c         STEPNAME(emit_ror16c)
 #define emit_ror32          STEPNAME(emit_ror32)
 #define emit_rol32c         STEPNAME(emit_rol32c)
 #define emit_ror32c         STEPNAME(emit_ror32c)
@@ -1472,6 +1473,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
 void emit_rol32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
 void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
 void emit_rol16c(dynarec_rv64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
+void emit_ror16c(dynarec_rv64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
 void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4, int s5);