about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2025-02-16 14:41:08 +0100
committerptitSeb <sebastien.chev@gmail.com>2025-02-16 14:41:08 +0100
commit85e79a822484abb642b59dc103c08393412336b5 (patch)
treeeaba11d29e33ad176fe4013589b735efec345b00 /src
parent9ef3e080fade70147de0569de6eb23b89f827142 (diff)
downloadbox64-85e79a822484abb642b59dc103c08393412336b5.tar.gz
box64-85e79a822484abb642b59dc103c08393412336b5.zip
[ARM64_DYNAREC] Improved safeflags=2
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c134
-rw-r--r--src/dynarec/arm64/dynarec_arm64_0f.c16
-rw-r--r--src/dynarec/arm64/dynarec_arm64_64.c42
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c66
-rw-r--r--src/dynarec/arm64/dynarec_arm64_660f.c16
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c36
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h14
-rw-r--r--src/dynarec/arm64/dynarec_arm64_pass0.h1
-rw-r--r--src/dynarec/arm64/dynarec_arm64_pass1.h1
9 files changed, 219 insertions, 107 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 8ccf25ba..b43ea421 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -1764,10 +1764,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 1:
             case 2:
                 if(rep==1) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");}
-                if(BOX64DRENV(dynarec_safeflags)>1)
-                    MAYSETFLAGS();
+                if(BOX64DRENV(dynarec_safeflags)>1) {
+                    READFLAGS(X_ALL);
+                    SETFLAGS(X_ALL, SF_SET);
+                } else
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
                 SMREAD();
-                SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZx_NEXT(xRCX);
                 TBNZ_MARK2(xFlags, F_DF);
                 MARK;   // Part with DF==0
@@ -1806,9 +1808,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 1:
             case 2:
                 if(rep==1) {INST_NAME("REPNZ CMPSD");} else {INST_NAME("REPZ CMPSD");}
-                if(BOX64DRENV(dynarec_safeflags)>1)
-                    MAYSETFLAGS();
-                SETFLAGS(X_ALL, SF_SET_PENDING);
+                if(BOX64DRENV(dynarec_safeflags)>1) {
+                    READFLAGS(X_ALL);
+                    SETFLAGS(X_ALL, SF_SET);
+                } else
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
                 SMREAD();
                 CBZx_NEXT(xRCX);
                 TBNZ_MARK2(xFlags, F_DF);
