about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-06-20 17:26:21 +0800
committerGitHub <noreply@github.com>2025-06-20 11:26:21 +0200
commitf1e884103040ef5d304de5d4f10aac3915f92451 (patch)
tree77fc740002fa46971c0108046be177d0c1d0e7df /src
parentcfdc733e2f6c25901cc72e774bcbcdecceb3d9de (diff)
downloadbox64-f1e884103040ef5d304de5d4f10aac3915f92451.tar.gz
box64-f1e884103040ef5d304de5d4f10aac3915f92451.zip
[DYNACACHE][RV64] Enabled dynacache for RV64 (#2762)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c42
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c25
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h15
-rw-r--r--src/dynarec/rv64/dynarec_rv64_pass2.h32
-rw-r--r--src/dynarec/rv64/dynarec_rv64_pass3.h33
-rw-r--r--src/dynarec/rv64/rv64_emitter.h30
-rw-r--r--src/tools/env.c2
7 files changed, 119 insertions, 60 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 5eb2196e..924f3e36 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -460,7 +460,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     if (tmp < 0 || (tmp & 15) > 1)
                         tmp = 0; // TODO: removed when FP is in place
                     if ((BOX64ENV(log) < 2 && !BOX64ENV(rolling_log)) && tmp) {
-                        call_n(dyn, ninst, *(void**)(addr + 8), tmp);
+                        call_n(dyn, ninst, (void*)(addr + 8), tmp);
                         addr += 8 + 8;
                     } else {
                         GETIP(ip + 1, x7); // read the 0xCC
@@ -964,7 +964,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
 #endif
             }
 #if STEP < 2
-            if (!rex.is32bits && IsNativeCall(addr + i32, rex.is32bits, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
+            if (!rex.is32bits && !dyn->need_reloc && IsNativeCall(addr + i32, rex.is32bits, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
                 tmp = dyn->insts[ninst].pass2choice = 3;
             else
                 tmp = dyn->insts[ninst].pass2choice = i32 ? 0 : 1;
@@ -978,8 +978,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     BARRIER(BARRIER_FULL);
                     if (dyn->last_ip && (addr - dyn->last_ip < 0x800)) {
                         ADDI(x2, xRIP, addr - dyn->last_ip);
+                    } else if (dyn->last_ip && (dyn->last_ip - addr < 0x800)) {
+                        SUBI(x2, xRIP, dyn->last_ip - addr);
                     } else {
-                        MOV64x(x2, addr);
+                        if (dyn->need_reloc) {
+                            TABLE64(x2, addr);
+                        } else {
+                            MOV64x(x2, addr);
+                        }
                     }
                     PUSH1(x2);
                     MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall - 1)), dyn->insts[ninst].retn);
@@ -996,7 +1002,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         // return value will be on the stack, so the stack depth needs to be updated
                         x87_purgecache(dyn, ninst, 0, x3, x1, x4);
                     if ((BOX64ENV(log) < 2 && !BOX64ENV(rolling_log)) && dyn->insts[ninst].natcall && tmp) {
-                        call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall + 2 + 8), tmp);
+                        call_n(dyn, ninst, (void*)(dyn->insts[ninst].natcall + 2 + 8), tmp);
                         POP1(xRIP); // pop the return address
                         dyn->last_ip = addr;
                     } else {
@@ -1026,7 +1032,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     break;
                 case 1:
                     // this is call to next step, so just push the return address to the stack
-                    MOV64x(x2, addr);
+                    if (dyn->need_reloc) {
+                        TABLE64(x2, addr);
+                    } else {
+                        MOV64x(x2, addr);
+                    }
                     PUSH1z(x2);
                     break;
                 default:
@@ -1036,15 +1046,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags to "dont'care" state
                     }
                     // regular call
