diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 16 | ||||
| -rw-r--r-- | src/emu/x64run_private.c | 31 | ||||
| -rw-r--r-- | src/include/regs.h | 5 |
3 files changed, 44 insertions, 8 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index 19343416..7c626eb1 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -1056,8 +1056,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint MOV32w(s3, c); 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_shld64:d_shld32); } else IFX(X_ALL) { SET_DFNONE(s4); } @@ -1070,12 +1069,15 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint } return; } - IFX(X_CF|X_OF) { + IFX(X_CF) { LSRxw(s3, s1, (rex.w?64:32)-c); BFIxw(xFlags, s3, F_CF, 1); } - LSLxw(s3, s1, c); - ORRxw_REG_LSR(s1, s3, s2, (rex.w?64:32)-c); + IFX(X_OF) { + LSRxw(s3, s1, rex.w?63:31); + BFIw(xFlags, s3, F_OF, 1); // store current sign for later use + } + EXTRxw(s1, s1, s2, (rex.w?64:32)-c); IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); @@ -1091,8 +1093,8 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint } IFX(X_OF) { if(c==1) { - UBFXxw(s3, s1, rex.w?63:31, 1); - EORxw_REG(s3, s3, xFlags); // CF is set if OF is asked + LSRxw(s3, s1, rex.w?63:31); + EORxw_REG_LSR(s3, s3, xFlags, F_OF); // OF is set if sign changed BFIw(xFlags, s3, F_OF, 1); } else { BFCw(xFlags, F_OF, 1); diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index a5a588c2..1eaa6301 100644 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -731,6 +731,36 @@ void UpdateFlags(x64emu_t *emu) } } break; + case d_shld32: + cnt = emu->op2.u32; + if (cnt > 0) { + cc = emu->op1.u32 & (1 << (32 - cnt)); + 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); + } else { + CLEAR_FLAG(F_OF); + } + } + break; + case d_shld64: + cnt = emu->op2.u64; + if (cnt > 0) { + cc = emu->op1.u64 & (1LL << (64 - cnt)); + 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); + } else { + CLEAR_FLAG(F_OF); + } + } + break; case d_sub8: CONDITIONAL_SET_FLAG(emu->res.u8 & 0x80, F_SF); CONDITIONAL_SET_FLAG((emu->res.u8 & 0xff) == 0, F_ZF); @@ -1014,6 +1044,7 @@ void UpdateFlags(x64emu_t *emu) case d_rcr16: case d_rcr32: case d_rcr64: + case d_shld16: 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 433b352c..dc72a648 100644 --- a/src/include/regs.h +++ b/src/include/regs.h @@ -142,7 +142,10 @@ typedef enum { d_shrd16, d_shrd32, d_shrd64, - d_unknown //98 + d_shld16, + d_shld32, + d_shld64, + d_unknown //101 } deferred_flags_t; #pragma pack(push, 1) |