mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-24 19:00:48 +02:00
Implements CMPS support for REPNE and no prefix
This commit is contained in:
1 parent
963de98276
commit
a8f4e8a860
1 file changed
+87
-48
+87
-48
@@ -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<IROp_CondJump> 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<IROp_CondJump> 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) {
|
||||
|
||||
Reference in new issue
Block a user