-                    /*if(BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock)>1) {
-                        BARRIER(BARRIER_FULL);
+                    if (dyn->need_reloc) {
+                        TABLE64(x2, addr);
                     } else {
-                        BARRIER(BARRIER_FLOAT);
-                        *need_epilog = 0;
-                        *ok = 0;
-                    }*/
-
-                    MOV64x(x2, addr);
+                        MOV64x(x2, addr);
+                    }
                     fpu_purgecache(dyn, ninst, 1, x1, x3, x4);
                     PUSH1z(x2);
                     if (BOX64DRENV(dynarec_callret)) {
@@ -1072,7 +1078,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
                         // jumps out of current dynablock...
                         j64 = getJumpTableAddress64(addr);
-                        MOV64x(x4, j64);
+                        if (dyn->need_reloc) {
+                            AddRelocTable64JmpTbl(dyn, ninst, addr, STEP);
+                            TABLE64_(x4, j64);
+                        } else {
+                            MOV64x(x4, j64);
+                        }
                         LD(x4, x4, 0);
                         BR(x4);
                     }
@@ -1562,7 +1573,8 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
                         // jumps out of current dynablock...
                         j64 = getJumpTableAddress64(addr);
-                        TABLE64(x4, j64);
+                        if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
+                        TABLE64_(x4, j64);
                         LD(x4, x4, 0);
                         BR(x4);
                     }
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 9f2645b5..0b597163 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -118,7 +118,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
                 GETIP(addr + delta, scratch);
                 ADDI(ret, xRIP, tmp);
                 SCRATCH_USAGE(1);
-            } else if (tmp + addr + delta < 0x100000000LL) {
+            } else if (tmp + addr + delta < 0x80000000LL && !dyn->need_reloc) {
                 MOV64x(ret, tmp + addr + delta);
             } else {
                 if (adj) {
@@ -591,7 +591,11 @@ static int indirect_lookup(dynarec_rv64_t* dyn, int ninst, int is32bits, int s1,
         if (!is32bits) {
             SRLI(s1, xRIP, 48);
             BNEZ_safe(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block);
-            MOV64x(s2, getConst(const_jmptbl48));
+            if (dyn->need_reloc) {
+                TABLE64C(s2, const_jmptbl48);
+            } else {
+                MOV64x(s2, getConst(const_jmptbl48));
+            }
             TH_EXTU(s1, xRIP, JMPTABL_START2 + JMPTABL_SHIFT2 - 1, JMPTABL_START2);
             TH_LRD(s2, s2, s1, 3);
         } else {
@@ -649,7 +653,8 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3
         uintptr_t p = getJumpTableAddress64(ip);
         MAYUSE(p);
         GETIP_(ip, x3);
-        TABLE64(x3, p);
+        if (dyn->need_reloc) AddRelocTable64JmpTbl(dyn, ninst, ip, STEP);
+        TABLE64_(x3, p);
         LD(x2, x3, 0);
         dest = x2;
     }
@@ -755,7 +760,11 @@ void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits)
     // set new RSP
     MV(xRSP, x3);
     // Ret....
-    MOV64x(x2, getConst(const_epilog)); // epilog on purpose, CS might have changed!
+    // epilog on purpose, CS might have changed!
+    if (dyn->need_reloc)
+        TABLE64C(x2, const_epilog);
+    else
+        MOV64x(x2, getConst(const_epilog));
     SMEND();
     BR(x2);
     CLEARIP();
@@ -841,7 +850,13 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w)
         }
     }
     // native call
