about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-06-27 15:17:06 +0800
committerGitHub <noreply@github.com>2025-06-27 09:17:06 +0200
commitf6bb7310bb3fed9d4a5b7456c5b0860bb753ec54 (patch)
tree12cbf5d9a96a64fe95cffd80d47ece63a772f820
parentd57416f4fb2b75a573e9731c1b33d0c9a1bea234 (diff)
downloadbox64-f6bb7310bb3fed9d4a5b7456c5b0860bb753ec54.tar.gz
box64-f6bb7310bb3fed9d4a5b7456c5b0860bb753ec54.zip
[LA64_DYNAREC] Optimized GETIP macro (#2781)
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c24
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c4
-rw-r--r--src/dynarec/la64/dynarec_la64_66.c4
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.c14
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h52
-rw-r--r--src/dynarec/la64/dynarec_la64_private.h2
6 files changed, 49 insertions, 51 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index 1fd49564..9f229883 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -669,7 +669,7 @@ uintptr_t dynarec64_00(dynarec_la64_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();
             CALL(const_native_priv, -1);
             LOAD_XEMU_CALL();
@@ -685,7 +685,7 @@ uintptr_t dynarec64_00(dynarec_la64_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();
             CALL(const_native_priv, -1);
             LOAD_XEMU_CALL();
@@ -1979,7 +1979,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
                     // FIXME: Even the basic support of isSimpleWrapper is disabled for now.
 
-                    GETIP(ip + 1); // read the 0xCC
+                    GETIP(ip + 1, x7); // read the 0xCC
                     STORE_XEMU_CALL();
                     ADDI_D(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
                     CALL_S(const_int3, -1);
@@ -2000,7 +2000,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     MOV32w(x2, offsetof(box64context_t, signals[SIGTRAP]));
                     LDX_D(x3, x1, x2);
                     BEQZ_MARK(x3);
-                    GETIP(addr);
+                    GETIP(addr, x7);
                     STORE_XEMU_CALL();
                     CALL(const_native_int3, -1);
                     LOAD_XEMU_CALL();
@@ -2017,7 +2017,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 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();
                 MOV32w(x1, u8);
                 CALL(const_native_int, -1);
@@ -2026,7 +2026,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 INST_NAME("32bits SYSCALL");
                 NOTEST(x1);
                 SMEND();
-                GETIP(addr);
+                GETIP(addr, x7);
                 STORE_XEMU_CALL();
                 CALL_S(const_x86syscall, -1);
                 LOAD_XEMU_CALL();
@@ -2044,7 +2044,7 @@ uintptr_t dynarec64_00(dynarec_la64_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(addr);
+                GETIP(addr, x7);
                 STORE_XEMU_CALL();
                 CALL(const_native_int3, -1);
                 LOAD_XEMU_CALL();
@@ -2058,7 +2058,7 @@ uintptr_t dynarec64_00(dynarec_la64_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); // priviledged instruction, IP not updated
+                GETIP(ip, x7); // priviledged instruction, IP not updated
                 STORE_XEMU_CALL();
                 CALL(const_native_priv, -1);
                 LOAD_XEMU_CALL();
@@ -2401,12 +2401,12 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     //     // 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
+                        // GETIP(ip+3+8+8, x7); // read the 0xCC
                         // FIXME: 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();
                         ADDI_D(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
                         CALL_S(const_int3, -1);
@@ -2535,7 +2535,7 @@ uintptr_t dynarec64_00(dynarec_la64_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();
             CALL(const_native_priv, -1);
             LOAD_XEMU_CALL();
@@ -2855,7 +2855,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         *need_epilog = 0;
                         *ok = 0;
                     }
-                    GETIP_(addr);
+                    GETIP_(addr, x7);
                     if (BOX64DRENV(dynarec_callret)) {
                         SET_HASCALLRET();
                         // Push actual return address
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index a8601aa7..2d009170 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -86,7 +86,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             INST_NAME("SYSCALL");
             NOTEST(x1);
             SMEND();
-            GETIP(addr);
+            GETIP(addr, x7);
             STORE_XEMU_CALL();
             CALL_S(const_x64syscall, -1);
             LOAD_XEMU_CALL();
@@ -105,7 +105,7 @@ uintptr_t dynarec64_0F(dynarec_la64_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();
             CALL(const_native_ud, -1);
             LOAD_XEMU_CALL();
diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c
index b4d1e50d..109683d3 100644
--- a/src/dynarec/la64/dynarec_la64_66.c
+++ b/src/dynarec/la64/dynarec_la64_66.c
@@ -968,7 +968,7 @@ uintptr_t dynarec64_66(dynarec_la64_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, x6);
                         STORE_XEMU_CALL();
                         CALL(const_native_div0, -1);
                         CLEARIP();
@@ -989,7 +989,7 @@ uintptr_t dynarec64_66(dynarec_la64_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();
                         CALL(const_native_div0, -1);
                         CLEARIP();
diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c
index ddc51082..6efc7bfb 100644
--- a/src/dynarec/la64/dynarec_la64_helper.c
+++ b/src/dynarec/la64/dynarec_la64_helper.c
@@ -94,13 +94,13 @@ uintptr_t geted(dynarec_la64_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_D(ret, xRIP, tmp + adj);
             } else if ((tmp >= -2048) && (tmp <= maxval)) {
-                GETIP(addr + delta);
+                GETIP(addr + delta, scratch);
                 ADDI_D(ret, xRIP, tmp);
             } else if (tmp + addr + delta < 0x100000000LL) {
                 MOV64x(ret, tmp + addr + delta);
@@ -109,7 +109,7 @@ uintptr_t geted(dynarec_la64_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_D(ret, ret, xRIP);
             }
@@ -400,7 +400,7 @@ uintptr_t geted32(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop
             uint32_t tmp = F32;
             // no need to zero up, as we did it below
             la64_move32(dyn, ninst, ret, tmp, 0);
-            GETIP(addr + delta);
+            GETIP(addr + delta, scratch);
             ADD_W(ret, ret, xRIP);
             ZEROUP(ret);
             switch (lock) {
@@ -500,7 +500,7 @@ void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst)
             MV(xRIP, reg);
         }
     } else {
-        GETIP_(ip);
+        GETIP_(ip, x2);
     }
     TABLE64C(x2, const_epilog);
     SMEND();
@@ -519,7 +519,7 @@ void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst)
             MV(xRIP, reg);
         }
     } else {
-        GETIP_(ip);
+        GETIP_(ip, x2);
     }
     TABLE64C(x2, const_epilog_fast);
     SMEND();
@@ -569,8 +569,8 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3
         NOTEST(x2);
         uintptr_t p = getJumpTableAddress64(ip);
         MAYUSE(p);
+        GETIP_(ip, x3);
         TABLE64(x3, p);
-        GETIP_(ip);
         LD_D(x2, x3, 0);
         dest = x2;
     }
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index b75e1f84..48387125 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -1031,34 +1031,32 @@
 #define ARCH_RESET()
 
 #if STEP < 2
-#define GETIP(A)  TABLE64(0, 0)
-#define GETIP_(A) TABLE64(0, 0)
+#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_D(xRIP, xRIP, _delta_ip);             \
-        }                                              \
-    } else {                                           \
-        dyn->last_ip = (A);                            \
-        if (dyn->last_ip < 0xffffffff) {               \
-            MOV64x(xRIP, dyn->last_ip);                \
-        } else                                         \
-            TABLE64(xRIP, dyn->last_ip);               \
-    }
-#define GETIP_(A)                                         \
-    if (dyn->last_ip && ((A) - dyn->last_ip) < 2048) {    \
-        int64_t _delta_ip = (A) - dyn->last_ip;           \
-        if (_delta_ip) { ADDI_D(xRIP, xRIP, _delta_ip); } \
-    } else {                                              \
-        if ((A) < 0xffffffff) {                           \
-            MOV64x(xRIP, (A));                            \
-        } else                                            \
-            TABLE64(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_D(xRIP, xRIP, _delta_ip);                        \
+        } else if (_delta_ip < 0 && _delta_ip >= -0xffffffff) {   \
+            MOV32w(scratch, -_delta_ip);                          \
+            SUB_D(xRIP, xRIP, scratch);                           \
+        } else if (_delta_ip > 0 && _delta_ip <= 0xffffffff) {    \
+            MOV32w(scratch, _delta_ip);                           \
+            ADD_D(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/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h
index 5b25edb9..27aac66d 100644
--- a/src/dynarec/la64/dynarec_la64_private.h
+++ b/src/dynarec/la64/dynarec_la64_private.h
@@ -185,7 +185,7 @@ int Table64(dynarec_la64_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(A1, xRIP);          \
     STORE_XEMU_CALL();     \
     MOV64x(A2, B);         \