@@ -1948,10 +1952,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 1:
             case 2:
                 if(rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
-                if(BOX64DRENV(dynarec_safeflags)>1)
-                    MAYSETFLAGS();
+                if(BOX64DRENV(dynarec_safeflags)>1) {
+                    READFLAGS(X_ALL);
+                    SETFLAGS(X_ALL, SF_SET);
+                } else
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
                 SMREAD();
-                SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZx_NEXT(xRCX);
                 UBFXw(x1, xRAX, 0, 8);
                 TBNZ_MARK2(xFlags, F_DF);
@@ -1987,10 +1993,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 1:
             case 2:
                 if(rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
-                if(BOX64DRENV(dynarec_safeflags)>1)
-                    MAYSETFLAGS();
+                if(BOX64DRENV(dynarec_safeflags)>1) {
+                    READFLAGS(X_ALL);
+                    SETFLAGS(X_ALL, SF_SET);
+                } else
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
                 SMREAD();
-                SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZx_NEXT(xRCX);
                 TBNZ_MARK2(xFlags, F_DF);
                 MARK;   // Part with DF==0
@@ -2776,14 +2784,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
             }
             break;
-        case 0xD2:  // TODO: Jump if CL is 0
+        case 0xD2:
             nextop = F8;
             switch((nextop>>3)&7) {
                 case 0:
                     INST_NAME("ROL Eb, CL");
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     UFLAG_IF {
                         ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                         CBZw_NEXT(x2);
@@ -2810,9 +2819,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 1:
                     INST_NAME("ROR Eb, CL");
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     UFLAG_IF {
                         ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                         CBZw_NEXT(x2);
@@ -2837,10 +2847,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 2:
                     INST_NAME("RCL Eb, CL");
-                    READFLAGS(X_CF);
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    } else {
+                        READFLAGS(X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                     // get CL % 9
                     MOV32w(x3, 0x1c72); // 0x10000 / 9 + 1 (this is precise enough in the 0..31 range)
@@ -2874,10 +2886,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 3:
                     INST_NAME("RCR Eb, CL");
-                    READFLAGS(X_CF);
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    } else {
+                        READFLAGS(X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                     // get CL % 9
                     MOV32w(x3, 0x1c72); // 0x10000 / 9 + 1
@@ -2904,9 +2918,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:
                 case 6:
                     INST_NAME("SHL Eb, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                     UFLAG_IF {
                         CBZw_NEXT(x2);
@@ -2917,9 +2933,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 5:
                     INST_NAME("SHR Eb, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                     UFLAG_IF {
                         CBZw_NEXT(x2);
@@ -2930,9 +2948,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 7:
                     INST_NAME("SAR Eb, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f
                     UFLAG_IF {
                         CBZw_NEXT(x2);
@@ -2948,9 +2968,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             switch((nextop>>3)&7) {
                 case 0:
                     INST_NAME("ROL Ed, CL");
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -2978,9 +2999,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 1:
                     INST_NAME("ROR Ed, CL");
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -3010,10 +3032,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 2:
                     INST_NAME("RCL Ed, CL");
                     MESSAGE(LOG_DUMP, "Need Optimization (RCL Ed, CL)\n");
-                    READFLAGS(X_CF);
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    } else {
+                        READFLAGS(X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SET_DF);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x2, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -3026,10 +3050,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 3:
                     INST_NAME("RCR Ed, CL");
                     MESSAGE(LOG_DUMP, "Need Optimization (RCR Ed, CL)\n");
-                    READFLAGS(X_CF);
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    } else {
+                        READFLAGS(X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SET_DF);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
                     if(rex.w) {
                         ANDx_mask(x2, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -3042,9 +3068,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:
                 case 6:
                     INST_NAME("SHL Ed, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -3060,9 +3088,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 5:
                     INST_NAME("SHR Ed, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -3078,9 +3108,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 7:
                     INST_NAME("SAR Ed, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c
index a157a9a4..ec13f6aa 100644
--- a/src/dynarec/arm64/dynarec_arm64_0f.c
+++ b/src/dynarec/arm64/dynarec_arm64_0f.c
@@ -1771,9 +1771,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xA5:

             nextop = F8;

             INST_NAME("SHLD Ed, Gd, CL");

-            SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

-            if(BOX64DRENV(dynarec_safeflags)>1)

-                MAYSETFLAGS();

+            if(BOX64DRENV(dynarec_safeflags)>1) {

+                READFLAGS(X_ALL);

+                SETFLAGS(X_ALL, SF_SET);

+            } else

+                SETFLAGS(X_ALL, SF_SET_PENDING);

             GETGD;

             GETED(0);

             if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);}

@@ -1859,9 +1861,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0xAD:

             nextop = F8;

             INST_NAME("SHRD Ed, Gd, CL");

-            SETFLAGS(X_ALL, SF_SET_PENDING);

-            if(BOX64DRENV(dynarec_safeflags)>1)

-                MAYSETFLAGS();

+            if(BOX64DRENV(dynarec_safeflags)>1) {

+                READFLAGS(X_ALL);

+                SETFLAGS(X_ALL, SF_SET);

+            } else

+                SETFLAGS(X_ALL, SF_SET_PENDING);

             GETGD;

             GETED(0);

             if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);}

diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c
index 1bfc1fe3..d770d4c7 100644
--- a/src/dynarec/arm64/dynarec_arm64_64.c
+++ b/src/dynarec/arm64/dynarec_arm64_64.c
@@ -1131,6 +1131,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             switch((nextop>>3)&7) {
                 case 0:
                     INST_NAME("ROL Ed, CL");
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
@@ -1156,6 +1159,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 1:
                     INST_NAME("ROR Ed, CL");
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SUBSET);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
@@ -1182,7 +1188,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 2:
                     INST_NAME("RCL Ed, CL");
                     MESSAGE(LOG_DUMP, "Need Optimization (RCL Seg:Ed, CL)\n");
-                    READFLAGS(X_CF);
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    } else {
+                        READFLAGS(X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SET_DF);
                     if(rex.w) {
                         ANDx_mask(x2, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
@@ -1199,7 +1209,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 3:
                     INST_NAME("RCR Ed, CL");
                     MESSAGE(LOG_DUMP, "Need Optimization (RCR Seg:Ed, CL)\n");
-                    READFLAGS(X_CF);
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_OF|X_CF);
+                    } else {
+                        READFLAGS(X_CF);
+                    }
                     SETFLAGS(X_OF|X_CF, SF_SET_DF);
                     if(rex.w) {
                         ANDx_mask(x2, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
@@ -1216,9 +1230,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:
                 case 6:
                     INST_NAME("SHL Ed, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -1232,9 +1248,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 5:
                     INST_NAME("SHR Ed, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
@@ -1248,9 +1266,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;
                 case 7:
                     INST_NAME("SAR Ed, CL");
-                    SETFLAGS(X_ALL, SF_SET_PENDING);
-                    if(BOX64DRENV(dynarec_safeflags)>1)
-                        MAYSETFLAGS();
+                    if(BOX64DRENV(dynarec_safeflags)>1) {
+                        READFLAGS(X_ALL);
+                        SETFLAGS(X_ALL, SF_SET);
+                    } else
+                        SETFLAGS(X_ALL, SF_SET_PENDING);
                     if(rex.w) {
                         ANDx_mask(x3, xRCX, 1, 0, 0b00101);  //mask=0x000000000000003f
                     } else {
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index 46cf8c90..89bc503e 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -871,9 +871,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 1:

             case 2:

                 if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}

-                if(BOX64DRENV(dynarec_safeflags)>1)

-                    MAYSETFLAGS();

-                SETFLAGS(X_ALL, SF_SET_PENDING);

+                if(BOX64DRENV(dynarec_safeflags)>1) {

+                    READFLAGS(X_ALL);

+                    SETFLAGS(X_ALL, SF_SET);

+                } else

+                    SETFLAGS(X_ALL, SF_SET_PENDING);

                 CBZx_NEXT(xRCX);

                 TBNZ_MARK2(xFlags, F_DF);

                 MARK;   // Part with DF==0

@@ -971,9 +973,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 1:

             case 2:

                 if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}

-                if(BOX64DRENV(dynarec_safeflags)>1)

-                    MAYSETFLAGS();

-                SETFLAGS(X_ALL, SF_SET_PENDING);

+                if(BOX64DRENV(dynarec_safeflags)>1) {

+                    READFLAGS(X_ALL);

+                    SETFLAGS(X_ALL, SF_SET);

+                } else

+                    SETFLAGS(X_ALL, SF_SET_PENDING);

                 CBZx_NEXT(xRCX);

                 UXTHw(x1, xRAX);

                 TBNZ_MARK2(xFlags, F_DF);

@@ -1211,9 +1215,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             switch((nextop>>3)&7) {

                 case 0:

                     INST_NAME("ROL Ew, CL");

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_OF|X_CF);

+                    }

                     SETFLAGS(X_OF|X_CF, SF_SUBSET);

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

                     UFLAG_IF {

                         ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                         CBZw_NEXT(x2);

@@ -1240,9 +1245,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 1:

                     INST_NAME("ROR Ew, CL");

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_OF|X_CF);

+                    }

                     SETFLAGS(X_OF|X_CF, SF_SUBSET);

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

                     UFLAG_IF {

                         ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                         CBZw_NEXT(x2);

@@ -1268,9 +1274,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 2:

                     INST_NAME("RCL Ew, CL");

                     MESSAGE(LOG_DUMP, "Need Optimization (RCL Ex, CL)\n");

-                    READFLAGS(X_CF);

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_OF|X_CF);

+                    } else {

+                        READFLAGS(X_CF);

+                    }

                     SETFLAGS(X_OF|X_CF, SF_SET_DF);

                     ANDw_mask(x2, xRCX, 0, 0b00100);

                     GETEW(x1, 0);

@@ -1280,9 +1288,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 3:

                     INST_NAME("RCR Ew, CL");

                     MESSAGE(LOG_DUMP, "Need Optimization (RCR Ew, CL)\n");

-                    READFLAGS(X_CF);

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_OF|X_CF);

+                    } else {

+                        READFLAGS(X_CF);

+                    }

                     SETFLAGS(X_OF|X_CF, SF_SET_DF);

                     ANDw_mask(x2, xRCX, 0, 0b00100);

                     GETEW(x1, 0);

@@ -1292,9 +1302,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 4:

                 case 6:

                     INST_NAME("SHL Ew, CL");

-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_ALL);

+                        SETFLAGS(X_ALL, SF_SET);

+                    } else

+                        SETFLAGS(X_ALL, SF_SET_PENDING);

                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                     UFLAG_IF {

                         CBZw_NEXT(x2);

@@ -1305,9 +1317,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 5:

                     INST_NAME("SHR Ew, CL");

-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_ALL);

+                        SETFLAGS(X_ALL, SF_SET);

+                    } else

+                        SETFLAGS(X_ALL, SF_SET_PENDING);

                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                     UFLAG_IF {

                         CBZw_NEXT(x2);

@@ -1318,9 +1332,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     break;

                 case 7:

                     INST_NAME("SAR Ew, CL");

-                    SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

-                    if(BOX64DRENV(dynarec_safeflags)>1)

-                        MAYSETFLAGS();

+                    if(BOX64DRENV(dynarec_safeflags)>1) {

+                        READFLAGS(X_ALL);

+                        SETFLAGS(X_ALL, SF_SET);

+                    } else

+                        SETFLAGS(X_ALL, SF_SET_PENDING);

                     ANDw_mask(x2, xRCX, 0, 0b00100);  //mask=0x00000001f

                     UFLAG_IF {

                         CBZw_NEXT(x2);

diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c
index ec5223ac..2306d1f3 100644
--- a/src/dynarec/arm64/dynarec_arm64_660f.c
+++ b/src/dynarec/arm64/dynarec_arm64_660f.c
@@ -2395,9 +2395,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
         case 0xA5:

             nextop = F8;

             INST_NAME("SHLD Ew, Gw, CL");

-            SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

-            if(BOX64DRENV(dynarec_safeflags)>1)

-                MAYSETFLAGS();

+            if(BOX64DRENV(dynarec_safeflags)>1) {

+                READFLAGS(X_ALL);

+                SETFLAGS(X_ALL, SF_SET);

+            } else

+                SETFLAGS(X_ALL, SF_SET_PENDING);

             GETGW(x2);

             GETEW(x1, 0);

             ANDw_mask(x4, xRCX, 0, 0b00100);  //mask=0x00000001f

@@ -2463,9 +2465,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
         case 0xAD:

             nextop = F8;

             INST_NAME("SHRD Ew, Gw, CL");

-            SETFLAGS(X_ALL, SF_SET_PENDING);    // some flags are left undefined

-            if(BOX64DRENV(dynarec_safeflags)>1)

-                MAYSETFLAGS();

+            if(BOX64DRENV(dynarec_safeflags)>1) {

+                READFLAGS(X_ALL);

+                SETFLAGS(X_ALL, SF_SET);

+            } else

+                SETFLAGS(X_ALL, SF_SET_PENDING);

             GETGW(x2);

             GETEW(x1, 0);

             ANDw_mask(x4, xRCX, 0, 0b00100);  //mask=0x00000001f

diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index 4c8680a8..ce80938f 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -809,6 +809,42 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
     //SET_NODF();
 }
 
+void call_i(dynarec_arm_t* dyn, int ninst, void* fnc)
+{
+    MAYUSE(fnc);
+    #if STEP == 0
+    dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
+    #endif
+    STPx_S7_preindex(x6, x7, xSP, -16);
+    STPx_S7_preindex(x4, x5, xSP, -16);
+    STPx_S7_preindex(x2, x3, xSP, -16);
+    STPx_S7_preindex(xEmu, x1, xSP, -16);   // ARM64 stack needs to be 16byte aligned
+    STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX]));    // x9..x15, x16,x17,x18 those needs to be saved by caller
+    STPx_S7_offset(xRDX, xRBX, xEmu, offsetof(x64emu_t, regs[_DX]));
+    STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
+    STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI]));
+    STPx_S7_offset(xR8,  xR9,  xEmu, offsetof(x64emu_t, regs[_R8]));
+    STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
+    fpu_pushcache(dyn, ninst, x7, 0);
+
+    TABLE64(x7, (uintptr_t)fnc);
+    BLR(x7);
+    LDPx_S7_postindex(xEmu, x1, xSP, 16);
+    LDPx_S7_postindex(x2, x3, xSP, 16);
+    LDPx_S7_postindex(x4, x5, xSP, 16);
+    #define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
+    GO(RAX, RCX);
+    GO(RDX, RBX);
+    GO(RSP, RBP);
+    GO(RSI, RDI);
+    GO(R8, R9);
+    #undef GO
+    LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
+    fpu_popcache(dyn, ninst, x7, 0);   // savereg will not be used
+    LDPx_S7_postindex(x6, x7, xSP, 16);
+    //SET_NODF();
+}
+
 void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
 {
     MAYUSE(fnc);
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 0954022f..60aac5aa 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -728,6 +728,9 @@
 // CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1)
 // R0 will not be pushed/popd if ret is -2. Flags are not save/restored
 #define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
+// CALL_ will use x7 for the call address.
+// All regs are saved, including scratch. This is use to call internal function that should not change state
+#define CALL_I(F) call_i(dyn, ninst, F)
 
 #define MARK        dyn->insts[ninst].mark = dyn->native_size
 #define GETMARK     dyn->insts[ninst].mark
@@ -1101,7 +1104,7 @@
         MOVZw(S, (N));                                                                                                          \
         STRw_U12(S, xEmu, offsetof(x64emu_t, df));                                                                              \
         if (dyn->f.pending == SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after & X_PEND)) { \
-            CALL_(UpdateFlags, -1, 0);                                                                                          \
+            CALL_I(UpdateFlags);                                                                                                \
             dyn->f.pending = SF_SET;                                                                                            \
             SET_NODF();                                                                                                         \
         }                                                                                                                       \
@@ -1114,10 +1117,6 @@
 #endif
 #define SET_DFOK()          dyn->f.dfnone = 1; dyn->f.dfnone_here=1
 
-#ifndef MAYSETFLAGS
-#define MAYSETFLAGS() do {} while (0)
-#endif
-
 #ifndef READFLAGS
 #define READFLAGS(A) \
     if(((A)!=X_PEND && dyn->f.pending!=SF_SET)          \
@@ -1127,7 +1126,7 @@
             j64 = (GETMARKF)-(dyn->native_size);        \
             CBZw(x3, j64);                              \
         }                                               \
-        CALL_(UpdateFlags, -1, 0);                      \
+        CALL_I(UpdateFlags);                            \
         MARKF;                                          \
         dyn->f.pending = SF_SET;                        \
         SET_DFOK();                                     \
@@ -1167,6 +1166,7 @@
 #define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
 #define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A);}
 #define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags)
+#define UFLAG_IF_DF if(dyn->insts[ninst].x64.gen_flags || (dyn->insts[ninst].f_entry.dfnone && dyn->insts[ninst].f_entry.dfnone_here))
 #define UFLAG_IF2(A) if(dyn->insts[ninst].x64.gen_flags A)
 #ifndef DEFAULT
 #define DEFAULT      *ok = -1; BARRIER(2)
@@ -1282,6 +1282,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
 #define retn_to_epilog  STEPNAME(retn_to_epilog)
 #define iret_to_epilog  STEPNAME(iret_to_epilog)
 #define call_c          STEPNAME(call_c)
+#define call_i          STEPNAME(call_i)
 #define call_n          STEPNAME(call_n)
 #define grab_segdata    STEPNAME(grab_segdata)
 #define emit_cmp8       STEPNAME(emit_cmp8)
@@ -1452,6 +1453,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex);
 void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n);
 void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits);
 void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
+void call_i(dynarec_arm_t* dyn, int ninst, void* fnc);
 void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
 void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg);
 void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h
index 391405ef..37cc7a3f 100644
--- a/src/dynarec/arm64/dynarec_arm64_pass0.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass0.h
@@ -6,7 +6,6 @@
     if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
 
 #define MESSAGE(A, ...) do {} while (0)
-#define MAYSETFLAGS()   dyn->insts[ninst].x64.may_set = 1
 #define READFLAGS(A)    \
         dyn->insts[ninst].x64.use_flags = A; dyn->f.dfnone = 1;\
         if(!BOX64ENV(dynarec_df) && (A)&X_PEND) dyn->insts[ninst].x64.use_flags = X_ALL; \
diff --git a/src/dynarec/arm64/dynarec_arm64_pass1.h b/src/dynarec/arm64/dynarec_arm64_pass1.h
index 7e81b167..f5ad6a7b 100644
--- a/src/dynarec/arm64/dynarec_arm64_pass1.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass1.h
@@ -2,7 +2,6 @@
 #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);     \