about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c3
-rw-r--r--src/dynarec/arm64/dynarec_arm64_functions.c6
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_pass1.h10
-rw-r--r--src/dynarec/arm64/dynarec_arm64_private.h1
-rw-r--r--src/dynarec/dynarec_native_functions.c14
-rw-r--r--src/dynarec/dynarec_native_functions.h2
-rw-r--r--src/dynarec/la64/dynarec_la64_private.h1
-rw-r--r--src/dynarec/rv64/dynarec_rv64_private.h1
10 files changed, 39 insertions, 3 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index cd886163..c777ed3d 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -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);
diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c
index 1400f977..dd4749e7 100644
--- a/src/dynarec/arm64/dynarec_arm64_functions.c
+++ b/src/dynarec/arm64/dynarec_arm64_functions.c
@@ -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,
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index 7a29562b..1b56127e 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -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:
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 803e15e1..84533591 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -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
diff --git a/src/dynarec/arm64/dynarec_arm64_pass1.h b/src/dynarec/arm64/dynarec_arm64_pass1.h
index 173f27bf..9a3132b3 100644
--- a/src/dynarec/arm64/dynarec_arm64_pass1.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass1.h
@@ -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;\
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index b010d4ed..3b8cb1f3 100644
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -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
diff --git a/src/dynarec/dynarec_native_functions.c b/src/dynarec/dynarec_native_functions.c
index c6ea65b0..f0bf3d08 100644
--- a/src/dynarec/dynarec_native_functions.c
+++ b/src/dynarec/dynarec_native_functions.c
@@ -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;       
+    }
+}
\ No newline at end of file
diff --git a/src/dynarec/dynarec_native_functions.h b/src/dynarec/dynarec_native_functions.h
index fe74c2b3..827a02a4 100644
--- a/src/dynarec/dynarec_native_functions.h
+++ b/src/dynarec/dynarec_native_functions.h
@@ -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);
diff --git a/src/dynarec/la64/dynarec_la64_private.h b/src/dynarec/la64/dynarec_la64_private.h
index 3d65de48..1dab0696 100644
--- a/src/dynarec/la64/dynarec_la64_private.h
+++ b/src/dynarec/la64/dynarec_la64_private.h
@@ -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
diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h
index 0beaf11c..5c00231e 100644
--- a/src/dynarec/rv64/dynarec_rv64_private.h
+++ b/src/dynarec/rv64/dynarec_rv64_private.h
@@ -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