about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-09-26 10:16:21 +0200
committerptitSeb <sebastien.chev@gmail.com>2022-09-26 10:16:21 +0200
commit40b849da233666044a04909995e558a254e4e7f9 (patch)
tree1dbde43cfc5aca30a008f115e6bf6473711a30b9 /src
parent4f18bd62931f92f14ebdaa25cae5f487619e8a52 (diff)
downloadbox64-40b849da233666044a04909995e558a254e4e7f9.tar.gz
box64-40b849da233666044a04909995e558a254e4e7f9.zip
Improved handling of CF flags in dec/inc opcodes ([DYNAREC] too) (helps Xonotic official linux build)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/arm64/dynarec_arm64_helper.h4
-rwxr-xr-xsrc/dynarec/dynarec_native.c3
-rwxr-xr-xsrc/emu/x64emu_private.h3
-rwxr-xr-xsrc/emu/x64primop.h42
-rwxr-xr-xsrc/emu/x64run_private.c27
-rwxr-xr-xsrc/include/regs.h12
6 files changed, 75 insertions, 16 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 51cf5ec7..69f5544b 100755
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -619,8 +619,8 @@
 #define SETFLAGS(A, B)                                                                          \
     if(dyn->f.pending!=SF_SET                                                                   \
     && ((B)&SF_SUB)                                                                             \
-    && (dyn->insts[ninst].x64.need_flags&(~((A)|((B==SF_SUBSET_PENDING)?X_PEND:0)))))           \
-        READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A)|X_PEND));                              \
+    && (dyn->insts[ninst].x64.need_flags&(~(A))))                                               \
+        READFLAGS(((dyn->insts[ninst].x64.need_flags&X_PEND)?X_ALL:dyn->insts[ninst].x64.need_flags)&(~(A)));\
     if(dyn->insts[ninst].x64.need_flags) switch(B) {                                            \
         case SF_SUBSET:                                                                         \
         case SF_SET: dyn->f.pending = SF_SET; break;                                            \
diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c
index 260fb145..b9beabf0 100755
--- a/src/dynarec/dynarec_native.c
+++ b/src/dynarec/dynarec_native.c
@@ -330,8 +330,11 @@ static void updateNeed(dynarec_native_t* dyn, int ninst, uint32_t need) {
     if((new_need&X_PEND) && dyn->insts[ninst].x64.state_flags==SF_SUBSET) {
         new_need &=~X_PEND;
         new_need |= X_ALL;
+    } else if((new_need&X_PEND) && dyn->insts[ninst].x64.state_flags==SF_SUBSET_PENDING) {
+        new_need |= X_ALL&~dyn->insts[ninst].x64.set_flags;
     }
 
+
     uint32_t new_set = 0;
     if(dyn->insts[ninst].x64.state_flags & SF_SET)
         new_set = dyn->insts[ninst].x64.set_flags;
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index 114731eb..1ffdd1fa 100755
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -52,6 +52,9 @@ typedef struct x64emu_s {
     multiuint_t op1;
     multiuint_t op2;
     multiuint_t res;
+    multiuint_t op1_sav;    // for dec/inc defered flags, to be able to compute CF
+    multiuint_t res_sav;
+    defered_flags_t df_sav;
     uint32_t    *x64emu_parity_tab; // helper
     #ifdef HAVE_TRACE
     reg64_t     oldregs[16];
diff --git a/src/emu/x64primop.h b/src/emu/x64primop.h
index f8152277..a0f465a3 100755
--- a/src/emu/x64primop.h
+++ b/src/emu/x64primop.h
@@ -89,88 +89,106 @@ uint64_t     cmp64 (x64emu_t *emu, uint64_t d, uint64_t s);
 uint8_t      daa8  (x64emu_t *emu, uint8_t d);
 uint8_t      das8  (x64emu_t *emu, uint8_t d);
 
+#define CF_SAV()	\
+	if(emu->df>=d_dec8 && emu->df<=d_inc64)	{		\
+		emu->df_sav = d_none;						\
+	} else if(emu->df<d_dec8i || emu->df>d_inc64i) {\
+		emu->df_sav = emu->df;						\
+		emu->op1_sav = emu->op1;					\
+		emu->res_sav = emu->res;					\
+	}
+
 static inline uint8_t dec8(x64emu_t *emu, uint8_t d)
 {
+	CF_SAV();
     emu->res.u8 = d - 1;
 	emu->op1.u8 = d;
-	emu->df = d_dec8;
+	emu->df = d_dec8i;
 	return emu->res.u8;
 }
 
 static inline uint16_t dec16(x64emu_t *emu, uint16_t d)
 {
+	CF_SAV();
     emu->res.u16 = d - 1;
 	emu->op1.u16 = d;
-	emu->df = d_dec16;
+	emu->df = d_dec16i;
 	return emu->res.u16;
 
 }
 
 static inline uint32_t dec32(x64emu_t *emu, uint32_t d)
 {
+	CF_SAV();
     emu->res.u32 = d - 1;
 	emu->op1.u32 = d;
-	emu->df = d_dec32;
+	emu->df = d_dec32i;
 
 	return emu->res.u32;
 }
 
 static inline uint64_t dec64(x64emu_t *emu, uint64_t d)
 {
+	CF_SAV();
     emu->res.u64 = d - 1;
 	emu->op1.u64 = d;
-	emu->df = d_dec64;
+	emu->df = d_dec64i;
 
 	return emu->res.u64;
 }
 
 static inline uint8_t inc8(x64emu_t *emu, uint8_t d)
 {
+	CF_SAV();
 	emu->res.u8 = d + 1;
 	emu->op1.u8 = d;
-	emu->df = d_inc8;
+	emu->df = d_inc8i;
 	return emu->res.u8;
 }
 
 static inline uint16_t inc16(x64emu_t *emu, uint16_t d)
 {
+	CF_SAV();
 	emu->res.u16 = d + 1;
 	emu->op1.u16 = d;
-	emu->df = d_inc16;
+	emu->df = d_inc16i;
 	return emu->res.u16;
 }
 
 static inline uint32_t inc32(x64emu_t *emu, uint32_t d)
 {
-	if(emu->df == d_shr32) {
+	/*if(emu->df == d_shr32) {
 		// workaround for some wine trickery
 		uint32_t cnt = emu->op2.u32;
         if (cnt > 0) {
             uint32_t cc = emu->op1.u32 & (1 << (cnt - 1));
 			CONDITIONAL_SET_FLAG(cc, F_CF);
 		}
-	}
+	}*/
+	CF_SAV();
 	emu->res.u32 = d + 1;
 	emu->op1.u32 = d;
-	emu->df = d_inc32;
+	emu->df = d_inc32i;
 	return emu->res.u32;
 }
 
 static inline uint64_t inc64(x64emu_t *emu, uint64_t d)
 {
-	if(emu->df == d_shr64) {
+	/*if(emu->df == d_shr64) {
 		// workaround for some wine trickery
 		uint64_t cnt = emu->op2.u64;
         if (cnt > 0) {
             uint64_t cc = emu->op1.u64 & (1LL << (cnt - 1));
 			CONDITIONAL_SET_FLAG(cc, F_CF);
 		}
-	}
+	}*/
+	CF_SAV();
 	emu->res.u64 = d + 1;
 	emu->op1.u64 = d;
-	emu->df = d_inc64;
+	emu->df = d_inc64i;
 	return emu->res.u64;
 }
+#undef CF_SAV
 
 static inline uint8_t or8(x64emu_t *emu, uint8_t d, uint8_t s)
 {
diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index cf232e77..adf90ee3 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -940,6 +940,33 @@ void UpdateFlags(x64emu_t *emu)
         case d_unknown:
             printf_log(LOG_NONE, "Box64: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
             break;
+        
+        case d_dec8i:
+        case d_dec16i:
+        case d_dec32i:
+        case d_dec64i:
+        case d_inc8i:
+        case d_inc16i:
+        case d_inc32i:
+        case d_inc64i:
+            {
+                defered_flags_t df = emu->df - (d_dec8i - d_dec8);
+                if(emu->df_sav!=d_none) {
+                    // compute CF
+                    multiuint_t op1 = emu->op1;
+                    multiuint_t res = emu->res;
+                    emu->df = emu->df_sav;
+                    emu->op1 = emu->op1_sav;
+                    emu->res = emu->res_sav;
+                    emu->df_sav = d_none;
+                    UpdateFlags(emu);
+                    emu->op1 = op1;
+                    emu->res = res;
+                }
+                emu->df = df;
+            }
+            UpdateFlags(emu);
+            break;
     }
     RESET_FLAGS(emu);
 }
diff --git a/src/include/regs.h b/src/include/regs.h
index c0d5ba4e..d7ae0250 100755
--- a/src/include/regs.h
+++ b/src/include/regs.h
@@ -54,7 +54,7 @@ typedef enum {
 	d_and16,
 	d_and32,
 	d_and64,
-	d_dec8,
+	d_dec8,		// warning dec8..inc64 needs to be in sequence
 	d_dec16,
 	d_dec32,
 	d_dec64,
@@ -131,7 +131,15 @@ typedef enum {
 	d_rcr16,
 	d_rcr32,
 	d_rcr64,
-	d_unknown	//46
+	d_dec8i,	// interpretor version, to handle the CF flags that is untouched
+	d_dec16i,
+	d_dec32i,
+	d_dec64i,
+	d_inc8i,
+	d_inc16i,
+	d_inc32i,
+	d_inc64i,
+	d_unknown	//95
 } defered_flags_t;
 
 #pragma pack(push, 1)