diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 098c3072d..5b5a253bc 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -3162,10 +3162,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ADR_S20(x4, j64); 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); - LDRx_U12(x4, x4, 0); + j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0; + ADR_S20(x4, j64); + MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); } STPx_S7_preindex(x4, x2, xSP, -16); } else { @@ -3177,6 +3176,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin 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); + LDRx_U12(x4, x4, 0); + BR(x4); + } break; } break; @@ -3674,15 +3681,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ADR_S20(x4, j64); 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); - LDRx_U12(x4, x4, 0); + j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0; + ADR_S20(x4, j64); + MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); } STPx_S7_preindex(x4, xRIP, xSP, -16); } 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); + LDRx_U12(x4, x4, 0); + BR(x4); + } break; case 3: // CALL FAR Ed if(MODREG) { diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index f4ed24833..dab72e9cd 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -1349,15 +1349,22 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ADR_S20(x4, j64); 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); - LDRx_U12(x4, x4, 0); + j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0; + ADR_S20(x4, j64); + MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); } STPx_S7_preindex(x4, xRIP, xSP, -16); } 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); + LDRx_U12(x4, x4, 0); + BR(x4); + } break; case 4: // JMP Ed INST_NAME("JMP Ed"); diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index 117e090a4..111bcf8e5 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1541,15 +1541,22 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin ADR_S20(x4, j64); 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); - LDRx_U12(x4, x4, 0); + j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0; + ADR_S20(x4, j64); + MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); } STPx_S7_preindex(x4, xRIP, xSP, -16); } 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); + LDRx_U12(x4, x4, 0); + BR(x4); + } break; default: DEFAULT; diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index 3003829fc..3e6c0f993 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"); diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 146645ae6..e1804f21f 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -957,10 +957,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ADDI(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(x4, x4, 0); + j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0; + AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff); + ADDI(x4, x4, j64 & 0xfff); + MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); } ADDI(xSP, xSP, -16); SD(x4, xSP, 0); @@ -974,6 +974,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int 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(x4, x4, 0); + BR(x4); + } break; } break; @@ -1443,10 +1451,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ADDI(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(x4, x4, 0); + j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0; + AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff); + ADDI(x4, x4, j64 & 0xfff); + MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2); } ADDI(xSP, xSP, -16); SD(x4, xSP, 0); @@ -1454,6 +1462,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } 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(x4, x4, 0); + BR(x4); + } break; case 4: // JMP Ed INST_NAME("JMP Ed"); diff --git a/src/dynarec/rv64/rv64_prolog.S b/src/dynarec/rv64/rv64_prolog.S index 1ca425fcf..67af8253a 100644 --- a/src/dynarec/rv64/rv64_prolog.S +++ b/src/dynarec/rv64/rv64_prolog.S @@ -67,4 +67,4 @@ rv64_prolog: xori x5, x0, -1 srli x5, x5, 32 // jump to block - jalr a1 + jr a1