From a8f4e8a8606efd675ea4e2438969d1ec7f82c839 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 10 Mar 2020 18:18:06 -0700 Subject: [PATCH] Implements CMPS support for REPNE and no prefix --- .../Interface/Core/OpcodeDispatcher.cpp | 135 +++++++++++------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index adfcabf63..00517ed0c 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1954,70 +1954,109 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { auto Size = GetSrcSize(Op); - auto JumpStart = _Jump(); - // Make sure to start a new block after ending this one - auto LoopStart = CreateNewCodeBlock(); - SetJumpTarget(JumpStart, LoopStart); - SetCurrentCodeBlock(LoopStart); + bool Repeat = Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX); + if (!Repeat) { + OrderedNode *Dest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); + OrderedNode *Dest_RSI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), GPRClass); - OrderedNode *Counter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); + auto Src1 = _LoadMem(GPRClass, Size, Dest_RDI, Size); + auto Src2 = _LoadMem(GPRClass, Size, Dest_RSI, Size); - // Can we end the block? - OrderedNode *CanLeaveCond = _Select(FEXCore::IR::COND_EQ, - Counter, _Constant(0), - _Constant(1), _Constant(0)); + auto ALUOp = _Sub(Src1, Src2); + GenerateFlags_SUB(Op, _Bfe(Size * 8, 0, ALUOp), _Bfe(Size * 8, 0, Src1), _Bfe(Size * 8, 0, Src2)); - auto CondJump = _CondJump(CanLeaveCond); - IRPair InternalCondJump; + auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); + auto PtrDir = _Select(FEXCore::IR::COND_EQ, + DF, _Constant(0), + _Constant(Size), _Constant(-Size)); - auto LoopTail = CreateNewCodeBlock(); - SetFalseJumpTarget(CondJump, LoopTail); - SetCurrentCodeBlock(LoopTail); + // Offset the pointer + Dest_RDI = _Add(Dest_RDI, PtrDir); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), Dest_RDI); - // Working loop - { - OrderedNode *Dest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); - OrderedNode *Dest_RSI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), GPRClass); + // Offset second pointer + Dest_RSI = _Add(Dest_RSI, PtrDir); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), Dest_RSI); + } + else { + bool REPE = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX; - auto Src1 = _LoadMem(GPRClass, Size, Dest_RDI, Size); - auto Src2 = _LoadMem(GPRClass, Size, Dest_RSI, Size); + auto JumpStart = _Jump(); + // Make sure to start a new block after ending this one + auto LoopStart = CreateNewCodeBlock(); + SetJumpTarget(JumpStart, LoopStart); + SetCurrentCodeBlock(LoopStart); - auto ALUOp = _Sub(Src1, Src2); - GenerateFlags_SUB(Op, _Bfe(Size * 8, 0, ALUOp), _Bfe(Size * 8, 0, Src1), _Bfe(Size * 8, 0, Src2)); + OrderedNode *Counter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); - OrderedNode *TailCounter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); + // Can we end the block? + OrderedNode *CanLeaveCond = _Select(FEXCore::IR::COND_EQ, + Counter, _Constant(0), + _Constant(1), _Constant(0)); - // Decrement counter - TailCounter = _Sub(TailCounter, _Constant(1)); + auto CondJump = _CondJump(CanLeaveCond); + IRPair InternalCondJump; - // Store the counter so we don't have to deal with PHI here - _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), TailCounter); + auto LoopTail = CreateNewCodeBlock(); + SetFalseJumpTarget(CondJump, LoopTail); + SetCurrentCodeBlock(LoopTail); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto PtrDir = _Select(FEXCore::IR::COND_EQ, - DF, _Constant(0), - _Constant(Size), _Constant(-Size)); + // Working loop + { + OrderedNode *Dest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); + OrderedNode *Dest_RSI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), GPRClass); - // Offset the pointer - Dest_RDI = _Add(Dest_RDI, PtrDir); - _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), Dest_RDI); + auto Src1 = _LoadMem(GPRClass, Size, Dest_RDI, Size); + auto Src2 = _LoadMem(GPRClass, Size, Dest_RSI, Size); - // Offset second pointer - Dest_RSI = _Add(Dest_RSI, PtrDir); - _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), Dest_RSI); + auto ALUOp = _Sub(Src1, Src2); + GenerateFlags_SUB(Op, _Bfe(Size * 8, 0, ALUOp), _Bfe(Size * 8, 0, Src1), _Bfe(Size * 8, 0, Src2)); - OrderedNode *ZF = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - InternalCondJump = _CondJump(ZF); + OrderedNode *TailCounter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); - // Jump back to the start if we have more work to do - SetTrueJumpTarget(InternalCondJump, LoopStart); + // Decrement counter + TailCounter = _Sub(TailCounter, _Constant(1)); + + // Store the counter so we don't have to deal with PHI here + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), TailCounter); + + auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); + auto PtrDir = _Select(FEXCore::IR::COND_EQ, + DF, _Constant(0), + _Constant(Size), _Constant(-Size)); + + // Offset the pointer + Dest_RDI = _Add(Dest_RDI, PtrDir); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), Dest_RDI); + + // Offset second pointer + Dest_RSI = _Add(Dest_RSI, PtrDir); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSI]), Dest_RSI); + + OrderedNode *ZF = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); + InternalCondJump = _CondJump(ZF); + + if (REPE) { + // Jump back to the start if we have more work to do + SetTrueJumpTarget(InternalCondJump, LoopStart); + } + else { + // Jump back to the start if we have more work to do + SetFalseJumpTarget(InternalCondJump, LoopStart); + } + } + + // Make sure to start a new block after ending this one + auto LoopEnd = CreateNewCodeBlock(); + SetTrueJumpTarget(CondJump, LoopEnd); + if (REPE) { + SetFalseJumpTarget(InternalCondJump, LoopEnd); } - - // Make sure to start a new block after ending this one - auto LoopEnd = CreateNewCodeBlock(); - SetTrueJumpTarget(CondJump, LoopEnd); - SetFalseJumpTarget(InternalCondJump, LoopEnd); - SetCurrentCodeBlock(LoopEnd); + else { + SetTrueJumpTarget(InternalCondJump, LoopEnd); + } + SetCurrentCodeBlock(LoopEnd); + } } void OpDispatchBuilder::SCASOp(OpcodeArgs) {