-    TABLE64(x3, (uintptr_t)fnc);
+    if (dyn->need_reloc) {
+        // fnc is indirect, to help with relocation (but PltResolver might be an issue here)
+        TABLE64(x3, (uintptr_t)fnc);
+        LD(x3, x3, 0);
+    } else {
+        TABLE64_(x3, *(uintptr_t*)fnc); // using x16 as scratch regs for call address
+    }
     JALR(xRA, x3);
     // put return value in x64 regs
     if (w > 0) {
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 361e104f..939e3c37 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1152,6 +1152,9 @@
 #ifndef TABLE64C
 #define TABLE64C(A, V)
 #endif
+#ifndef TABLE64_
+#define TABLE64_(A, V)
+#endif
 
 #define ARCH_INIT() \
     SMSTART();      \
@@ -1168,7 +1171,11 @@
     do {                                                          \
         ssize_t _delta_ip = (ssize_t)(A) - (ssize_t)dyn->last_ip; \
         if (!dyn->last_ip) {                                      \
-            MOV64x(xRIP, A);                                      \
+            if (dyn->need_reloc) {                                \
+                TABLE64(xRIP, (A));                               \
+            } else {                                              \
+                MOV64x(xRIP, (A));                                \
+            }                                                     \
         } else if (_delta_ip == 0) {                              \
         } else if (_delta_ip >= -2048 && _delta_ip < 2048) {      \
             ADDI(xRIP, xRIP, _delta_ip);                          \
@@ -1179,7 +1186,11 @@
             MOV32w(scratch, _delta_ip);                           \
             ADD(xRIP, xRIP, scratch);                             \
         } else {                                                  \
-            MOV64x(xRIP, (A));                                    \
+            if (dyn->need_reloc) {                                \
+                TABLE64(xRIP, (A));                               \
+            } else {                                              \
+                MOV64x(xRIP, (A));                                \
+            }                                                     \
         }                                                         \
     } while (0)
 #define GETIP(A, scratch) \
diff --git a/src/dynarec/rv64/dynarec_rv64_pass2.h b/src/dynarec/rv64/dynarec_rv64_pass2.h
index 7466f426..d6bb4934 100644
--- a/src/dynarec/rv64/dynarec_rv64_pass2.h
+++ b/src/dynarec/rv64/dynarec_rv64_pass2.h
@@ -25,22 +25,32 @@
     }
 #define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
 #define INST_NAME(name)
-#define TABLE64(A, V)         \
-    {                         \
+#define TABLE64(A, V)                                \
+    do {                                             \
+        if (dyn->need_reloc && !isTable64(dyn, (V))) \
+            AddRelocTable64Addr(dyn, ninst, (V), 2); \
+        Table64(dyn, (V), 2);                        \
+        EMIT(0);                                     \
+        EMIT(0);                                     \
+    } while (0)
+#define TABLE64_(A, V)        \
+    do {                      \
         Table64(dyn, (V), 2); \
         EMIT(0);              \
         EMIT(0);              \
-    }
+    } while (0)
 #define FTABLE64(A, V)               \
-    {                                \
+    do {                             \
         mmx87_regs_t v = { .d = V }; \
         Table64(dyn, v.q, 2);        \
         EMIT(0);                     \
         EMIT(0);                     \
-    }
-#define TABLE64C(A, V)                \
-    {                                 \
-        Table64(dyn, getConst(V), 2); \
-        EMIT(0);                      \
-        EMIT(0);                      \
-    }
+    } while (0)
+#define TABLE64C(A, V)                                       \
+    do {                                                     \
+        if (dyn->need_reloc && !isTable64(dyn, getConst(V))) \
+            AddRelocTable64Const(dyn, ninst, (V), 2);        \
+        Table64(dyn, getConst(V), 2);                        \
+        EMIT(0);                                             \
+        EMIT(0);                                             \
+    } while (0)
diff --git a/src/dynarec/rv64/dynarec_rv64_pass3.h b/src/dynarec/rv64/dynarec_rv64_pass3.h
index 9a08a57e..1938eccc 100644
--- a/src/dynarec/rv64/dynarec_rv64_pass3.h
+++ b/src/dynarec/rv64/dynarec_rv64_pass3.h
@@ -30,27 +30,38 @@
 #define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex)
 
 #define TABLE64(A, V)                                 \
-    {                                                 \
+    do {                                              \
+        if (dyn->need_reloc && !isTable64(dyn, (V)))  \
+            AddRelocTable64Addr(dyn, ninst, (V), 3);  \
         int val64offset = Table64(dyn, (V), 3);       \
         MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V)); \
         AUIPC(A, SPLIT20(val64offset));               \
         LD(A, A, SPLIT12(val64offset));               \
