about summary refs log tree commit diff stats
path: root/src/dynarec/la64
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-10-07 22:57:47 +0800
committerGitHub <noreply@github.com>2024-10-07 16:57:47 +0200
commit4c69bcd97aff691b464f01ebed057cfcb912612b (patch)
tree3dbf5c2aad18598a6306d5b3ed9e324f66a593d8 /src/dynarec/la64
parent05aac0879e415b99225d731e154bc5d6535c1d15 (diff)
downloadbox64-4c69bcd97aff691b464f01ebed057cfcb912612b.tar.gz
box64-4c69bcd97aff691b464f01ebed057cfcb912612b.zip
[DYNAREC] Optimized CALL/RET RAS for out of dynablock jumps (#1909)
Diffstat (limited to 'src/dynarec/la64')
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index 3003829f..3e6c0f99 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -2030,10 +2030,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             ADDI_D(x4, x4, j64 & 0xfff);
                             MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
                         } else {
-                            MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
-                            j64 = getJumpTableAddress64(addr);
-                            TABLE64(x4, j64);
-                            LD_D(x4, x4, 0);
+                            j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
+                            PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
+                            ADDI_D(x4, x4, j64 & 0xfff);
+                            MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
                         }
                         ADDI_D(xSP, xSP, -16);
                         ST_D(x4, xSP, 0);
@@ -2047,6 +2047,14 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     else
                         j64 = addr+i32;
                     jump_to_next(dyn, j64, 0, ninst, rex.is32bits);
+                    if(box64_dynarec_callret && addr >= (dyn->start + dyn->isize)) {
+                        // jumps out of current dynablock...
+                        MARK;
+                        j64 = getJumpTableAddress64(addr);
+                        TABLE64(x4, j64);
+                        LD_D(x4, x4, 0);
+                        BR(x4);
+                    }
                     break;
             }
             break;
@@ -2371,10 +2379,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             ADDI_D(x4, x4, j64 & 0xfff);
                             MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
                         } else {
-                            MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
-                            j64 = getJumpTableAddress64(addr);
-                            TABLE64(x4, j64);
-                            LD_D(x4, x4, 0);
+                            j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
+                            PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
+                            ADDI_D(x4, x4, j64 & 0xfff);
+                            MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
                         }
                         ADDI_D(xSP, xSP, -16);
                         ST_D(x4, xSP, 0);
@@ -2382,6 +2390,14 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     }
                     PUSH1z(xRIP);
                     jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
+                    if(box64_dynarec_callret && addr >= (dyn->start + dyn->isize)) {
+                        // jumps out of current dynablock...
+                        MARK;
+                        j64 = getJumpTableAddress64(addr);
+                        TABLE64(x4, j64);
+                        LD_D(x4, x4, 0);
+                        BR(x4);
+                    }
                     break;
                 case 4: // JMP Ed
                     INST_NAME("JMP Ed");