From d587485383936b182fe7b967149c5a6bd9da1edc Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 21 Jun 2021 00:20:44 -0700 Subject: [PATCH] Implements 32-bit iret instruction This is necessary for wine and some wine-like emulation layers. With this implemented then some Saint's Row games start running. Fixes #1100 --- .../Interface/Core/OpcodeDispatcher.cpp | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 70ba43d31..150dc59d8 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -178,6 +178,7 @@ void OpDispatchBuilder::RETOp(OpcodeArgs) { /* stack contains: +Size of each member is 64-bit, 32-bit, or 16-bit depending on operating size RIP CS EFLAGS @@ -185,8 +186,9 @@ RSP SS */ void OpDispatchBuilder::IRETOp(OpcodeArgs) { - if (CTX->Config.Is64BitMode == false) { - LogMan::Msg::E("IRET only implemented for x64"); + // Operand Size override unsupported! + if ((Op->Flags & X86Tables::DecodeFlags::FLAG_OPERAND_SIZE) != 0) { + LogMan::Msg::E("IRET only implemented for 64bit and 32bit sizes"); DecodeFailure = true; return; } @@ -197,7 +199,7 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) { OrderedNode* SP = _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), GPRClass); - // RIP (64 bits) + // RIP (64/32/16 bits) auto NewRIP = _LoadMem(GPRClass, GPRSize, SP, GPRSize); SP = _Add(SP, Constant); //CS (lower 16 used) @@ -206,13 +208,17 @@ void OpDispatchBuilder::IRETOp(OpcodeArgs) { //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); + + if (CTX->Config.Is64BitMode) { + // RSP and SS only happen in 64-bit mode or if this is a CPL mode jump! + 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(NewRIP); BlockSetRIP = true;