about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-01-25 04:35:47 +0800
committerGitHub <noreply@github.com>2025-01-24 21:35:47 +0100
commit6f8f37e8ffc61a496c9e533fdca83d14adc5ee28 (patch)
treef32277bcd71887a69168d7653100029d7cf54bbb /src
parent3ec950726b61eb427cb4250a28125a2a791e3a6a (diff)
downloadbox64-6f8f37e8ffc61a496c9e533fdca83d14adc5ee28.tar.gz
box64-6f8f37e8ffc61a496c9e533fdca83d14adc5ee28.zip
[RV64_DYNAREC] Optimized GETIP (#2294)
Co-authored-by: xctan <xctan@cirno.icu>
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_1.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c36
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c6
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c4
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.c14
-rw-r--r--src/dynarec/rv64/dynarec_rv64_helper.h43
-rw-r--r--src/dynarec/rv64/dynarec_rv64_private.h2
7 files changed, 55 insertions, 54 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c
index f532218e..88dd813f 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_1.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_1.c
@@ -290,7 +290,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             } else {
                 SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
             }
-            GETIP(ip);
+            GETIP(ip, x7);
             STORE_XEMU_CALL(x3);
             CALL(native_priv, -1, 0, 0);
             LOAD_XEMU_CALL();
@@ -306,7 +306,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             } else {
                 SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
             }
-            GETIP(ip);
+            GETIP(ip, x7);
             STORE_XEMU_CALL(x3);
             CALL(native_priv, -1, 0, 0);
             LOAD_XEMU_CALL();
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 6777c7ac..0764618e 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -438,8 +438,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 if ((PK64(0) == 0)) {
                     addr += 8;
                     MESSAGE(LOG_DEBUG, "Exit x64 Emu\n");
-                    // GETIP(ip+1+2);    // no use
-                    // STORE_XEMU_REGS(xRIP);    // no need, done in epilog
                     MOV64x(x1, 1);
                     SW(x1, xEmu, offsetof(x64emu_t, quit));
                     *ok = 0;
@@ -457,11 +455,10 @@ 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) {
-                        // GETIP(ip+3+8+8); // read the 0xCC
                         call_n(dyn, ninst, *(void**)(addr + 8), tmp);
                         addr += 8 + 8;
                     } else {
-                        GETIP(ip + 1); // read the 0xCC
+                        GETIP(ip + 1, x7); // read the 0xCC
                         STORE_XEMU_CALL(x3);
                         ADDI(x3, xRIP, 8 + 8);                            // expected return address
                         ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
@@ -484,7 +481,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     ADD(x2, x2, x1);
                     LD(x3, x2, 0);
                     BEQZ_MARK(x3);
-                    GETIP(addr);
+                    GETIP(addr, x7);
                     STORE_XEMU_CALL(x3);
                     CALL(native_int3, -1, 0, 0);
                     LOAD_XEMU_CALL();
@@ -502,7 +499,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 INST_NAME("INT 29/2c/2d");
                 // lets do nothing
                 MESSAGE(LOG_INFO, "INT 29/2c/2d Windows interruption\n");
-                GETIP(ip); // priviledged instruction, IP not updated
+                GETIP(ip, x7); // priviledged instruction, IP not updated
                 STORE_XEMU_CALL(x3);
                 MOV32w(x1, u8);
                 CALL(native_int, -1, x1, 0);
@@ -511,7 +508,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 INST_NAME("32bits SYSCALL");
                 NOTEST(x1);
                 SMEND();
-                GETIP(addr);
+                GETIP(addr, x7);
                 STORE_XEMU_CALL(x3);
                 CALL_S(x86Syscall, -1, 0);
                 LOAD_XEMU_CALL();
@@ -529,7 +526,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 } else {
                     SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
                 }
-                GETIP(addr);
+                GETIP(addr, x7);
                 STORE_XEMU_CALL(x3);
                 CALL(native_int3, -1, 0, 0);
                 LOAD_XEMU_CALL();
@@ -543,7 +540,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 } else {
                     SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
                 }
-                GETIP(ip); // priviledged instruction, IP not updated
+                GETIP(ip, x7); // priviledged instruction, IP not updated
                 STORE_XEMU_CALL(x3);
                 CALL(native_priv, -1, 0, 0);
                 LOAD_XEMU_CALL();
