[DYNAREC] Added callret=3 and move in_used tracking to it (#4609)

Also removed the leafcall optimization from LoongArch.
This commit is contained in:
Yang Liu authored and GitHub committed 2026-10-26 16:12:23 +01:00
1 parent 11effee660
commit 74ee4280db
25 files changed
+41 -615

No files matched your search

+1
View File
@@ -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"),
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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<BOX64_DYNAREC_DF> =I<0|1>
+1 -1
View File
@@ -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
}
]
+1 -1
View File
@@ -107,7 +107,7 @@
"0": "不优化 CALL/RET,使用跳转表。",
"1": "尝试优化 CALL/RET,在可能的情况下跳过跳转表。",
"2": "尝试优化 CALL/RET,在可能的情况下跳过跳转表,同时增加对返回到脏/已修改代码块的代码的处理。在 WowBox64 上不可用。",
"3": "在 2 的基础上,对叶子函数进行分析,并将符合条件的叶子函数体复制到调用方。目前仅支持龙架构。"
"3": "在 2 的基础上,额外跟踪代码块的使用情况,避免回收仍在使用中的代码块。"
}
},
"BOX64_DYNAREC_DF": {
+3 -3
View File
@@ -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);
+3 -1
View File
@@ -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)
+6 -2
View File
@@ -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);
-371
View File
@@ -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;
+3 -74
View File
@@ -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
-11
View File
@@ -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;
-7
View File
@@ -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();
-7
View File
@@ -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) {
-4
View File
@@ -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);
+10 -68
View File
@@ -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);
-4
View File
@@ -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);
+4 -5
View File
@@ -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);
-31
View File
@@ -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)
-8
View File
@@ -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; \
+1 -2
View File
@@ -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; \
-5
View File
@@ -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
+4 -4
View File
@@ -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);
-3
View File
@@ -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);
+1
View File
@@ -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);