From d7744ea22d511ede738bda7f2f5d7520f246aa4b Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Mon, 24 Mar 2025 12:03:18 +0100 Subject: [DYNAREC] Better handling of blocksize limit when generating very large dynablocks --- src/dynarec/dynablock.c | 2 +- src/dynarec/dynarec_native.c | 34 ++++++++++++++++++++++++---------- src/dynarec/dynarec_native_pass.c | 4 ++-- src/include/dynarec_native.h | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 517a702e..7a7e4033 100644 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -238,7 +238,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t mutex_unlock(&my_context->mutex_dyndump); return NULL; } - void* ret = FillBlock64(block, filladdr, (addr==filladdr)?0:1, is32bits); + void* ret = FillBlock64(block, filladdr, (addr==filladdr)?0:1, is32bits, MAX_INSTS); if(!ret) { dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr); customFree(block); diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index 678f5426..e8406cce 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -553,10 +553,10 @@ void CancelBlock64(int need_lock) mutex_unlock(&my_context->mutex_dyndump); } -uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits); -uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits); -uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits); -uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits); +uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); +uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits, int inst_max); +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); void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) { block->isize = 0; @@ -582,7 +582,7 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) { return block; } -void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits) { +void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits, int inst_max) { /* A Block must have this layout: @@ -626,7 +626,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit helper.table64 = static_table64; helper.table64cap = sizeof(static_table64)/sizeof(uint64_t); // pass 0, addresses, x64 jump addresses, overall size of the block - uintptr_t end = native_pass0(&helper, addr, alternate, is32bits); + uintptr_t end = native_pass0(&helper, addr, alternate, is32bits, inst_max); if(helper.abort) { if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass0\n"); CancelBlock64(0); @@ -741,7 +741,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit // pass 1, float optimizations, first pass for flags - native_pass1(&helper, addr, alternate, is32bits); + native_pass1(&helper, addr, alternate, is32bits, inst_max); if(helper.abort) { if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass1\n"); CancelBlock64(0); @@ -749,16 +749,30 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit } // pass 2, instruction size - native_pass2(&helper, addr, alternate, is32bits); + native_pass2(&helper, addr, alternate, is32bits, inst_max); if(helper.abort) { if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass2\n"); CancelBlock64(0); return NULL; } // keep size of instructions for signal handling + size_t native_size = (helper.native_size+7)&~7; // round the size... + // check if size is overlimit + if((inst_max==MAX_INSTS) && (native_size>MAXBLOCK_SIZE)) { + int imax = 0; + size_t max_size = 0; + while((max_sizenative_size >= MAXBLOCK_SIZE) || (ninst >= MAX_INSTS)) { + if(ninst >= inst_max) { need_epilog = 1; break; } diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h index 2f305155..2754eed7 100644 --- a/src/include/dynarec_native.h +++ b/src/include/dynarec_native.h @@ -24,7 +24,7 @@ typedef struct instsize_s instsize_t; void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size); void CancelBlock64(int need_lock); -void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits); +void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits, int inst_max); void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size, const char* inst_name); -- cgit 1.4.1