about summary refs log tree commit diff stats
path: root/src/emu
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/emu
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/emu')
-rwxr-xr-xsrc/emu/x64emu_private.h3
-rwxr-xr-xsrc/emu/x64primop.h42
-rwxr-xr-xsrc/emu/x64run_private.c27
3 files changed, 60 insertions, 12 deletions
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);
 }