diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2022-09-26 10:16:21 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2022-09-26 10:16:21 +0200 |
| commit | 40b849da233666044a04909995e558a254e4e7f9 (patch) | |
| tree | 1dbde43cfc5aca30a008f115e6bf6473711a30b9 /src | |
| parent | 4f18bd62931f92f14ebdaa25cae5f487619e8a52 (diff) | |
| download | box64-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-x | src/dynarec/arm64/dynarec_arm64_helper.h | 4 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_native.c | 3 | ||||
| -rwxr-xr-x | src/emu/x64emu_private.h | 3 | ||||
| -rwxr-xr-x | src/emu/x64primop.h | 42 | ||||
| -rwxr-xr-x | src/emu/x64run_private.c | 27 | ||||
| -rwxr-xr-x | src/include/regs.h | 12 |
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) |