From 46f983fbb63395553f7912b17f034320fabb65d9 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 11 Sep 2019 00:22:10 -0700 Subject: [PATCH] Minor fix to SHL op to not update flags if the shift amount was zero. --- Source/Interface/Core/OpcodeDispatcher.cpp | 50 +++++++++++++++++++++- Source/Interface/Core/OpcodeDispatcher.h | 1 + 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Source/Interface/Core/OpcodeDispatcher.cpp b/Source/Interface/Core/OpcodeDispatcher.cpp index a0b2eeaab..631f2061c 100644 --- a/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1156,7 +1156,7 @@ void OpDispatchBuilder::SHLOp(OpcodeArgs) { StoreResult(Op, ALUOp); // XXX: This isn't correct - GenerateFlags_Logical(Op, _Bfe(Size, 0, ALUOp), _Bfe(Size, 0, Dest), _Bfe(Size, 0, Src)); + GenerateFlags_Shift(Op, _Bfe(Size, 0, ALUOp), _Bfe(Size, 0, Dest), _Bfe(Size, 0, Src)); } void OpDispatchBuilder::SHROp(OpcodeArgs) { @@ -2904,6 +2904,54 @@ void OpDispatchBuilder::GenerateFlags_Logical(FEXCore::X86Tables::DecodedOp Op, SetRFLAG(ZeroConst); } } + +void OpDispatchBuilder::GenerateFlags_Shift(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) { + auto ZeroConst = _Constant(0); + auto OneConst = _Constant(1); + + auto CmpResult = _Select(FEXCore::IR::COND_EQ, Src2, ZeroConst, OneConst, ZeroConst); + auto CondJump = _CondJump(CmpResult); + // AF + { + // Undefined + // Set to zero anyway + SetRFLAG(ZeroConst); + } + + // SF + { + auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1); + + auto LshrOp = _Lshr(Res, SignBitConst); + SetRFLAG(LshrOp); + } + + // PF + { + auto EightBitMask = _Constant(0xFF); + auto PopCountOp = _Popcount(_And(Res, EightBitMask)); + auto XorOp = _Xor(PopCountOp, OneConst); + SetRFLAG(XorOp); + } + + // ZF + { + auto SelectOp = _Select(FEXCore::IR::COND_EQ, + Res, ZeroConst, OneConst, ZeroConst); + SetRFLAG(SelectOp); + } + + // CF/OF + { + SetRFLAG(ZeroConst); + SetRFLAG(ZeroConst); + } + + _EndBlock(0); + auto NewBlock = _BeginBlock(); + SetJumpTarget(CondJump, NewBlock); +} + void OpDispatchBuilder::GenerateFlags_Rotate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2) { auto ZeroConst = _Constant(0); diff --git a/Source/Interface/Core/OpcodeDispatcher.h b/Source/Interface/Core/OpcodeDispatcher.h index dfc7146d6..1265f0ba0 100644 --- a/Source/Interface/Core/OpcodeDispatcher.h +++ b/Source/Interface/Core/OpcodeDispatcher.h @@ -294,6 +294,7 @@ private: void GenerateFlags_MUL(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *High); void GenerateFlags_UMUL(FEXCore::X86Tables::DecodedOp Op, OrderedNode *High); void GenerateFlags_Logical(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2); + void GenerateFlags_Shift(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2); void GenerateFlags_Rotate(FEXCore::X86Tables::DecodedOp Op, OrderedNode *Res, OrderedNode *Src1, OrderedNode *Src2); OrderedNode *CreateNode(IROp_Header *Op) {