[ARM64_DYNAREC] Try to not call UpdateFlags when switching to a DFNONE state but dfnone is not needed

This commit is contained in:
ptitSeb 2024-11-15 14:27:43 +01:00
parent eaca84e9ba
commit 64b213fe42
10 changed files with 39 additions and 3 deletions

View File

@ -3158,6 +3158,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
JUMP((uintptr_t)getAlternate((void*)j64), 0);
if(dyn->insts[ninst].x64.jmp_insts==-1) {
// out of the block
SET_NODF();
fpu_purgecache(dyn, ninst, 1, x1, x2, x3);
jump_to_next(dyn, (uintptr_t)getAlternate((void*)j64), 0, ninst, rex.is32bits);
} else {
@ -3746,6 +3747,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4: // JMP Ed
INST_NAME("JMP Ed");
READFLAGS(X_PEND);
SET_NODF();
BARRIER(BARRIER_FLOAT);
GETEDz(0);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
@ -3758,6 +3760,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("JMP FAR Ed");
READFLAGS(X_PEND);
SET_NODF();
BARRIER(BARRIER_FLOAT);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0, 0, rex, NULL, 0, 0);

View File

@ -662,7 +662,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
{
if(box64_dynarec_dump) {
printf_x64_instruction(rex.is32bits?my_context->dec32:my_context->dec, &dyn->insts[ninst].x64, name);
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d/%d(%d:%d->%d:%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
(box64_dynarec_dump>1)?"\e[32m":"",
(void*)(dyn->native_start+dyn->insts[ninst].address),
dyn->insts[ninst].size/4,
@ -671,6 +671,10 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].f_entry.pending,
dyn->insts[ninst].f_entry.dfnone,
dyn->insts[ninst].f_exit.pending,
dyn->insts[ninst].f_exit.dfnone,
dyn->insts[ninst].x64.may_set?"may":"set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,

View File

@ -2346,7 +2346,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->f.dfnone || (dyn->insts[jmp].f_exit.dfnone_here && !dyn->insts[jmp].x64.use_flags)) // flags are fully known, nothing we can do more
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone && !dyn->insts[jmp].df_notneeded)?1:0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:

View File

@ -1092,7 +1092,9 @@
} \
dyn->f.dfnone=0; \
} else SET_DFNONE(S)
#ifndef SET_NODF
#define SET_NODF() dyn->f.dfnone = 0
#endif
#define SET_DFOK() dyn->f.dfnone = 1; dyn->f.dfnone_here=1
#ifndef MAYSETFLAGS

View File

@ -2,6 +2,16 @@
#define FINI
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do {} while (0)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define SET_NODF() \
if(!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].x64.use_flags) \
propagate_nodf(dyn, ninst); \
dyn->f.dfnone = 0
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\

View File

@ -119,6 +119,7 @@ typedef struct instruction_arm64_s {
unsigned normal_carry:1;
unsigned normal_carry_before:1;
unsigned invert_carry:1; // this opcode force an inverted carry
unsigned df_notneeded:1;
flagcache_t f_exit; // flags status at end of instruction
neoncache_t n; // neoncache at end of instruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin

View File

@ -513,7 +513,7 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone && !dyn->insts[jmp].df_notneeded)
return 1;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
@ -648,3 +648,15 @@ void avx_unmark_zero(dynarec_native_t* dyn, int ninst, int reg)
{
dyn->ymm_zero &= ~(1<<reg);
}
void propagate_nodf(dynarec_native_t* dyn, int ninst)
{
while(ninst>=0) {
if(dyn->insts[ninst].df_notneeded)
return; // already flagged
if(dyn->insts[ninst].x64.gen_flags || dyn->insts[ninst].x64.use_flags)
return; // flags are use, so maybe it's needed
dyn->insts[ninst].df_notneeded = 1;
--ninst;
}
}

View File

@ -61,6 +61,8 @@ void native_div0(x64emu_t* emu);
// Caches transformation (for loops) // Specific, need to be written par backend
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
// propagete defererd to unknow, as state is not needed
void propagate_nodf(dynarec_native_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_native_t* dyn, int ninst, int pred);

View File

@ -91,6 +91,7 @@ typedef struct instruction_la64_s {
uint8_t barrier_maybe;
uint8_t will_write;
uint8_t last_write;
uint8_t df_notneeded;
flagcache_t f_exit; // flags status at end of instruction
lsxcache_t lsx; // lsxcache at end of instruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin

View File

@ -122,6 +122,7 @@ typedef struct instruction_rv64_s {
uint16_t ymm0_out; // the ymm0 at th end of the opcode
uint16_t ymm0_pass2, ymm0_pass3;
int barrier_maybe;
uint8_t df_notneeded;
flagcache_t f_exit; // flags status at end of instruction
extcache_t e; // extcache at end of instruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin