From 7a052000c9e94abebbe06d3d4a4da7ddea6888a7 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 9 Mar 2020 18:15:05 -0700 Subject: [PATCH] Implements SCAS with no repeat prefix This is used in a couple unit tests --- .../Interface/Core/OpcodeDispatcher.cpp | 128 +++++++++++------- 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index f448cc1e8..b33aee409 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1994,76 +1994,104 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { } void OpDispatchBuilder::SCASOp(OpcodeArgs) { - LogMan::Throw::A(Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX, "Can only handle REPNE\n"); + LogMan::Throw::A( + (Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX) || + !(Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX), + "Can only handle REPNE Or NONE\n"); auto Size = GetSrcSize(Op); + bool Repeat = Op->Flags & (FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX | FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX); - auto JumpStart = _Jump(); - // Make sure to start a new block after ending this one - auto LoopStart = CreateNewCodeBlock(); - SetJumpTarget(JumpStart, LoopStart); - SetCurrentCodeBlock(LoopStart); + if (!Repeat) { + OrderedNode *Dest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); - auto ZeroConst = _Constant(0); - auto OneConst = _Constant(1); + auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + auto Src2 = _LoadMem(GPRClass, Size, Dest_RDI, Size); - OrderedNode *Counter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); + auto ALUOp = _Sub(Src1, Src2); + GenerateFlags_SUB(Op, ALUOp, Src1, Src2); - // Can we end the block? - OrderedNode *CanLeaveCond = _Select(FEXCore::IR::COND_EQ, - Counter, ZeroConst, - OneConst, ZeroConst); + auto SizeConst = _Constant(Size); + auto NegSizeConst = _Constant(-Size); - // We leave if RCX = 0 - auto CondJump = _CondJump(CanLeaveCond); - IRPair InternalCondJump; + auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); + auto PtrDir = _Select(FEXCore::IR::COND_EQ, + DF, _Constant(0), + SizeConst, NegSizeConst); - auto LoopTail = CreateNewCodeBlock(); - SetFalseJumpTarget(CondJump, LoopTail); - SetCurrentCodeBlock(LoopTail); + // Offset the pointer + OrderedNode *TailDest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); + TailDest_RDI = _Add(TailDest_RDI, PtrDir); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), TailDest_RDI); + } + else { + auto JumpStart = _Jump(); + // Make sure to start a new block after ending this one + auto LoopStart = CreateNewCodeBlock(); + SetJumpTarget(JumpStart, LoopStart); + SetCurrentCodeBlock(LoopStart); - // Working loop - { - OrderedNode *Dest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); + auto ZeroConst = _Constant(0); + auto OneConst = _Constant(1); - auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); - auto Src2 = _LoadMem(GPRClass, Size, Dest_RDI, Size); + OrderedNode *Counter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); - auto ALUOp = _Sub(Src1, Src2); - GenerateFlags_SUB(Op, ALUOp, Src1, Src2); + // Can we end the block? + OrderedNode *CanLeaveCond = _Select(FEXCore::IR::COND_EQ, + Counter, ZeroConst, + OneConst, ZeroConst); - OrderedNode *TailCounter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); - OrderedNode *TailDest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); + // We leave if RCX = 0 + auto CondJump = _CondJump(CanLeaveCond); + IRPair InternalCondJump; - // Decrement counter - TailCounter = _Sub(TailCounter, _Constant(1)); + auto LoopTail = CreateNewCodeBlock(); + SetFalseJumpTarget(CondJump, LoopTail); + SetCurrentCodeBlock(LoopTail); - // 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); + // Working loop + { + OrderedNode *Dest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); - auto SizeConst = _Constant(Size); - auto NegSizeConst = _Constant(-Size); + auto Src1 = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1); + auto Src2 = _LoadMem(GPRClass, Size, Dest_RDI, Size); - auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); - auto PtrDir = _Select(FEXCore::IR::COND_EQ, - DF, _Constant(0), - SizeConst, NegSizeConst); + auto ALUOp = _Sub(Src1, Src2); + GenerateFlags_SUB(Op, ALUOp, Src1, Src2); - // Offset the pointer - TailDest_RDI = _Add(TailDest_RDI, PtrDir); - _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), TailDest_RDI); + OrderedNode *TailCounter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass); + OrderedNode *TailDest_RDI = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass); - OrderedNode *ZF = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); - InternalCondJump = _CondJump(ZF); + // Decrement counter + TailCounter = _Sub(TailCounter, _Constant(1)); - // Jump back to the start if we have more work to do - SetFalseJumpTarget(InternalCondJump, LoopStart); + // 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 SizeConst = _Constant(Size); + auto NegSizeConst = _Constant(-Size); + + auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC); + auto PtrDir = _Select(FEXCore::IR::COND_EQ, + DF, _Constant(0), + SizeConst, NegSizeConst); + + // Offset the pointer + TailDest_RDI = _Add(TailDest_RDI, PtrDir); + _StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), TailDest_RDI); + + OrderedNode *ZF = GetRFLAG(FEXCore::X86State::RFLAG_ZF_LOC); + InternalCondJump = _CondJump(ZF); + + // 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); + SetTrueJumpTarget(InternalCondJump, LoopEnd); + SetCurrentCodeBlock(LoopEnd); } - // Make sure to start a new block after ending this one - auto LoopEnd = CreateNewCodeBlock(); - SetTrueJumpTarget(CondJump, LoopEnd); - SetTrueJumpTarget(InternalCondJump, LoopEnd); - SetCurrentCodeBlock(LoopEnd); } void OpDispatchBuilder::BSWAPOp(OpcodeArgs) {