@@ -964,12 +961,11 @@ 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) {
-                        // GETIP(ip+3+8+8); // read the 0xCC
                         call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall + 2 + 8), tmp);
                         POP1(xRIP); // pop the return address
                         dyn->last_ip = addr;
                     } else {
-                        GETIP_(dyn->insts[ninst].natcall); // read the 0xCC already
+                        GETIP_(dyn->insts[ninst].natcall, x7); // read the 0xCC already
                         STORE_XEMU_CALL(x3);
                         ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
                         CALL_S(x64Int3, -1, x1);
@@ -1091,7 +1087,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             else
                 INST_NAME("OUT DX, EAX");
             SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
-            GETIP(ip);
+            GETIP(ip, x7);
             STORE_XEMU_CALL(xRIP);
             CALL(native_priv, -1, 0, 0);
             LOAD_XEMU_CALL();
@@ -1285,14 +1281,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                             && *(uint32_t*)(dyn->insts[ninst - 1].x64.addr + 1) == 0) {
                             // hack for some protection that check a divide by zero actually trigger a divide by zero exception
                             MESSAGE(LOG_INFO, "Divide by 0 hack\n");
-                            GETIP(ip);
+                            GETIP(ip, x7);
                             STORE_XEMU_CALL(x3);
                             CALL(native_div0, -1, 0, 0);
                             LOAD_XEMU_CALL();
                         } else {
                             if (BOX64ENV(dynarec_div0)) {
                                 BNE_MARK3(ed, xZR);
-                                GETIP_(ip);
+                                GETIP_(ip, x7);
                                 STORE_XEMU_CALL(x3);
                                 CALL(native_div0, -1, 0, 0);
                                 CLEARIP();
@@ -1320,7 +1316,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                             GETED(0);
                             if (BOX64ENV(dynarec_div0)) {
                                 BNE_MARK3(ed, xZR);
-                                GETIP_(ip);
+                                GETIP_(ip, x7);
                                 STORE_XEMU_CALL(x3);
                                 CALL(native_div0, -1, 0, 0);
                                 CLEARIP();
@@ -1335,7 +1331,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                             GETEDH(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
                             if (BOX64ENV(dynarec_div0)) {
                                 BNE_MARK3(ed, xZR);
-                                GETIP_(ip);
+                                GETIP_(ip, x7);
                                 STORE_XEMU_CALL(x3);
                                 CALL(native_div0, -1, 0, 0);
                                 CLEARIP();
@@ -1362,7 +1358,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         GETSED(0);
                         if (BOX64ENV(dynarec_div0)) {
                             BNE_MARK3(ed, xZR);
-                            GETIP_(ip);
+                            GETIP_(ip, x7);
                             STORE_XEMU_CALL(x3);
                             CALL(native_div0, -1, 0, 0);
                             CLEARIP();
@@ -1385,7 +1381,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                             GETED(0);
                             if (BOX64ENV(dynarec_div0)) {
                                 BNE_MARK3(ed, xZR);
-                                GETIP_(ip);
+                                GETIP_(ip, x7);
                                 STORE_XEMU_CALL(x3);
                                 CALL(native_div0, -1, 0, 0);
                                 CLEARIP();
@@ -1400,7 +1396,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                             GETEDH(x1, 0); // get edd changed addr, so cannot be called 2 times for same op...
                             if (BOX64ENV(dynarec_div0)) {
                                 BNE_MARK3(ed, xZR);
-                                GETIP_(ip);
+                                GETIP_(ip, x7);
                                 STORE_XEMU_CALL(x3);
                                 CALL(native_div0, -1, 0, 0);
                                 CLEARIP();
@@ -1504,7 +1500,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                         *need_epilog = 0;
                         *ok = 0;
                     }
-                    GETIP_(addr);
+                    GETIP_(addr, x7);
                     if (BOX64DRENV(dynarec_callret)) {
                         SET_HASCALLRET();
                         j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 8d760708..35441901 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -116,7 +116,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             INST_NAME("SYSCALL");
             NOTEST(x1);
             SMEND();
-            GETIP(addr);
+            GETIP(addr, x7);
             STORE_XEMU_CALL(x3);
             CALL_S(x64Syscall, -1, 0);
             LOAD_XEMU_CALL();
@@ -136,7 +136,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             } else {
                 SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
             }
-            GETIP(ip);
+            GETIP(ip, x7);
             STORE_XEMU_CALL(x3);
             CALL(native_ud, -1, 0, 0);
             LOAD_XEMU_CALL();
@@ -152,7 +152,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             } else {
                 SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
             }
-            GETIP(ip);
+            GETIP(ip, x7);
             STORE_XEMU_CALL(x3);
             CALL(native_ud, -1, 0, 0);
             LOAD_XEMU_CALL();
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index fc939557..3bffea83 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -1403,7 +1403,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     OR(x2, x2, x7);
                     if (BOX64ENV(dynarec_div0)) {
                         BNE_MARK3(ed, xZR);
-                        GETIP_(ip);
+                        GETIP_(ip, x7);
                         STORE_XEMU_CALL(x6);
                         CALL(native_div0, -1, 0, 0);
                         CLEARIP();
@@ -1424,7 +1424,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     GETSEW(x1, 0);
                     if (BOX64ENV(dynarec_div0)) {
                         BNE_MARK3(ed, xZR);
-                        GETIP_(ip);
+                        GETIP_(ip, x7);
                         STORE_XEMU_CALL(x6);
                         CALL(native_div0, -1, 0, 0);
                         CLEARIP();
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c
index 8f53ceb3..1a7d0f97 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.c
+++ b/src/dynarec/rv64/dynarec_rv64_helper.c
@@ -90,13 +90,13 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
                 ret = xRIP;
                 *fixaddress = tmp + adj;
             } else if (i12 && (tmp >= -2048) && (tmp <= maxval)) {
-                GETIP(addr + delta);
+                GETIP(addr + delta, scratch);
                 ret = xRIP;
                 *fixaddress = tmp;
             } else if (adj && (tmp + adj >= -2048) && (tmp + adj <= maxval)) {
                 ADDI(ret, xRIP, tmp + adj);
             } else if ((tmp >= -2048) && (tmp <= maxval)) {
-                GETIP(addr + delta);
+                GETIP(addr + delta, scratch);
                 ADDI(ret, xRIP, tmp);
             } else if (tmp + addr + delta < 0x100000000LL) {
                 MOV64x(ret, tmp + addr + delta);
@@ -105,7 +105,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
                     MOV64x(ret, tmp + adj);
                 } else {
                     MOV64x(ret, tmp);
-                    GETIP(addr + delta);
+                    GETIP(addr + delta, scratch);
                 }
                 ADD(ret, ret, xRIP);
             }
@@ -390,7 +390,7 @@ uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop
             uint32_t tmp = F32;
             // no need to zero up, as we did it below
             rv64_move32(dyn, ninst, ret, tmp, 0);
-            GETIP(addr + delta);
+            GETIP(addr + delta, scratch);
             ADDW(ret, ret, xRIP);
             ZEROUP(ret);
             switch (lock) {
@@ -490,7 +490,7 @@ void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
             MV(xRIP, reg);
         }
     } else {
-        GETIP_(ip);
+        GETIP_(ip, x2);
     }
     TABLE64(x2, (uintptr_t)rv64_epilog);
     SMEND();
@@ -509,7 +509,7 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
             MV(xRIP, reg);
         }
     } else {
-        GETIP_(ip);
+        GETIP_(ip, x2);
     }
     TABLE64(x2, (uintptr_t)rv64_epilog_fast);
     SMEND();
@@ -590,8 +590,8 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3
     } else {
         uintptr_t p = getJumpTableAddress64(ip);
         MAYUSE(p);
+        GETIP_(ip, x3);
         TABLE64(x3, p);
-        GETIP_(ip);
         LD(x2, x3, 0);
     }
     CLEARIP();
diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h
index 2b8a6d42..5669406f 100644
--- a/src/dynarec/rv64/dynarec_rv64_helper.h
+++ b/src/dynarec/rv64/dynarec_rv64_helper.h
@@ -1107,26 +1107,31 @@
     dyn->vector_sew = VECTOR_SEWNA;
 
 #if STEP < 2
-#define GETIP(A)  MOV64x(xRIP, A)
-#define GETIP_(A) MOV64x(xRIP, A)
+#define GETIP(A, scratch)
+#define GETIP_(A, scratch)
 #else
-// put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later...
-#define GETIP(A)                                       \
-    if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) { \
-        uint64_t _delta_ip = (A) - dyn->last_ip;       \
-        dyn->last_ip += _delta_ip;                     \
-        if (_delta_ip) ADDI(xRIP, xRIP, _delta_ip);    \
-    } else {                                           \
-        dyn->last_ip = (A);                            \
-        MOV64x(xRIP, (A));                             \
-    }
-#define GETIP_(A)                                      \
-    if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) { \
-        int64_t _delta_ip = (A) - dyn->last_ip;        \
-        if (_delta_ip) ADDI(xRIP, xRIP, _delta_ip);    \
-    } else {                                           \
-        MOV64x(xRIP, (A));                             \
-    }
+#define GETIP_(A, scratch)                                        \
+    do {                                                          \
+        ssize_t _delta_ip = (ssize_t)(A) - (ssize_t)dyn->last_ip; \
+        if (!dyn->last_ip) {                                      \
+            MOV64x(xRIP, A);                                      \
+        } else if (_delta_ip == 0) {                              \
+        } else if (_delta_ip >= -2048 && _delta_ip < 2048) {      \
+            ADDI(xRIP, xRIP, _delta_ip);                          \
+        } else if (_delta_ip < 0 && _delta_ip >= -0xffffffff) {   \
+            MOV32w(scratch, -_delta_ip);                          \
+            SUB(xRIP, xRIP, scratch);                             \
+        } else if (_delta_ip > 0 && _delta_ip <= 0xffffffff) {    \
+            MOV32w(scratch, _delta_ip);                           \
+            ADD(xRIP, xRIP, scratch);                             \
+        } else {                                                  \
+            MOV64x(xRIP, (A));                                    \
+        }                                                         \
+    } while (0)
+#define GETIP(A, scratch) \
+    GETIP_(A, scratch);   \
+    dyn->last_ip = (A);
+
 #endif
 #define CLEARIP() dyn->last_ip = 0
 
diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h
index b39a589b..99281462 100644
--- a/src/dynarec/rv64/dynarec_rv64_private.h
+++ b/src/dynarec/rv64/dynarec_rv64_private.h
@@ -204,7 +204,7 @@ int Table64(dynarec_rv64_t *dyn, uint64_t val, int pass);  // add a value to tab
 void CreateJmpNext(void* addr, void* next);
 
 #define GO_TRACE(A, B, s0) \
-    GETIP(addr);           \
+    GETIP(addr, s0);       \
     MV(x1, xRIP);          \
     STORE_XEMU_CALL(s0);   \
     MOV64x(x2, B);         \