diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-11-16 10:42:40 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-11-16 10:42:40 +0100 |
| commit | f7d75ca641ec6de4a35421fe206f8608ee531a20 (patch) | |
| tree | c7b19d5320c0a5d0d0910d6902e066c8f27de5b9 /src | |
| parent | 5baa0833865379799136eea5541b62fe4044ed9a (diff) | |
| download | box64-f7d75ca641ec6de4a35421fe206f8608ee531a20.tar.gz box64-f7d75ca641ec6de4a35421fe206f8608ee531a20.zip | |
[ARM64_DYNAREC] Fixed shrd 32/64bits opcodes
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 10 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 29 | ||||
| -rw-r--r-- | src/include/regs.h | 5 |
3 files changed, 37 insertions, 7 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index e67961b2..7b504321 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1006,7 +1006,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2)); // same flags computation as with shl64/shl32 - SET_DF(s4, rex.w?d_shl64:d_shl32); + SET_DF(s4, rex.w?d_shrd64:d_shrd32); } else IFX(X_ALL) { SET_DFNONE(s4); } @@ -1025,7 +1025,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint BFIw(xFlags, s4, F_OF, 1); // store sign for later use } } - EXTRxw(s1, s1, s2, c); + EXTRxw(s1, s2, s1, c); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } @@ -1111,7 +1111,7 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); STRxw_U12(s5, xEmu, offsetof(x64emu_t, op2)); // same flags computation as with shl64/shl32 - SET_DF(s4, rex.w?d_shl64:d_shl32); + SET_DF(s4, rex.w?d_shrd64:d_shrd32); } else IFX(X_ALL) { SET_DFNONE(s4); } @@ -1139,12 +1139,12 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s } IFX(X_SF) { LSRxw(s4, s1, (rex.w)?63:31); - BFIx(xFlags, s4, F_SF, 1); + BFIw(xFlags, s4, F_SF, 1); } IFX(X_OF) { CMPSw_U12(s5, 1); Bcond(cNE, 4+3*4); - LSRxw(s4, s1, rex.w?62:30); + LSRxw(s4, s1, rex.w?63:31); EORw_REG_LSR(s4, s4, xFlags, F_OF); // Set if sign changed BFIw(xFlags, s4, F_OF, 1); } diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 1ef14725..f50c32cc 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -687,10 +687,36 @@ void UpdateFlags(x64emu_t *emu) CONDITIONAL_SET_FLAG(!emu->res.u64, F_ZF); CONDITIONAL_SET_FLAG(emu->res.u64 & 0x8000000000000000LL, F_SF); CONDITIONAL_SET_FLAG(PARITY(emu->res.u64 & 0xff), F_PF); - } if (cnt == 1) { CONDITIONAL_SET_FLAG(emu->op1.u64 & 0x8000000000000000LL, F_OF); } + } + break; + case d_shrd32: + cnt = emu->op2.u32; + if (cnt > 0) { + cc = emu->op1.u32 & (1 << (cnt - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG(!emu->res.u32, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u32 & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u32 & 0xff), F_PF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG((emu->op1.u32 ^ emu->res.u32) & 0x80000000, F_OF); + } + } + break; + case d_shrd64: + cnt = emu->op2.u64; + if (cnt > 0) { + cc = emu->op1.u64 & (1LL << (cnt - 1)); + CONDITIONAL_SET_FLAG(cc, F_CF); + CONDITIONAL_SET_FLAG(!emu->res.u64, F_ZF); + CONDITIONAL_SET_FLAG(emu->res.u64 & 0x8000000000000000LL, F_SF); + CONDITIONAL_SET_FLAG(PARITY(emu->res.u64 & 0xff), F_PF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG((emu->op1.u64 ^ emu->res.u64) & 0x8000000000000000LL, F_OF); + } + } break; case d_sub8: CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); @@ -975,6 +1001,7 @@ void UpdateFlags(x64emu_t *emu) case d_rcr16: case d_rcr32: case d_rcr64: + case d_shrd16: case d_unknown: printf_log(LOG_NONE, "Box64: %p trying to evaluate Unknown deferred Flags\n", (void*)R_RIP); break; diff --git a/src/include/regs.h b/src/include/regs.h index 3d1a4984..433b352c 100644 --- a/src/include/regs.h +++ b/src/include/regs.h @@ -139,7 +139,10 @@ typedef enum { d_inc16i, d_inc32i, d_inc64i, - d_unknown //95 + d_shrd16, + d_shrd32, + d_shrd64, + d_unknown //98 } deferred_flags_t; #pragma pack(push, 1) |