From 61df7a576ae168ca2a0b08f9eea0ddce3bd2875c Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 30 Aug 2023 19:20:46 -0700 Subject: [PATCH] OpcodeDispatcher: Be super defensive when starting a new block Ensure all cached data is correct. --- .../Interface/Core/OpcodeDispatcher.cpp | 44 +++++++++++++++++++ .../Core/OpcodeDispatcher/Vector.cpp | 5 +++ 2 files changed, 49 insertions(+) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 64d0ca025..2007e255a 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1139,6 +1139,7 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAtEnd(); SetTrueJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); auto NewRIP = GetRelocatedPC(Op, TargetOffset); @@ -1156,6 +1157,7 @@ void OpDispatchBuilder::CondJUMPOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(CurrentBlock); SetFalseJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); // Leave block auto RIPTargetConst = GetRelocatedPC(Op); @@ -1202,6 +1204,7 @@ void OpDispatchBuilder::CondJUMPRCXOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAtEnd(); SetTrueJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); auto NewRIP = GetRelocatedPC(Op, Op->Src[0].Data.Literal.Value); @@ -1219,6 +1222,7 @@ void OpDispatchBuilder::CondJUMPRCXOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(CurrentBlock); SetFalseJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); // Leave block auto RIPTargetConst = GetRelocatedPC(Op); @@ -1282,6 +1286,7 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAtEnd(); SetTrueJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); auto NewRIP = GetRelocatedPC(Op, Op->Src[1].Data.Literal.Value); @@ -1299,6 +1304,7 @@ void OpDispatchBuilder::LoopOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(GetCurrentBlock()); SetFalseJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); // Leave block auto RIPTargetConst = GetRelocatedPC(Op); @@ -1350,6 +1356,7 @@ void OpDispatchBuilder::JUMPOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(GetCurrentBlock()); SetJumpTarget(Jump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); _ExitFunction(GetRelocatedPC(Op, TargetOffset)); } return; @@ -1929,6 +1936,7 @@ void OpDispatchBuilder::SHLDOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(CurrentBlock); SetFalseJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); if (Size != 64) { Res = _Bfe(OpSize::i64Bit, Size, 0, Res); @@ -1943,6 +1951,7 @@ void OpDispatchBuilder::SHLDOp(OpcodeArgs) { SetJumpTarget(Jump, NextJumpTarget); SetTrueJumpTarget(CondJump, NextJumpTarget); SetCurrentCodeBlock(NextJumpTarget); + StartNewBlock(); } void OpDispatchBuilder::SHLDImmediateOp(OpcodeArgs) { @@ -2027,6 +2036,7 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(GetCurrentBlock()); SetFalseJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); if (Size != 64) { Res = _Bfe(OpSize::i64Bit, Size, 0, Res); @@ -2041,6 +2051,7 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) { SetJumpTarget(Jump, NextJumpTarget); SetTrueJumpTarget(CondJump, NextJumpTarget); SetCurrentCodeBlock(NextJumpTarget); + StartNewBlock(); } void OpDispatchBuilder::SHRDImmediateOp(OpcodeArgs) { @@ -3424,11 +3435,13 @@ void OpDispatchBuilder::DAAOp(OpcodeArgs) { CalculateDeferredFlags(); _CondJump(Cond, TrueBlock, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); { SetRFLAG(_Constant(0)); _Jump(EndBlock); } SetCurrentCodeBlock(TrueBlock); + StartNewBlock(); { auto NewAL = _Add(OpSize::i64Bit, AL, _Constant(0x6)); StoreGPRRegister(X86State::REG_RAX, NewAL, 1); @@ -3444,6 +3457,7 @@ void OpDispatchBuilder::DAAOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(EndBlock); + StartNewBlock(); Cond = _Or(OpSize::i64Bit, CF, _Select(FEXCore::IR::COND_UGT, AL, _Constant(0x99), _Constant(1), _Constant(0))); FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock()); @@ -3451,12 +3465,14 @@ void OpDispatchBuilder::DAAOp(OpcodeArgs) { EndBlock = CreateNewCodeBlockAfter(TrueBlock); _CondJump(Cond, TrueBlock, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); { SetRFLAG(_Constant(0)); CalculateDeferredFlags(); _Jump(EndBlock); } SetCurrentCodeBlock(TrueBlock); + StartNewBlock(); { AL = LoadGPRRegister(X86State::REG_RAX, 1); @@ -3467,6 +3483,7 @@ void OpDispatchBuilder::DAAOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(EndBlock); + StartNewBlock(); // Update Flags AL = LoadGPRRegister(X86State::REG_RAX, 1); @@ -3492,11 +3509,13 @@ void OpDispatchBuilder::DASOp(OpcodeArgs) { CalculateDeferredFlags(); _CondJump(Cond, TrueBlock, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); { SetRFLAG(_Constant(0)); _Jump(EndBlock); } SetCurrentCodeBlock(TrueBlock); + StartNewBlock(); { auto NewAL = _Sub(OpSize::i64Bit, AL, _Constant(0x6)); StoreGPRRegister(X86State::REG_RAX, NewAL, 1); @@ -3512,6 +3531,7 @@ void OpDispatchBuilder::DASOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(EndBlock); + StartNewBlock(); Cond = _Or(OpSize::i64Bit, CF, _Select(FEXCore::IR::COND_UGT, AL, _Constant(0x99), _Constant(1), _Constant(0))); FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock()); @@ -3519,12 +3539,14 @@ void OpDispatchBuilder::DASOp(OpcodeArgs) { EndBlock = CreateNewCodeBlockAfter(TrueBlock); _CondJump(Cond, TrueBlock, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); { SetRFLAG(_Constant(0)); CalculateDeferredFlags(); _Jump(EndBlock); } SetCurrentCodeBlock(TrueBlock); + StartNewBlock(); { AL = LoadGPRRegister(X86State::REG_RAX, 1); auto NewAL = _Sub(OpSize::i64Bit, AL, _Constant(0x60)); @@ -3534,6 +3556,7 @@ void OpDispatchBuilder::DASOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(EndBlock); + StartNewBlock(); // Update Flags AL = LoadGPRRegister(X86State::REG_RAX, 1); SetRFLAG(_Select(FEXCore::IR::COND_UGE, _And(OpSize::i64Bit, AL, _Constant(0x80)), _Constant(0), _Constant(1), _Constant(0))); @@ -3555,6 +3578,7 @@ void OpDispatchBuilder::AAAOp(OpcodeArgs) { _CondJump(Cond, TrueBlock, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); { auto NewAX = _And(OpSize::i64Bit, AX, _Constant(0xFF0F)); StoreGPRRegister(X86State::REG_RAX, NewAX, 2); @@ -3564,6 +3588,8 @@ void OpDispatchBuilder::AAAOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(TrueBlock); + StartNewBlock(); + { auto NewAX = _Add(OpSize::i64Bit, AX, _Constant(0x106)); auto Result = _And(OpSize::i64Bit, NewAX, _Constant(0xFF0F)); @@ -3574,6 +3600,7 @@ void OpDispatchBuilder::AAAOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(EndBlock); + StartNewBlock(); } void OpDispatchBuilder::AASOp(OpcodeArgs) { @@ -3590,6 +3617,7 @@ void OpDispatchBuilder::AASOp(OpcodeArgs) { _CondJump(Cond, TrueBlock, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); { auto NewAX = _And(OpSize::i64Bit, AX, _Constant(0xFF0F)); StoreGPRRegister(X86State::REG_RAX, NewAX, 2); @@ -3599,6 +3627,7 @@ void OpDispatchBuilder::AASOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(TrueBlock); + StartNewBlock(); { auto NewAX = _Sub(OpSize::i64Bit, AX, _Constant(6)); NewAX = _Sub(OpSize::i64Bit, NewAX, _Constant(0x100)); @@ -3610,6 +3639,7 @@ void OpDispatchBuilder::AASOp(OpcodeArgs) { _Jump(EndBlock); } SetCurrentCodeBlock(EndBlock); + StartNewBlock(); } void OpDispatchBuilder::AAMOp(OpcodeArgs) { @@ -3995,6 +4025,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { auto LoopStart = CreateNewCodeBlockAfter(GetCurrentBlock()); SetJumpTarget(JumpStart, LoopStart); SetCurrentCodeBlock(LoopStart); + StartNewBlock(); OrderedNode *Counter = LoadGPRRegister(X86State::REG_RCX); @@ -4005,6 +4036,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { auto LoopTail = CreateNewCodeBlockAfter(LoopStart); SetFalseJumpTarget(CondJump, LoopTail); SetCurrentCodeBlock(LoopTail); + StartNewBlock(); // Working loop { @@ -4059,6 +4091,7 @@ void OpDispatchBuilder::CMPSOp(OpcodeArgs) { SetFalseJumpTarget(InternalCondJump, LoopEnd); SetCurrentCodeBlock(LoopEnd); + StartNewBlock(); } } @@ -4118,6 +4151,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { auto LoopStart = CreateNewCodeBlockAfter(GetCurrentBlock()); SetJumpTarget(JumpStart, LoopStart); SetCurrentCodeBlock(LoopStart); + StartNewBlock(); OrderedNode *Counter = LoadGPRRegister(X86State::REG_RCX); @@ -4129,6 +4163,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { auto LoopTail = CreateNewCodeBlockAfter(LoopStart); SetFalseJumpTarget(CondJump, LoopTail); SetCurrentCodeBlock(LoopTail); + StartNewBlock(); // Working loop { @@ -4160,6 +4195,7 @@ void OpDispatchBuilder::LODSOp(OpcodeArgs) { auto LoopEnd = CreateNewCodeBlockAfter(LoopTail); SetTrueJumpTarget(CondJump, LoopEnd); SetCurrentCodeBlock(LoopEnd); + StartNewBlock(); } } @@ -4220,6 +4256,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { auto LoopStart = CreateNewCodeBlockAfter(GetCurrentBlock()); SetJumpTarget(JumpStart, LoopStart); SetCurrentCodeBlock(LoopStart); + StartNewBlock(); OrderedNode *Counter = LoadGPRRegister(X86State::REG_RCX); @@ -4231,6 +4268,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { auto LoopTail = CreateNewCodeBlockAfter(LoopStart); SetFalseJumpTarget(CondJump, LoopTail); SetCurrentCodeBlock(LoopTail); + StartNewBlock(); // Working loop { @@ -4277,6 +4315,7 @@ void OpDispatchBuilder::SCASOp(OpcodeArgs) { SetFalseJumpTarget(InternalCondJump, LoopEnd); SetCurrentCodeBlock(LoopEnd); + StartNewBlock(); } } @@ -4702,6 +4741,7 @@ void OpDispatchBuilder::CMPXCHGPairOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(GetCurrentBlock()); SetFalseJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); StoreGPRRegister(X86State::REG_RAX, Result_Lower); StoreGPRRegister(X86State::REG_RDX, Result_Upper); @@ -4711,6 +4751,7 @@ void OpDispatchBuilder::CMPXCHGPairOp(OpcodeArgs) { SetJumpTarget(Jump, NextJumpTarget); SetTrueJumpTarget(CondJump, NextJumpTarget); SetCurrentCodeBlock(NextJumpTarget); + StartNewBlock(); } void OpDispatchBuilder::CreateJumpBlocks(fextl::vector const *Blocks) { @@ -5560,6 +5601,7 @@ void OpDispatchBuilder::INTOp(OpcodeArgs) { auto FalseBlock = CreateNewCodeBlockAfter(GetCurrentBlock()); SetFalseJumpTarget(CondJump, FalseBlock); SetCurrentCodeBlock(FalseBlock); + StartNewBlock(); auto NewRIP = GetRelocatedPC(Op); _StoreContext(GPRSize, GPRClass, NewRIP, offsetof(FEXCore::Core::CPUState, rip)); @@ -5569,6 +5611,7 @@ void OpDispatchBuilder::INTOp(OpcodeArgs) { auto JumpTarget = CreateNewCodeBlockAfter(FalseBlock); SetTrueJumpTarget(CondJump, JumpTarget); SetCurrentCodeBlock(JumpTarget); + StartNewBlock(); } else { BlockSetRIP = true; @@ -5712,6 +5755,7 @@ void OpDispatchBuilder::UnimplementedOp(OpcodeArgs) { if (Multiblock) { auto NextBlock = CreateNewCodeBlockAfter(GetCurrentBlock()); SetCurrentCodeBlock(NextBlock); + StartNewBlock(); } } diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index a3faa673d..ba9221df1 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -2550,6 +2550,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) { auto StoreBlock = CreateNewCodeBlockAfter(GetCurrentBlock()); SetTrueJumpTarget(CondJump, StoreBlock); SetCurrentCodeBlock(StoreBlock); + StartNewBlock(); { fn(); } @@ -2558,6 +2559,7 @@ void OpDispatchBuilder::XSaveOpImpl(OpcodeArgs) { SetJumpTarget(Jump, NextJumpTarget); SetFalseJumpTarget(CondJump, NextJumpTarget); SetCurrentCodeBlock(NextJumpTarget); + StartNewBlock(); }; // x87 @@ -2758,6 +2760,7 @@ void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) { auto RestoreBlock = CreateNewCodeBlockAfter(GetCurrentBlock()); SetTrueJumpTarget(CondJump, RestoreBlock); SetCurrentCodeBlock(RestoreBlock); + StartNewBlock(); { restore_fn(); } @@ -2767,12 +2770,14 @@ void OpDispatchBuilder::XRstorOpImpl(OpcodeArgs) { SetJumpTarget(RestoreExitJump, ExitBlock); SetFalseJumpTarget(CondJump, DefaultBlock); SetCurrentCodeBlock(DefaultBlock); + StartNewBlock(); { default_fn(); } auto DefaultExitJump = _Jump(); SetJumpTarget(DefaultExitJump, ExitBlock); SetCurrentCodeBlock(ExitBlock); + StartNewBlock(); }; // x87