From 23a4e83ba2c810b80957f5a90d7b01645acdad37 Mon Sep 17 00:00:00 2001 From: Stefanos Kornilios Mitsis Poiitidis Date: Mon, 21 Sep 2020 13:40:42 +0300 Subject: [PATCH] x86-64: Implement IRET for wine --- .../Interface/Core/OpcodeDispatcher.cpp | 39 +++++++++++++++++++ .../Source/Interface/Core/OpcodeDispatcher.h | 1 + .../Interface/Core/X86Tables/BaseTables.cpp | 2 +- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 2e7dd76c2..9e1577d49 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -168,6 +168,44 @@ void OpDispatchBuilder::RETOp(OpcodeArgs) { BlockSetRIP = true; } +/* +stack contains: +RIP +CS +EFLAGS +RSP +SS +*/ +void OpDispatchBuilder::IRETOp(OpcodeArgs) { + LogMan::Throw::A(CTX->Config.Is64BitMode == true, "IRET only implemented for x64"); + + uint8_t GPRSize = CTX->Config.Is64BitMode ? 8 : 4; + + auto Constant = _Constant(GPRSize); + + OrderedNode* SP = _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), GPRClass); + + // RIP (64 bits) + _StoreContext(GPRClass, GPRSize, offsetof(FEXCore::Core::CPUState, rip), _LoadMem(GPRClass, GPRSize, SP, GPRSize)); + SP = _Add(SP, Constant); + //CS (lower 16 used) + _StoreContext(GPRClass, 2, offsetof(FEXCore::Core::CPUState, cs), _LoadMem(GPRClass, GPRSize, SP, GPRSize)); + SP = _Add(SP, Constant); + //eflags (lower 16 used) + auto eflags = _LoadMem(GPRClass, GPRSize, SP, GPRSize); + SetPackedRFLAG(false, eflags); + SP = _Add(SP, Constant); + // RSP + _StoreContext(GPRClass, GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), _LoadMem(GPRClass, GPRSize, SP, GPRSize)); + SP = _Add(SP, Constant); + //ss + _StoreContext(GPRClass, 2, offsetof(FEXCore::Core::CPUState, ss), _LoadMem(GPRClass, GPRSize, SP, GPRSize)); + SP = _Add(SP, Constant); + + _ExitFunction(); + BlockSetRIP = true; +} + void OpDispatchBuilder::SIGRETOp(OpcodeArgs) { // Store the new RIP _SignalReturn(); @@ -7477,6 +7515,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) { {0xC8, 1, &OpDispatchBuilder::EnterOp}, {0xC9, 1, &OpDispatchBuilder::LEAVEOp}, {0xCC, 2, &OpDispatchBuilder::INTOp}, + {0xCF, 1, &OpDispatchBuilder::IRETOp}, {0xD7, 2, &OpDispatchBuilder::XLATOp}, {0xE0, 3, &OpDispatchBuilder::LoopOp}, {0xE3, 1, &OpDispatchBuilder::CondJUMPRCXOp}, diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index 16e413cfd..d8daf4858 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -106,6 +106,7 @@ public: void LEAOp(OpcodeArgs); void NOPOp(OpcodeArgs); void RETOp(OpcodeArgs); + void IRETOp(OpcodeArgs); void SIGRETOp(OpcodeArgs); void CallbackReturnOp(OpcodeArgs); void SecondaryALUOp(OpcodeArgs); diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp index 8edd0349f..037160989 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp @@ -179,7 +179,7 @@ void InitializeBaseTables(Context::OperatingMode Mode) { {0xCC, 1, X86InstInfo{"INT3", TYPE_INST, FLAGS_DEBUG, 0, nullptr}}, {0xCD, 1, X86InstInfo{"INT", TYPE_INST, FLAGS_DEBUG , 1, nullptr}}, {0xCE, 1, X86InstInfo{"[INV]", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, - {0xCF, 1, X86InstInfo{"IRET", TYPE_PRIV, FLAGS_NONE, 0, nullptr}}, + {0xCF, 1, X86InstInfo{"IRET", TYPE_INST, FLAGS_SETS_RIP | FLAGS_BLOCK_END, 0, nullptr}}, {0xD4, 3, X86InstInfo{"[INV]", TYPE_INVALID, FLAGS_NONE, 0, nullptr}}, {0xD7, 1, X86InstInfo{"XLAT", TYPE_INST, FLAGS_DEBUG_MEM_ACCESS, 0, nullptr}},