diff --git a/configurator/model.py b/configurator/model.py index 2c92583da..cf6870740 100644 --- a/configurator/model.py +++ b/configurator/model.py @@ -103,6 +103,7 @@ PROFILE_SETTINGS = { ("BOX64_DYNAREC_BIGBLOCK", "0"), ("BOX64_DYNAREC_SAFEFLAGS", "2"), ("BOX64_DYNAREC_STRONGMEM", "2"), + ("BOX64_DYNAREC_CALLRET", "3"), ), "safe": ( ("BOX64_DYNAREC_BIGBLOCK", "0"), diff --git a/docs/USAGE.md b/docs/USAGE.md index 2b0f2932f..2bbd6ab62 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -80,7 +80,7 @@ Optimize CALL/RET opcodes. Available in WowBox64. * 0: Do not optimize CALL/RET, use jump table. * 1: Try to optimize CALL/RET, skipping the jump table when possible. * 2: Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle return to dirty/modified block. Does not work on WowBox64. [Default] - * 3: Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now. + * 3: Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use. ### BOX64_DYNAREC_DF diff --git a/docs/USAGE_CN.md b/docs/USAGE_CN.md index f7ec7edd6..f93c8f083 100644 --- a/docs/USAGE_CN.md +++ b/docs/USAGE_CN.md @@ -80,7 +80,7 @@ BOX64_DYNAREC_CALLRET=1 * 0: 不优化 CALL/RET,使用跳转表。 * 1: 尝试优化 CALL/RET,在可能的情况下跳过跳转表。 * 2: 尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。 [默认值] - * 3: 在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。 + * 3: 在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。 ### BOX64_DYNAREC_DF diff --git a/docs/box64.pod b/docs/box64.pod index 83621c376..40fc9f3e9 100644 --- a/docs/box64.pod +++ b/docs/box64.pod @@ -175,7 +175,7 @@ Optimize CALL/RET opcodes. Available in WowBox64. * 0 : Do not optimize CALL/RET, use jump table. * 1 : Try to optimize CALL/RET, skipping the jump table when possible. * 2 : Try to optimize CALL/RET, skipping the jump table when possible, adding code to handle return to dirty/modified block. Does not work on WowBox64. [Default] - * 3 : Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now. + * 3 : Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use. =item B =I<0|1> diff --git a/docs/gen/usage.json b/docs/gen/usage.json index e259d3ef7..1d0f49e17 100644 --- a/docs/gen/usage.json +++ b/docs/gen/usage.json @@ -309,7 +309,7 @@ }, { "key": "3", - "description": "Same as 2, with leaf call analysis that tries to duplicate leaf bodies into their callers. Only available for LoongArch for now.", + "description": "Same as 2, but also track dynablock usage so blocks are not reclaimed while still in use.", "default": false } ] diff --git a/docs/gen/usage_cn.json b/docs/gen/usage_cn.json index 7292afb68..7833debcf 100644 --- a/docs/gen/usage_cn.json +++ b/docs/gen/usage_cn.json @@ -107,7 +107,7 @@ "0": "不优化 CALL/RET,使用跳转表。", "1": "尝试优化 CALL/RET,在可能的情况下跳过跳转表。", "2": "尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。", - "3": "在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。" + "3": "在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。" } }, "BOX64_DYNAREC_DF": { diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 27c777185..ac4f39b8c 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -349,7 +349,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -425,7 +425,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32 if(reg!=x1) { MOVx_REG(x1, xRIP); } - if(BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if(BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // #ifdef HAVE_TRACE // The BLR form is only for gdb backtraces, but it breaks the @@ -451,7 +451,7 @@ void ret_to_next(dynarec_arm_t* dyn, uintptr_t ip, int ninst, rex_t rex) // pop the actual return address for ARM stack LDPx_S7_postindex(xLR, x6, xSP, 16); SUBx_REG(x6, x6, xRIP); // is it the right address? - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x3); CBNZx(x6, 2*4); RET(xLR); diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index d81e7f352..4f470b10f 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -325,8 +325,10 @@ int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size) void dynablock_leave_runtime(dynablock_t* db) { if(!db) return; - if(BOX64ENV(dynarec_callret) < 2) return; +#ifdef HAVE_IN_USED + if(BOX64ENV(dynarec_callret) < 3) return; __atomic_fetch_sub(&db->in_used, 1, __ATOMIC_ACQ_REL); +#endif } dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits) diff --git a/src/dynarec/dynarec_arch.h b/src/dynarec/dynarec_arch.h index 729e24d39..8c55c93e6 100644 --- a/src/dynarec/dynarec_arch.h +++ b/src/dynarec/dynarec_arch.h @@ -8,6 +8,8 @@ #define dynarec_native_t dynarec_arm_t #define extcache_native_t neoncache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); @@ -49,12 +51,12 @@ extern void arm64_next_invalid(); #define PRINT_OPCODE(C, A) arm64_print(C, A) #elif defined(LA64) -#define HAVE_LEAFCALL - #define instruction_native_t instruction_la64_t #define dynarec_native_t dynarec_la64_t #define extcache_native_t lsxcache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); @@ -98,6 +100,8 @@ extern void la64_next_invalid(); #define dynarec_native_t dynarec_rv64_t #define extcache_native_t extcache_t +#define HAVE_IN_USED + #define ADDITIONNAL_DEFINITION() \ int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); \ int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst); diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index 3c80f848e..24c89af58 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -416,347 +416,6 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); -#ifdef HAVE_LEAFCALL -#define LEAFCALL_MAX_INSTS 128 -#define LEAFCALL_MAX_BYTES 4096 -#define LEAFCALL_MAX_EMBEDDEDS 32 -#define LEAFCALL_MAX_TOTAL_INSTS 512 - -typedef struct leafcall_peek_s { - dynarec_native_t dyn; - instruction_native_t insts[LEAFCALL_MAX_INSTS + 2]; - int jmps[LEAFCALL_MAX_INSTS + 2]; - uintptr_t next[LEAFCALL_MAX_INSTS + 2]; -} leafcall_peek_t; - -typedef struct leafcall_analysis_s { - uintptr_t work[LEAFCALL_MAX_INSTS]; - uintptr_t decoded[LEAFCALL_MAX_INSTS]; - uint8_t decoded_len[LEAFCALL_MAX_INSTS]; - instruction_native_t* decoded_inst; - uintptr_t body_start; - uintptr_t body_end; - int work_size; - int decoded_size; - int saw_ret; - int reads_rsp; - int implicit_rsp; - int failed; -} leafcall_analysis_t; - -typedef struct leaf_embedded_s { - dynarec_native_t dyn; -} leaf_embedded_t; - -static leaf_embedded_t static_leaf_embeddeds[LEAFCALL_MAX_EMBEDDEDS]; -static instruction_native_t static_leafinsts[LEAFCALL_MAX_TOTAL_INSTS + LEAFCALL_MAX_EMBEDDEDS]; -static int static_leafjmps[LEAFCALL_MAX_TOTAL_INSTS]; -static int static_leafpreds[LEAFCALL_MAX_TOTAL_INSTS * 2]; -static instsize_t static_leaf_instsize[LEAFCALL_INSTSIZE_SCRATCH]; -static int static_leaf_embedded_count; -static int static_leafinst_count; -static int static_leafdecoded_count; -static int static_leafpred_count; - -static int leafcall_readable(uintptr_t addr, uintptr_t size) -{ - if (!size) - return 1; - uintptr_t end = addr + size - 1; - if (end < addr) - return 0; - uintptr_t cur = addr; - while (1) { - uint32_t prot = getProtection(cur); - if ((prot & (PROT_READ | PROT_EXEC)) != (PROT_READ | PROT_EXEC)) - return 0; - uintptr_t page_end = (cur & ~(box64_pagesize - 1)) + box64_pagesize - 1; - if (end <= page_end) - return 1; - cur = page_end + 1; - } -} - -static int leafcall_seen(const leafcall_analysis_t* scan, uintptr_t addr) -{ - for (int i = 0; i < scan->decoded_size; ++i) - if (scan->decoded[i] == addr) - return 1; - return 0; -} - -static int leafcall_queue_jump(leafcall_analysis_t* scan, uintptr_t addr, uintptr_t continuation) -{ - if (!addr || addr == continuation) - return 0; - if (addr < scan->body_start || addr >= scan->body_end) - return 0; - if (leafcall_seen(scan, addr)) - return 1; - for (int i = 0; i < scan->work_size; ++i) - if (scan->work[i] == addr) - return 1; - if (scan->work_size >= LEAFCALL_MAX_INSTS) - return 0; - scan->work[scan->work_size++] = addr; - return 1; -} - -static int leafcall_check_segment(leafcall_analysis_t* scan, uintptr_t entry, uintptr_t continuation, int is32bits) -{ - if (!leafcall_readable(entry, 1) || leafcall_seen(scan, entry)) - return leafcall_seen(scan, entry); - - leafcall_peek_t peek; - memset(&peek, 0, sizeof(peek)); - dynarec_native_t* dyn = &peek.dyn; - dyn->start = entry; - dyn->end = entry + LEAFCALL_MAX_BYTES; - if (dyn->end < entry) - return 0; - uintptr_t mapped = SizeFileMapped(entry); - if (mapped && mapped < LEAFCALL_MAX_BYTES) - dyn->end = entry + mapped; - dyn->cap = LEAFCALL_MAX_INSTS + 2; - dyn->insts = peek.insts; - dyn->jmp_cap = LEAFCALL_MAX_INSTS + 2; - dyn->jmps = peek.jmps; - dyn->next_cap = LEAFCALL_MAX_INSTS + 2; - dyn->next = peek.next; - dyn->env = GetCurEnvByAddr(entry); - dyn->is_file_mapped = IsAddrElfOrFileMapped(entry); - dyn->peeking_flags = 1; - - uintptr_t end = native_pass0(dyn, entry, 0, is32bits, LEAFCALL_MAX_INSTS); - if (dyn->size <= 0 || dyn->size > LEAFCALL_MAX_INSTS || end < entry) - return 0; - - for (int i = 0; i < dyn->size; ++i) { - instruction_x64_t* inst = &dyn->insts[i].x64; - uintptr_t ip = inst->addr; - uintptr_t next = (i + 1 < dyn->size) ? dyn->insts[i + 1].x64.addr : end; - if (ip == continuation || ip < scan->body_start || next > scan->body_end) - return 0; - if (leafcall_seen(scan, ip)) - continue; - if (scan->decoded_size >= LEAFCALL_MAX_INSTS) - return 0; - scan->decoded[scan->decoded_size] = ip; - scan->decoded_len[scan->decoded_size] = next - ip; - if (scan->decoded_inst) { - scan->decoded_inst[scan->decoded_size] = dyn->insts[i]; - scan->decoded_inst[scan->decoded_size].pred = NULL; - scan->decoded_inst[scan->decoded_size].pred_sz = 0; - } - ++scan->decoded_size; - - if (dyn->insts[i].host_call) - return 0; - - if (inst->leaf_kind == LEAF_KIND_CALL) - return 0; - - int implicit_rsp = (inst->leaf_rsp & LEAF_RSP_PUSHPOP) ? 1 : 0; - if (implicit_rsp) scan->implicit_rsp = 1; - - if (inst->leaf_kind == LEAF_KIND_RET) { - scan->saw_ret = 1; - continue; - } - - uint16_t sp_bits = (dyn->insts[i].up32_read | dyn->insts[i].up32_write64 | dyn->insts[i].up32_write32 | dyn->insts[i].up32_zero) & (1u << _SP); - if ((inst->leaf_rsp & LEAF_RSP_REF) || (!implicit_rsp && sp_bits)) - scan->reads_rsp = 1; - - if (!inst->has_next) { - if (!inst->jmp || inst->jmp_cond) - return 0; - if (!leafcall_queue_jump(scan, inst->jmp, continuation)) - return 0; - continue; - } - if (inst->jmp) { - if (!inst->jmp_cond || !leafcall_queue_jump(scan, inst->jmp, continuation)) - return 0; - } - } - return 1; -} - -static int leafcall_analyze_leaf(leafcall_analysis_t* scan, uintptr_t target, uintptr_t continuation, int is32bits, instruction_native_t* decoded_inst) -{ - memset(scan, 0, sizeof(*scan)); - scan->decoded_inst = decoded_inst; - scan->body_start = target; - scan->body_end = target + LEAFCALL_MAX_BYTES; - if (scan->body_end < target) - return 0; - uintptr_t mapped = SizeFileMapped(target); - if (mapped && mapped < LEAFCALL_MAX_BYTES) - scan->body_end = target + mapped; - scan->work[scan->work_size++] = target; - while (scan->work_size && !scan->failed) { - uintptr_t entry = scan->work[--scan->work_size]; - if (!leafcall_check_segment(scan, entry, continuation, is32bits)) - scan->failed = 1; - } - if (scan->failed || !scan->saw_ret || !scan->decoded_size) - return 0; - - for (int i = 1; i < scan->decoded_size; ++i) { - uintptr_t addr = scan->decoded[i]; - uint8_t len = scan->decoded_len[i]; - instruction_native_t inst; - if (decoded_inst) - inst = decoded_inst[i]; - int j = i; - while (j && scan->decoded[j - 1] > addr) { - scan->decoded[j] = scan->decoded[j - 1]; - scan->decoded_len[j] = scan->decoded_len[j - 1]; - if (decoded_inst) - decoded_inst[j] = decoded_inst[j - 1]; - --j; - } - scan->decoded[j] = addr; - scan->decoded_len[j] = len; - if (decoded_inst) - decoded_inst[j] = inst; - } - if (scan->decoded[0] != target) - return 0; - for (int i = 1; i < scan->decoded_size; ++i) - if (scan->decoded[i] < scan->decoded[i - 1] + scan->decoded_len[i - 1]) - return 0; - return 1; -} - -static int leaf_embedded_find(const instruction_native_t* insts, int size, uintptr_t addr) -{ - int low = 0; - int high = size - 1; - while (low <= high) { - int mid = (low + high) / 2; - if (insts[mid].x64.addr == addr) - return mid; - if (insts[mid].x64.addr < addr) - low = mid + 1; - else - high = mid - 1; - } - return -1; -} - -static int leaf_embedded_build(uintptr_t target, uintptr_t continuation, int is32bits, uint8_t* embedded_id) -{ - instruction_native_t decoded[LEAFCALL_MAX_INSTS + 2]; - leafcall_analysis_t scan; - if (!embedded_id || static_leaf_embedded_count >= LEAFCALL_MAX_EMBEDDEDS || BOX64ENV(dynarec_test) || BOX64ENV(dynarec_trace)) - return 0; -#ifdef HAVE_ALTJUMP - if (getAlternateJump((void*)target, is32bits)) - return 0; -#endif - if (!leafcall_analyze_leaf(&scan, target, continuation, is32bits, decoded)) - return 0; - if (static_leafdecoded_count + scan.decoded_size > LEAFCALL_MAX_TOTAL_INSTS || static_leafinst_count + scan.decoded_size + 1 > (int)(sizeof(static_leafinsts) / sizeof(static_leafinsts[0]))) - return 0; - - leaf_embedded_t* embedded = &static_leaf_embeddeds[static_leaf_embedded_count]; - memset(embedded, 0, sizeof(*embedded)); - dynarec_native_t* leaf = &embedded->dyn; - leaf->insts = &static_leafinsts[static_leafinst_count]; - memcpy(leaf->insts, decoded, scan.decoded_size * sizeof(decoded[0])); - memset(&leaf->insts[scan.decoded_size], 0, sizeof(leaf->insts[scan.decoded_size])); - leaf->size = scan.decoded_size; - leaf->cap = scan.decoded_size + 1; - leaf->start = target; - leaf->end = scan.decoded[scan.decoded_size - 1] + scan.decoded_len[scan.decoded_size - 1]; - leaf->isize = leaf->end - target; - leaf->env = GetCurEnvByAddr(target); - leaf->is_file_mapped = IsAddrElfOrFileMapped(target); - leaf->peeking_flags = 2; - leaf->inline_leaf = 1; - leaf->inline_is32bits = is32bits; - leaf->inline_rsp = scan.reads_rsp ? 0 : (scan.implicit_rsp ? (is32bits ? 4 : 8) : -(is32bits ? 4 : 8)); - leaf->instsize = static_leaf_instsize; - leaf->jmps = &static_leafjmps[static_leafdecoded_count]; - leaf->jmp_cap = scan.decoded_size; - - for (int i = 0; i < leaf->size; ++i) { - instruction_native_t* inst = &leaf->insts[i]; - inst->x64.size = scan.decoded_len[i]; - inst->x64.alive = 0; - inst->x64.jmp_insts = -1; - inst->pred = NULL; - inst->pred_sz = 0; - if (inst->x64.has_next) { - if (i + 1 >= leaf->size || inst->x64.addr + inst->x64.size != leaf->insts[i + 1].x64.addr) - return 0; - } - if (inst->x64.jmp) { - int target_inst = leaf_embedded_find(leaf->insts, leaf->size, inst->x64.jmp); - if (target_inst < 0) - return 0; - inst->x64.jmp_insts = target_inst; - inst->barrier_maybe = 0; - leaf->jmps[leaf->jmp_sz++] = i; - } - int isret = (inst->x64.leaf_kind == LEAF_KIND_RET); - if (isret) - inst->x64.need_after |= X_PEND; - } - leaf->insts[leaf->size].x64.addr = leaf->end; - - sizePredecessors(leaf); - int predecessor_count = 0; - for (int i = 0; i < leaf->size; ++i) - predecessor_count += leaf->insts[i].pred_sz; - if (static_leafpred_count + predecessor_count > (int)(sizeof(static_leafpreds) / sizeof(static_leafpreds[0]))) - return 0; - leaf->predecessor = &static_leafpreds[static_leafpred_count]; - fillPredecessors(leaf); - for (int i = 0; i < leaf->size; ++i) - if (!leaf->insts[i].x64.alive) - return 0; - - PREUPDATE_SPECIFICS(leaf); - int pos = leaf->size - 1; - while (pos >= 0) - pos = updateNeed(leaf, pos, 0); - updateUpperLiveness(leaf); - updateRspMerge(leaf, is32bits); - UPDATE_SPECIFICS(leaf); - - static_leafinst_count += leaf->size + 1; - static_leafdecoded_count += leaf->size; - static_leafpred_count += predecessor_count; - *embedded_id = ++static_leaf_embedded_count; - return 1; -} - -static void leaf_embedded_reset(dynarec_native_t* dyn) -{ - static_leaf_embedded_count = 0; - static_leafinst_count = 0; - static_leafdecoded_count = 0; - static_leafpred_count = 0; - memset(static_leaf_embeddeds, 0, sizeof(static_leaf_embeddeds)); - dyn->leaf_embeddeds = static_leaf_embeddeds; -} - -void* dynarec_get_leaf_embedded(void* owner, int ninst) -{ - dynarec_native_t* dyn = owner; - if (!dyn || !dyn->leaf_embeddeds || ninst < 0 || ninst >= dyn->size) - return NULL; - int embedded_id = dyn->insts[ninst].x64.leaf_embedded; - if (embedded_id <= 0 || embedded_id > static_leaf_embedded_count) - return NULL; - leaf_embedded_t* embeddeds = dyn->leaf_embeddeds; - return &embeddeds[embedded_id - 1].dyn; -} -#endif - #define PEEK_FLAGS_INSTS 16 typedef struct peek_flags_state_s { @@ -948,9 +607,6 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, helper.next_cap = MAX_INSTS; helper.table64 = NULL; helper.env = GetCurEnvByAddr(addr); - #ifdef HAVE_LEAFCALL - leaf_embedded_reset(&helper); - #endif if(prot&PROT_NEVERCLEAN) { helper.always_test = 1; } @@ -1031,33 +687,6 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, state = BUILD_ABORT_EMPTY; continue; } - #ifdef HAVE_LEAFCALL - if (BOX64DRENV(dynarec_callret) >= 3) { - for (int i = 0; i < helper.size; ++i) { - instruction_x64_t* inst = &helper.insts[i].x64; - if (inst->leaf_kind != LEAF_KIND_CALL) - continue; - uintptr_t target = inst->leaf_target; - uintptr_t continuation = inst->addr + inst->size; - uint8_t embedded_id = 0; - if (!target || !inst->has_next || i + 1 >= helper.size || helper.insts[i + 1].x64.addr != continuation || !leaf_embedded_build(target, continuation, is32bits, &embedded_id)) - inst->leaf_call = 0; - else - inst->leaf_embedded = embedded_id; - } - for (int i = 0; i < helper.size; ++i) - if (helper.insts[i].x64.leaf_call) - helper.insts[i].x64.barrier = BARRIER_FLOAT; - } else { - for (int i = 0; i < helper.size; ++i) { - helper.insts[i].x64.leaf_call = 0; - helper.insts[i].x64.leaf_embedded = 0; - helper.insts[i].x64.leaf_kind = LEAF_KIND_NONE; - helper.insts[i].x64.leaf_rsp = 0; - helper.insts[i].x64.leaf_target = 0; - } - } - #endif if(!is_inhotpage && !isprotectedDB(addr, 1)) { dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr); state = BUILD_ABORT_NULL; diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 99453ee29..90c2917e5 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -119,11 +119,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int fpu_reset(dyn); ARCH_INIT(); int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n - #if defined(HAVE_LEAFCALL) - dyn->last_ip = (dyn->inline_leaf || alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of ordinary blocks unless there is a predecessor! - #else dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz)) ? 0 : ip; // RIP is always set at start of block unless there is a predecessor! - #endif int stopblock = 2 + !dyn->is_file_mapped; // if block is in elf memory or file mapped memory, it can be extended with BOX64DRENV(dynarec_bigblock)==2, else it needs 3 // ok, go now INIT; @@ -131,10 +127,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int uintptr_t cur_page = ALIGN_DOWN(addr); #endif while(ok) { - #if STEP > 0 && defined(HAVE_LEAFCALL) - if (dyn->inline_leaf) - addr = dyn->insts[ninst].x64.addr; - #endif #if STEP == 0 int stop_for_guard = 0; if(cur_page != (ALIGN_DOWN(addr))) { @@ -169,7 +161,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int ip = addr; #ifdef ARM64 if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if(dyn->always_test) checkCRC(dyn, 0); @@ -179,7 +171,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } #elif defined(LA64) if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if(dyn->always_test) checkCRC(dyn, 0); @@ -190,7 +182,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } #elif defined(RV64) if(!ninst) { - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doEnterBlock(dyn, 0, x1, x2, x3); if (dyn->insts[0].preload_xmmymm) doPreload(dyn, 0); @@ -342,12 +334,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int return ip; INST_EPILOG; - #if STEP == 0 && defined(HAVE_LEAFCALL) - if (!dyn->peeking_flags && BOX64DRENV(dynarec_callret) >= 3 && dyn->insts[ninst].x64.leaf_kind == LEAF_KIND_CALL && dyn->insts[ninst].x64.leaf_target) { - dyn->insts[ninst].x64.leaf_call = 1; - } - #endif - #if STEP > 1 if (dyn->insts[ninst].lock) DMB_ISH(); @@ -580,60 +566,3 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size); return addr; } - -#ifdef HAVE_LEAFCALL -void emit_inline_leaf(dynarec_native_t* parent, int parent_ninst) -{ - dynarec_native_t* leaf = dynarec_get_leaf_embedded(parent, parent_ninst); - if (!leaf) { - parent->abort = 1; - return; - } - - leaf->block = parent->block; - leaf->native_start = parent->native_start; - leaf->native_size = parent->native_size; - leaf->table64 = parent->table64; - leaf->table64size = parent->table64size; - leaf->table64cap = parent->table64cap; - leaf->tablestart = parent->tablestart; - leaf->jmp_next = parent->jmp_next; - leaf->dynablock = parent->dynablock; - leaf->callrets = parent->callrets; - leaf->callret_size = parent->callret_size; - leaf->need_dump = parent->need_dump; - leaf->need_reloc = parent->need_reloc; - leaf->relocs = parent->relocs; - leaf->reloc_size = parent->reloc_size; - leaf->inline_native_end = parent->insts[parent_ninst].mark[2]; - leaf->insts_size = 0; - leaf->abort = 0; - - size_t native_start = leaf->native_size; - native_pass(leaf, leaf->start, 0, leaf->inline_is32bits, leaf->size); - size_t native_delta = leaf->native_size - native_start; - - parent->block = leaf->block; - parent->native_size = leaf->native_size; - parent->table64size = leaf->table64size; - parent->callret_size = leaf->callret_size; - parent->reloc_size = leaf->reloc_size; - parent->abort |= leaf->abort; - - #if STEP == 1 - POSTUPDATE_SPECIFICS(leaf); - #elif STEP == 2 - parent->insts[parent_ninst].size += native_delta; - if (leaf->insts_size > LEAFCALL_INSTSIZE_SCRATCH) - parent->abort = 1; - #elif STEP == 3 - parent->insts[parent_ninst].size2 += native_delta; - for (int i = 0; i < leaf->size; ++i) { - if (!leaf->insts[i].x64.alive) - continue; - if (leaf->insts[i].size2 != leaf->insts[i].size) - parent->abort = 1; - } - #endif -} -#endif diff --git a/src/dynarec/dynarec_private.h b/src/dynarec/dynarec_private.h index bbd8e7350..86a44003c 100644 --- a/src/dynarec/dynarec_private.h +++ b/src/dynarec/dynarec_private.h @@ -36,12 +36,6 @@ #define NAT_FLAGS_FUSION 0 #define NAT_FLAGS_NOFUSION 1 -#define LEAF_KIND_NONE 0 -#define LEAF_KIND_CALL 1 -#define LEAF_KIND_RET 2 -#define LEAF_RSP_PUSHPOP 1 -#define LEAF_RSP_REF 2 - typedef struct instruction_x64_s { uintptr_t addr; //address of the instruction int32_t size; // size of the instruction @@ -50,7 +44,6 @@ typedef struct instruction_x64_s { uint8_t jmp_cond:1; // 1 of conditionnal jump uint8_t has_next:1; // does this opcode can continue to the next? uint8_t has_callret:1; // this instruction have an optimized call setup - uint8_t leaf_call:1; // direct call to a proven closed leaf body uint8_t alive:1; // this opcode gets executed (0 if dead code in that block) uint8_t self_loop:1; // this is a landing address for a self-loop (loop on itslef with no exit) uint8_t barrier; // next instruction is a jump point, so no optim allowed @@ -61,10 +54,6 @@ typedef struct instruction_x64_s { uint8_t gen_flags; // calculated uint8_t need_before;// calculated uint8_t need_after; // calculated - uint8_t leaf_embedded; - uint8_t leaf_kind; - uint8_t leaf_rsp; - uintptr_t leaf_target; uint8_t strongmem:3; // strongmem model at the opcode } instruction_x64_t; diff --git a/src/dynarec/la64/dynarec_la64_00_0.c b/src/dynarec/la64/dynarec_la64_00_0.c index 4bc033367..0ca58e983 100644 --- a/src/dynarec/la64/dynarec_la64_00_0.c +++ b/src/dynarec/la64/dynarec_la64_00_0.c @@ -105,7 +105,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); break; case 0x06: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH ES"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_ES])); @@ -126,7 +125,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x07: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP ES"); SMREAD(); @@ -195,7 +193,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4); break; case 0x0E: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH CS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_CS])); @@ -283,7 +280,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); break; case 0x16: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH SS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_SS])); @@ -304,7 +300,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x17: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP SS"); SMREAD(); @@ -380,7 +375,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; case 0x1E: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("PUSH DS"); LD_HU(x1, xEmu, offsetof(x64emu_t, segs[_DS])); @@ -401,7 +395,6 @@ uintptr_t dynarec64_00_0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x1F: - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (rex.is32bits) { INST_NAME("POP DS"); SMREAD(); diff --git a/src/dynarec/la64/dynarec_la64_00_1.c b/src/dynarec/la64/dynarec_la64_00_1.c index 699718082..d1a562c3b 100644 --- a/src/dynarec/la64/dynarec_la64_00_1.c +++ b/src/dynarec/la64/dynarec_la64_00_1.c @@ -93,7 +93,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x56: case 0x57: INST_NAME("PUSH reg"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SCRATCH_USAGE(0); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); MARKREGsz(gd); @@ -110,8 +109,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x5E: case 0x5F: INST_NAME("POP reg"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); - if (opcode == 0x5C) MARK_LEAF_RSP(LEAF_RSP_REF); SCRATCH_USAGE(0); SMREAD(); gd = TO_NAT((opcode & 0x07) + (rex.b << 3)); @@ -122,7 +119,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x60: if (rex.is32bits) { INST_NAME("PUSHAD"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); MV(x1, xRSP); PUSH1_32(xRAX); PUSH1_32(xRCX); @@ -150,7 +146,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0x61: if (rex.is32bits) { INST_NAME("POPAD"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SMREAD(); POP1_32(xRDI); POP1_32(xRSI); @@ -250,7 +245,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x68: INST_NAME("PUSH Id"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); i64 = F32S; if (PK(0) == 0xC3) { @@ -320,7 +314,6 @@ uintptr_t dynarec64_00_1(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x6A: INST_NAME("PUSH Ib"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); i64 = F8S; if (!i64) { diff --git a/src/dynarec/la64/dynarec_la64_00_2.c b/src/dynarec/la64/dynarec_la64_00_2.c index bb1f1df6b..553470554 100644 --- a/src/dynarec/la64/dynarec_la64_00_2.c +++ b/src/dynarec/la64/dynarec_la64_00_2.c @@ -605,7 +605,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int switch ((nextop >> 3) & 7) { case 0: INST_NAME("POP Ed"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SMREAD(); MARKREGsdz(xRSP); if (MODREG) { @@ -679,7 +678,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x9A: - MARK_LEAF_CALL(); if (rex.is32bits) { DEFAULT; } else { @@ -716,7 +714,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x9C: INST_NAME("PUSHF"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); READFLAGS(X_ALL); RESTORE_EFLAGS(x1); if (!rex.is32bits) UP32_READ(xRSP); @@ -724,7 +721,6 @@ uintptr_t dynarec64_00_2(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0x9D: INST_NAME("POPF"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); if (!rex.is32bits) UP32_READ(xRSP); POP1z(xFlags); diff --git a/src/dynarec/la64/dynarec_la64_00_3.c b/src/dynarec/la64/dynarec_la64_00_3.c index 6e1bc44d3..caddad588 100644 --- a/src/dynarec/la64/dynarec_la64_00_3.c +++ b/src/dynarec/la64/dynarec_la64_00_3.c @@ -346,64 +346,32 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC2: INST_NAME("RETN"); - MARK_LEAF_RET(); if (BOX64DRENV(dynarec_safeflags)) { READFLAGS(X_PEND); // lets play safe here too } BARRIER(BARRIER_FLOAT); u16 = F16; if (!rex.is32bits) UP32_READ(xRSP); - if (dyn->inline_leaf) { - if (dyn->inline_rsp >= 0) - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } else { - POP1z(xRIP); - } + POP1z(xRIP); if (u16 < 2048) ADDIz(xRSP, xRSP, u16); else { MOV32w(x1, u16); ADDz(xRSP, xRSP, x1); } - if (dyn->inline_leaf) { - SMEND(); - CHECK_DFNONE(0); - if (ninst + 1 < dyn->size) { - j64 = dyn->inline_native_end - dyn->native_size; - B(j64); - } - CLEARIP(); - } else { - ret_to_next(dyn, ip, ninst, rex); - } + ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; case 0xC3: INST_NAME("RET"); - MARK_LEAF_RET(); if (BOX64DRENV(dynarec_safeflags)) { READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost } BARRIER(BARRIER_FLOAT); if (!rex.is32bits) UP32_READ(xRSP); - if (dyn->inline_leaf) { - if (dyn->inline_rsp >= 0) - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } else { - POP1z(xRIP); - } - if (dyn->inline_leaf) { - SMEND(); - CHECK_DFNONE(0); - if (ninst + 1 < dyn->size) { - j64 = dyn->inline_native_end - dyn->native_size; - B(j64); - } - CLEARIP(); - } else { - ret_to_next(dyn, ip, ninst, rex); - } + POP1z(xRIP); + ret_to_next(dyn, ip, ninst, rex); *need_epilog = 0; *ok = 0; break; @@ -517,7 +485,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC8: INST_NAME("ENTER Iw,Ib"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); u16 = F16; u8 = (F8) & 0x1f; if (!rex.is32bits) { @@ -546,7 +513,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 0xC9: INST_NAME("LEAVE"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); MARKREGsz(xRBP); MVz(xRSP, xRBP); POP1z(xRBP); @@ -1323,7 +1289,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int case 0xE8: INST_NAME("CALL Id"); i32 = (rex.is32bits && rex.is66) ? F16S : F32S; - MARK_LEAF_CALL(); if (addr + i32 == 0) { #if STEP == 3 printf_log(LOG_INFO, "Warning, CALL to 0x0 at %p (%p)\n", (void*)addr, (void*)(addr - 1)); @@ -1431,32 +1396,12 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int } // regular call BARRIER(BARRIER_FLOAT); - int leaf_call = dyn->insts[ninst].x64.leaf_call && - dyn->insts[ninst].x64.leaf_embedded && - BOX64DRENV(dynarec_callret) >= 3; - dynarec_la64_t* leaf_embedded = leaf_call ? dynarec_get_leaf_embedded(dyn, ninst) : NULL; - if (!leaf_embedded) - leaf_call = 0; - uintptr_t leaf_target = rex.is32bits ? (uint32_t)(addr + i32) : addr + i32; - MARK_LEAF_CALL_TARGET(leaf_target); - if (!leaf_call || !leaf_embedded->inline_rsp) { - if (dyn->need_reloc) { - TABLE64(x2, addr); - } else { - MOV64x(x2, addr); - } - PUSH1z(x2); - } else if (leaf_embedded->inline_rsp > 0) { - ADDIz(xRSP, xRSP, -leaf_embedded->inline_rsp); - } - if (leaf_call) { - SET_HASCALLRET(); - MESSAGE(LOG_DUMP, "Embedded leaf call:\n"); - emit_inline_leaf(dyn, ninst); - MARK3; - CLEARIP(); - break; + if (dyn->need_reloc) { + TABLE64(x2, addr); + } else { + MOV64x(x2, addr); } + PUSH1z(x2); int can_continue = (addr < (dyn->start + dyn->isize)); if (BOX64DRENV(dynarec_callret)) { SET_HASCALLRET(); @@ -1475,7 +1420,7 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int *ok = 0; *need_epilog = 0; } - j64 = leaf_target; + j64 = rex.is32bits ? (uint32_t)(addr + i32) : addr + i32; j64 = (uintptr_t)getAlternate((void*)j64); jump_to_next(dyn, j64, 0, ninst, rex.is32bits); CALLRET_RET(can_continue); @@ -2147,7 +2092,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 2: INST_NAME("CALL Ed"); - MARK_LEAF_CALL(); PASS2IF ((BOX64DRENV(dynarec_safeflags) > 1) || ((ninst && dyn->insts[ninst - 1].x64.set_flags) || ((ninst > 1) && dyn->insts[ninst - 2].x64.set_flags)), 1) { READFLAGS(X_PEND); // that's suspicious } else { @@ -2200,7 +2144,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int CLEARIP(); break; case 3: // CALL FAR Ed - MARK_LEAF_CALL(); if (MODREG) { DEFAULT; } else { @@ -2295,7 +2238,6 @@ uintptr_t dynarec64_00_3(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 6: // Push Ed INST_NAME("PUSH Ed"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); if (!rex.is32bits) UP32_READ(xRSP); GETEDz(0); PUSH1z(ed); diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c index 93223c7e3..c10c0aa32 100644 --- a/src/dynarec/la64/dynarec_la64_0f.c +++ b/src/dynarec/la64/dynarec_la64_0f.c @@ -1669,13 +1669,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni #undef GO case 0xA0: INST_NAME("PUSH FS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_FS])); PUSH1z(x2); break; case 0xA1: INST_NAME("POP FS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); POP1z(x2); ST_H(x2, xEmu, offsetof(x64emu_t, segs[_FS])); CBZ_NEXT(x2); @@ -1754,13 +1752,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xA8: INST_NAME("PUSH GS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); LD_HU(x2, xEmu, offsetof(x64emu_t, segs[_GS])); PUSH1z(x2); break; case 0xA9: INST_NAME("POP GS"); - MARK_LEAF_RSP(LEAF_RSP_PUSHPOP); POP1z(x2); ST_H(x2, xEmu, offsetof(x64emu_t, segs[_GS])); CBZ_NEXT(x2); diff --git a/src/dynarec/la64/dynarec_la64_helper.c b/src/dynarec/la64/dynarec_la64_helper.c index 73c2af5ff..65d1c2922 100644 --- a/src/dynarec/la64/dynarec_la64_helper.c +++ b/src/dynarec/la64/dynarec_la64_helper.c @@ -48,7 +48,6 @@ uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, if ((nextop & 7) == 4) { uint8_t sib = PK(0); - if ((sib & 7) == 4) MARK_LEAF_RSP(LEAF_RSP_REF); if (((sib & 7) != 5) || ((nextop & 0xC0) != 0)) UP32_READ(TO_NAT((sib & 7) + (rex.b << 3))); if ((((sib >> 3) & 7) + (rex.x << 3)) != 4) UP32_READ(TO_NAT(((sib >> 3) & 7) + (rex.x << 3))); } else if (((nextop & 7) != 5) || ((nextop & 0xC0) != 0)) { @@ -379,7 +378,7 @@ void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -401,7 +400,7 @@ void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog_fast); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -489,7 +488,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } CLEARIP(); SMEND(); - if (BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if (BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // The JIRL(xRA, ...) form is only for gdb backtraces, but it breaks the // return-address-stack prediction on every block-to-block jump, which is @@ -514,7 +513,7 @@ void ret_to_next(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD_D(xRA, xSP, 0); // native addr LD_D(x6, xSP, 8); // x86 addr ADDI_D(xSP, xSP, 16); // pop - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index cb26fd31b..511e30f8f 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -435,8 +435,6 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGd(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (rex.w) \ UP32_WRITE64(r); \ else \ @@ -445,8 +443,6 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGdz(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (!rex.is32bits) \ UP32_WRITE64(r); \ else \ @@ -455,15 +451,11 @@ static inline int comis_fuse_inverted(int condition) #define MARKREGs(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (rex.w) UP32_READ(r); \ } while (0) #define MARKREGsz(r) \ do { \ - if ((r) == xRSP) \ - MARK_LEAF_RSP(LEAF_RSP_REF); \ if (!rex.is32bits) UP32_READ(r); \ } while (0) @@ -1667,26 +1659,6 @@ static inline int comis_fuse_inverted(int condition) #ifndef SET_HASCALLRET #define SET_HASCALLRET() #endif -#ifndef MARK_LEAF_CALL -#define MARK_LEAF_CALL() \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_CALL_TARGET -#define MARK_LEAF_CALL_TARGET(T) \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_RET -#define MARK_LEAF_RET() \ - do { \ - } while (0) -#endif -#ifndef MARK_LEAF_RSP -#define MARK_LEAF_RSP(F) \ - do { \ - } while (0) -#endif #ifndef CALLRET_RET #define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0) #endif @@ -1798,9 +1770,6 @@ static inline int comis_fuse_inverted(int condition) #define native_pass STEPNAME(native_pass) #define updateflags_pass STEPNAME(updateflags_pass) -#define emit_inline_leaf STEPNAME(emit_inline_leaf) -void emit_inline_leaf(dynarec_la64_t* dyn, int ninst); - #define dynarec64_00 STEPNAME(dynarec64_00) #define dynarec64_00_0 STEPNAME(dynarec64_00_0) #define dynarec64_00_1 STEPNAME(dynarec64_00_1) diff --git a/src/dynarec/la64/dynarec_la64_pass0.h b/src/dynarec/la64/dynarec_la64_pass0.h index 9c34c057f..e0e13e6d8 100644 --- a/src/dynarec/la64/dynarec_la64_pass0.h +++ b/src/dynarec/la64/dynarec_la64_pass0.h @@ -70,14 +70,6 @@ } else \ dyn->insts[ninst].barrier_maybe = 1 #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1 -#define MARK_LEAF_CALL() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_CALL -#define MARK_LEAF_CALL_TARGET(T) \ - do { \ - dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_CALL; \ - dyn->insts[ninst].x64.leaf_target = (uintptr_t)(T); \ - } while (0) -#define MARK_LEAF_RET() dyn->insts[ninst].x64.leaf_kind = LEAF_KIND_RET -#define MARK_LEAF_RSP(F) dyn->insts[ninst].x64.leaf_rsp |= (F) #define NEW_INST \ ++dyn->size; \ dyn->insts[ninst].x64.addr = ip; \ diff --git a/src/dynarec/la64/dynarec_la64_pass2.h b/src/dynarec/la64/dynarec_la64_pass2.h index 0223e2cbd..c5d4ebeb4 100644 --- a/src/dynarec/la64/dynarec_la64_pass2.h +++ b/src/dynarec/la64/dynarec_la64_pass2.h @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT #define INIT \ do { \ - if (!dyn->inline_leaf) \ - dyn->native_size = 0; \ + dyn->native_size = 0; \ } while (0) #define ENDPREFIX \ dyn->prefixsize = dyn->native_size; \ diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h index c9721df92..933dec490 100644 --- a/src/dynarec/la64/dynarec_la64_private.h +++ b/src/dynarec/la64/dynarec_la64_private.h @@ -214,9 +214,6 @@ typedef struct dynarec_la64_s { size_t insts_size; // size of the instruction size array (calculated) int callret_size; // size of the array callret_t* callrets; // array of callret return, with NOP / UDF depending if the block is clean or dirty - void* leaf_embeddeds; - uintptr_t inline_native_end; - int16_t inline_rsp; uintptr_t forward; // address of the last end of code while testing forward uintptr_t forward_to; // address of the next jump to (to check if everything is ok) int32_t forward_size; // size at the forward point @@ -231,8 +228,6 @@ typedef struct dynarec_la64_s { uint8_t use_ymm:1; uint8_t no_scalar_renaming:1; uint8_t is_file_mapped:1; - uint8_t inline_leaf:1; - uint8_t inline_is32bits:1; void* gdbjit_block; uint32_t need_x87check; // x87 low precision check int x87round_active; // we are in the middle of x87_setround and x87_restoreround diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index 077b9ba6a..66ae83167 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -407,7 +407,7 @@ void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -429,7 +429,7 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst) TABLE64C(x2, const_epilog_fast); SMEND(); CHECK_DFNONE(0); - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x6); BR(x2); } @@ -539,7 +539,7 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3 } CLEARIP(); SMEND(); - if (BOX64DRENV(dynarec_callret) >= 2 && !dyn->insts[ninst].x64.has_callret) + if (BOX64DRENV(dynarec_callret) >= 3 && !dyn->insts[ninst].x64.has_callret) doLeaveBlock(dyn, ninst, x4, x5, x6); // #ifdef HAVE_TRACE // The JALR(xRA, ...) form is only for gdb backtraces, but it breaks the @@ -564,7 +564,7 @@ void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex) LD(xRA, xSP, 0); // native addr LD(x6, xSP, 8); // x86 addr ADDI(xSP, xSP, 16); // pop - if (BOX64DRENV(dynarec_callret) >= 2) + if (BOX64DRENV(dynarec_callret) >= 3) doLeaveBlock(dyn, ninst, x4, x5, x7); BNE(x6, xRIP, 2 * 4); // is it the right address? BR(xRA); diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h index dcf9ca1f3..c7ff8f5dc 100644 --- a/src/include/dynarec_native.h +++ b/src/include/dynarec_native.h @@ -7,12 +7,9 @@ typedef struct x64emu_s x64emu_t; typedef struct instsize_s instsize_t; #define MAX_INSTS 32760 -#define LEAFCALL_INSTSIZE_SCRATCH 32768 void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size); -void* dynarec_get_leaf_embedded(void* owner, int ninst); - void CancelBlock64(int need_lock); dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt); diff --git a/src/tools/env.c b/src/tools/env.c index 37e3caa4f..38f74625c 100644 --- a/src/tools/env.c +++ b/src/tools/env.c @@ -238,6 +238,7 @@ static void applyCustomRules() SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 0); SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 2); SET_BOX64ENV_IF_EMPTY(dynarec_strongmem, 2); + SET_BOX64ENV_IF_EMPTY(dynarec_callret, 3); } else if (!strcasecmp(box64env.profile, "safe")) { SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 0); SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 2);