-    }
+    } while (0)
+#define TABLE64_(A, V)                                \
+    do {                                              \
+        int val64offset = Table64(dyn, (V), 3);       \
+        MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V)); \
+        AUIPC(A, SPLIT20(val64offset));               \
+        LD(A, A, SPLIT12(val64offset));               \
+    } while (0)
 #define FTABLE64(A, V)                              \
-    {                                               \
+    do {                                            \
         mmx87_regs_t v = { .d = V };                \
         int val64offset = Table64(dyn, v.q, 3);     \
         MESSAGE(LOG_DUMP, "  FTable64: %g\n", v.d); \
         AUIPC(x1, SPLIT20(val64offset));            \
         FLD(A, x1, SPLIT12(val64offset));           \
-    }
-#define TABLE64C(A, V)                                  \
-    {                                                   \
-        int val64offset = Table64(dyn, getConst(V), 3); \
-        MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V));   \
-        AUIPC(A, SPLIT20(val64offset));                 \
-        LD(A, A, SPLIT12(val64offset));                 \
-    }
+    } while (0)
+#define TABLE64C(A, V)                                       \
+    do {                                                     \
+        if (dyn->need_reloc && !isTable64(dyn, getConst(V))) \
+            AddRelocTable64Const(dyn, ninst, (V), 3);        \
+        int val64offset = Table64(dyn, getConst(V), 3);      \
+        MESSAGE(LOG_DUMP, "  Table64: 0x%lx\n", (V));        \
+        AUIPC(A, SPLIT20(val64offset));                      \
+        LD(A, A, SPLIT12(val64offset));                      \
+    } while (0)
 
 #define DEFAULT_VECTOR                                                                                                                  \
     if (BOX64ENV(dynarec_log) >= LOG_INFO || dyn->need_dump || BOX64ENV(dynarec_missing) == 2) {                                        \
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index cb91b7e6..f5ad2530 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -948,21 +948,21 @@
 // Count trailing zero bits
 // BEWARE: You should take care of the all zeros situation yourself,
 //         and clear the high 32bit when x is 1.
-#define CTZxw(rd, rs, x, s1, s2)            \
-    if (cpuext.zbb) {                       \
-        if (x)                              \
-            CTZ(rd, rs);                    \
-        else                                \
-            CTZW(rd, rs);                   \
-    } else {                                \
-        NEG(s2, rs);                        \
-        AND(s2, s2, rs);                    \
-        TABLE64(s1, 0x03f79d71b4ca8b09ULL); \
-        MUL(s2, s2, s1);                    \
-        SRLI(s2, s2, 64 - 6);               \
-        TABLE64C(s1, const_deBruijn64tab);  \
-        ADD(s1, s1, s2);                    \
-        LBU(rd, s1, 0);                     \
+#define CTZxw(rd, rs, x, s1, s2)             \
+    if (cpuext.zbb) {                        \
+        if (x)                               \
+            CTZ(rd, rs);                     \
+        else                                 \
+            CTZW(rd, rs);                    \
+    } else {                                 \
+        NEG(s2, rs);                         \
+        AND(s2, s2, rs);                     \
+        TABLE64_(s1, 0x03f79d71b4ca8b09ULL); \
+        MUL(s2, s2, s1);                     \
+        SRLI(s2, s2, 64 - 6);                \
+        TABLE64C(s1, const_deBruijn64tab);   \
+        ADD(s1, s1, s2);                     \
+        LBU(rd, s1, 0);                      \
     }
 
 // Count set bits
diff --git a/src/tools/env.c b/src/tools/env.c
index 3a22855c..fce6cdaa 100644
--- a/src/tools/env.c
+++ b/src/tools/env.c
@@ -806,7 +806,7 @@ done:
 #ifdef ARM64
 #define ARCH_VERSION SET_VERSION(0, 0, 1)
 #elif defined(RV64)
-#define ARCH_VERSION SET_VERSION(0, 0, 0)
+#define ARCH_VERSION SET_VERSION(0, 0, 1)
 #elif defined(LA64)
 #define ARCH_VERSION SET_VERSION(0, 0, 0)
 #else