mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-27 09:00:57 +01:00
Merge pull request #486 from FEX-Emu/skmp/abi-opts
Unsafe opts: --unsafe-local-flags, --unsafe-no-pf, --unsafe-no-tso
This commit is contained in:
12 files changed
+103
-34
No files matched your search
@@ -39,6 +39,12 @@ namespace FEXCore::Config {
|
||||
case FEXCore::Config::CONFIG_SMC_CHECKS:
|
||||
CTX->Config.SMCChecks = Config != 0;
|
||||
break;
|
||||
case FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS:
|
||||
CTX->Config.ABILocalFlags = Config != 0;
|
||||
break;
|
||||
case FEXCore::Config::CONFIG_ABI_NO_PF:
|
||||
CTX->Config.ABINoPF = Config != 0;
|
||||
break;
|
||||
default: LogMan::Msg::A("Unknown configuration option");
|
||||
}
|
||||
}
|
||||
@@ -92,6 +98,12 @@ namespace FEXCore::Config {
|
||||
case FEXCore::Config::CONFIG_SMC_CHECKS:
|
||||
return CTX->Config.SMCChecks;
|
||||
break;
|
||||
case FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS:
|
||||
return CTX->Config.ABILocalFlags;
|
||||
break;
|
||||
case FEXCore::Config::CONFIG_ABI_NO_PF:
|
||||
return CTX->Config.ABINoPF;
|
||||
break;
|
||||
default: LogMan::Msg::A("Unknown configuration option");
|
||||
}
|
||||
|
||||
|
||||
@@ -62,8 +62,11 @@ namespace FEXCore::Context {
|
||||
uint64_t EmulatedCPUCores{1};
|
||||
bool TSOEnabled {true};
|
||||
bool SMCChecks {false};
|
||||
bool ABILocalFlags {false};
|
||||
bool ABINoPF {false};
|
||||
|
||||
std::string DumpIR;
|
||||
|
||||
} Config;
|
||||
|
||||
FEXCore::Memory::MemMapper MemoryMapper;
|
||||
|
||||
@@ -488,6 +488,7 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
|
||||
case IR::OP_DUMMY:
|
||||
case IR::OP_BEGINBLOCK:
|
||||
case IR::OP_ENDBLOCK:
|
||||
case IR::OP_INVALIDATEFLAGS:
|
||||
break;
|
||||
case IR::OP_FENCE: {
|
||||
auto Op = IROp->C<IR::IROp_Fence>();
|
||||
|
||||
@@ -126,6 +126,7 @@ void JITCore::RegisterMiscHandlers() {
|
||||
REGISTER_OP(PRINT, Unhandled);
|
||||
REGISTER_OP(GETROUNDINGMODE, GetRoundingMode);
|
||||
REGISTER_OP(SETROUNDINGMODE, SetRoundingMode);
|
||||
REGISTER_OP(INVALIDATEFLAGS, NoOp);
|
||||
#undef REGISTER_OP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@ void JITCore::RegisterMiscHandlers() {
|
||||
REGISTER_OP(PRINT, Print);
|
||||
REGISTER_OP(GETROUNDINGMODE, GetRoundingMode);
|
||||
REGISTER_OP(SETROUNDINGMODE, SetRoundingMode);
|
||||
REGISTER_OP(INVALIDATEFLAGS, NoOp);
|
||||
#undef REGISTER_OP
|
||||
}
|
||||
}
|
||||
|
||||
+22
-11
@@ -144,6 +144,11 @@ void OpDispatchBuilder::NOPOp(OpcodeArgs) {
|
||||
void OpDispatchBuilder::RETOp(OpcodeArgs) {
|
||||
uint8_t GPRSize = CTX->Config.Is64BitMode ? 8 : 4;
|
||||
|
||||
// ABI Optimization: Flags don't survive calls or rets
|
||||
if (CTX->Config.ABILocalFlags) {
|
||||
_InvalidateFlags();
|
||||
}
|
||||
|
||||
auto Constant = _Constant(GPRSize);
|
||||
|
||||
auto OldSP = _LoadContext(GPRSize, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RSP]), GPRClass);
|
||||
@@ -622,6 +627,12 @@ void OpDispatchBuilder::CALLOp(OpcodeArgs) {
|
||||
uint8_t GPRSize = CTX->Config.Is64BitMode ? 8 : 4;
|
||||
|
||||
BlockSetRIP = true;
|
||||
|
||||
// ABI Optimization: Flags don't survive calls or rets
|
||||
if (CTX->Config.ABILocalFlags) {
|
||||
_InvalidateFlags();
|
||||
}
|
||||
|
||||
auto ConstantPC = _Constant(Op->PC + Op->InstSize);
|
||||
|
||||
OrderedNode *JMPPCOffset = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
|
||||
@@ -4721,7 +4732,7 @@ void OpDispatchBuilder::GenerateFlags_ADC(FEXCore::X86Tables::DecodedOp Op, Orde
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto PopCountOp = _Popcount(_And(Res, _Constant(0xFF)));
|
||||
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -4788,7 +4799,7 @@ void OpDispatchBuilder::GenerateFlags_SBB(FEXCore::X86Tables::DecodedOp Op, Orde
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto PopCountOp = _Popcount(_And(Res, _Constant(0xFF)));
|
||||
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -4854,7 +4865,7 @@ void OpDispatchBuilder::GenerateFlags_SUB(FEXCore::X86Tables::DecodedOp Op, Orde
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -4909,7 +4920,7 @@ void OpDispatchBuilder::GenerateFlags_ADD(FEXCore::X86Tables::DecodedOp Op, Orde
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5019,7 +5030,7 @@ void OpDispatchBuilder::GenerateFlags_Logical(FEXCore::X86Tables::DecodedOp Op,
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5056,7 +5067,7 @@ void OpDispatchBuilder::GenerateFlags_ShiftLeft(FEXCore::X86Tables::DecodedOp Op
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5102,7 +5113,7 @@ void OpDispatchBuilder::GenerateFlags_ShiftRight(FEXCore::X86Tables::DecodedOp O
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5148,7 +5159,7 @@ void OpDispatchBuilder::GenerateFlags_SignShiftRight(FEXCore::X86Tables::Decoded
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5194,7 +5205,7 @@ void OpDispatchBuilder::GenerateFlags_ShiftLeftImmediate(FEXCore::X86Tables::Dec
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5241,7 +5252,7 @@ void OpDispatchBuilder::GenerateFlags_SignShiftRightImmediate(FEXCore::X86Tables
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
@@ -5290,7 +5301,7 @@ void OpDispatchBuilder::GenerateFlags_ShiftRightImmediate(FEXCore::X86Tables::De
|
||||
}
|
||||
|
||||
// PF
|
||||
{
|
||||
if (!CTX->Config.ABINoPF) {
|
||||
auto EightBitMask = _Constant(0xFF);
|
||||
auto PopCountOp = _Popcount(_And(Res, EightBitMask));
|
||||
auto XorOp = _Xor(PopCountOp, _Constant(1));
|
||||
|
||||
@@ -89,6 +89,11 @@
|
||||
]
|
||||
},
|
||||
|
||||
"InvalidateFlags": {
|
||||
"OpClass": "Misc",
|
||||
"HasSideEffects": true
|
||||
},
|
||||
|
||||
"EndBlock": {
|
||||
"HasSideEffects": true,
|
||||
"OpClass": "Misc",
|
||||
|
||||
@@ -42,6 +42,9 @@ bool DeadFlagStoreElimination::Run(IREmitter *IREmit) {
|
||||
auto Op = IROp->CW<IR::IROp_StoreFlag>();
|
||||
FlagMap[BlockNode].writes |= 1 << Op->Flag;
|
||||
}
|
||||
else if (IROp->Op == OP_INVALIDATEFLAGS) {
|
||||
FlagMap[BlockNode].writes = -1;
|
||||
}
|
||||
else if (IROp->Op == OP_LOADFLAG) {
|
||||
auto Op = IROp->CW<IR::IROp_LoadFlag>();
|
||||
FlagMap[BlockNode].reads |= 1 << Op->Flag;
|
||||
|
||||
+3
-1
@@ -18,7 +18,9 @@ namespace FEXCore::Config {
|
||||
CONFIG_EMULATED_CPU_CORES,
|
||||
CONFIG_TSO_ENABLED,
|
||||
CONFIG_SMC_CHECKS,
|
||||
CONFIG_DUMPIR
|
||||
CONFIG_ABI_LOCAL_FLAGS,
|
||||
CONFIG_ABI_NO_PF,
|
||||
CONFIG_DUMPIR,
|
||||
};
|
||||
|
||||
enum ConfigCore {
|
||||
|
||||
@@ -48,29 +48,23 @@ namespace FEX::ArgLoader {
|
||||
.dest("MaxInst")
|
||||
.help("Maximum number of instructions to stick in a block")
|
||||
.set_default(~0U);
|
||||
CPUGroup.add_option("-m", "--multiblock")
|
||||
.dest("Multiblock")
|
||||
.action("store_true")
|
||||
.help("Enable Multiblock code compilation");
|
||||
CPUGroup.add_option("--no-multiblock")
|
||||
.dest("Multiblock")
|
||||
.action("store_false")
|
||||
.help("Enable Multiblock code compilation");
|
||||
CPUGroup.add_option("-G", "--gdb")
|
||||
.dest("GdbServer")
|
||||
.action("store_true")
|
||||
.help("Enables the GDB server");
|
||||
CPUGroup.add_option("-m", "--multiblock")
|
||||
.dest("Multiblock")
|
||||
.action("store_true")
|
||||
.help("Enable Multiblock code compilation");
|
||||
CPUGroup.add_option("--no-multiblock")
|
||||
.dest("Multiblock")
|
||||
.action("store_false")
|
||||
.help("Enable Multiblock code compilation");
|
||||
CPUGroup.add_option("-G", "--gdb")
|
||||
.dest("GdbServer")
|
||||
.action("store_true")
|
||||
.help("Enables the GDB server");
|
||||
|
||||
CPUGroup.add_option("-T", "--Threads")
|
||||
.dest("Threads")
|
||||
.help("Number of physical hardware threads to tell the process we have")
|
||||
.set_default(1);
|
||||
|
||||
CPUGroup.add_option("--disable-tso")
|
||||
.dest("TSOEnabled")
|
||||
.action("store_false")
|
||||
.help("Disables TSO IR ops. Highly likely to break any threaded application")
|
||||
.set_default(true);
|
||||
CPUGroup.add_option("-T", "--Threads")
|
||||
.dest("Threads")
|
||||
.help("Number of physical hardware threads to tell the process we have")
|
||||
.set_default(1);
|
||||
|
||||
CPUGroup.add_option("--smc-full-checks")
|
||||
.dest("SMCChecks")
|
||||
@@ -78,6 +72,24 @@ namespace FEX::ArgLoader {
|
||||
.help("Checks code for modification before execution. Slow.")
|
||||
.set_default(false);
|
||||
|
||||
CPUGroup.add_option("--unsafe-no-tso")
|
||||
.dest("TSOEnabled")
|
||||
.action("store_false")
|
||||
.help("Disables TSO IR ops. Highly likely to break any threaded application")
|
||||
.set_default(true);
|
||||
|
||||
CPUGroup.add_option("--unsafe-local-flags")
|
||||
.dest("AbiLocalFlags")
|
||||
.action("store_true")
|
||||
.help("Assumes flags are not used across calls. Hand-written asm could violate this assumption")
|
||||
.set_default(false);
|
||||
|
||||
CPUGroup.add_option("--unsafe-no-pf")
|
||||
.dest("AbiNoPF")
|
||||
.action("store_true")
|
||||
.help("Does not calculate the parity flag on integer operations")
|
||||
.set_default(false);
|
||||
|
||||
Parser.add_option_group(CPUGroup);
|
||||
}
|
||||
{
|
||||
@@ -208,6 +220,14 @@ namespace FEX::ArgLoader {
|
||||
bool SMCChecks = Options.get("SMCChecks");
|
||||
Config::Add("SMCChecks", std::to_string(SMCChecks));
|
||||
}
|
||||
if (Options.is_set_by_user("AbiLocalFlags")) {
|
||||
bool AbiLocalFlags = Options.get("AbiLocalFlags");
|
||||
Config::Add("AbiLocalFlags", std::to_string(AbiLocalFlags));
|
||||
}
|
||||
if (Options.is_set_by_user("AbiNoPF")) {
|
||||
bool AbiNoPF = Options.get("AbiNoPF");
|
||||
Config::Add("AbiNoPF", std::to_string(AbiNoPF));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -111,6 +111,8 @@ int main(int argc, char **argv, char **const envp) {
|
||||
FEX::Config::Value<std::string> DumpIR{"DumpIR", "no"};
|
||||
FEX::Config::Value<bool> TSOEnabledConfig{"TSOEnabled", true};
|
||||
FEX::Config::Value<bool> SMCChecksConfig{"SMCChecks", false};
|
||||
FEX::Config::Value<bool> ABILocalFlags{"ABILocalFlags", false};
|
||||
FEX::Config::Value<bool> AbiNoPF{"AbiNoPF", false};
|
||||
|
||||
::SilentLog = SilentLog();
|
||||
|
||||
@@ -156,6 +158,8 @@ int main(int argc, char **argv, char **const envp) {
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_EMULATED_CPU_CORES, ThreadsConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_TSO_ENABLED, TSOEnabledConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_SMC_CHECKS, SMCChecksConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, ABILocalFlags());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ABI_NO_PF, AbiNoPF());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_DUMPIR, DumpIR());
|
||||
|
||||
FEXCore::Context::SetCustomCPUBackendFactory(CTX, VMFactory::CPUCreationFactory);
|
||||
|
||||
@@ -60,7 +60,10 @@ int main(int argc, char **argv, char **const envp) {
|
||||
FEX::Config::Value<uint64_t> BlockSizeConfig{"MaxInst", 1};
|
||||
FEX::Config::Value<bool> SingleStepConfig{"SingleStep", false};
|
||||
FEX::Config::Value<bool> MultiblockConfig{"Multiblock", false};
|
||||
FEX::Config::Value<bool> TSOEnabledConfig{"TSOEnabled", true};
|
||||
FEX::Config::Value<bool> SMCChecksConfig{"SMCChecks", false};
|
||||
FEX::Config::Value<bool> ABILocalFlags{"ABILocalFlags", false};
|
||||
FEX::Config::Value<bool> AbiNoPF{"AbiNoPF", false};
|
||||
|
||||
auto Args = FEX::ArgLoader::Get();
|
||||
|
||||
@@ -78,7 +81,10 @@ int main(int argc, char **argv, char **const envp) {
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_SINGLESTEP, SingleStepConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_MAXBLOCKINST, BlockSizeConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_IS64BIT_MODE, Loader.Is64BitMode());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_TSO_ENABLED, TSOEnabledConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_SMC_CHECKS, SMCChecksConfig());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ABI_LOCAL_FLAGS, ABILocalFlags());
|
||||
FEXCore::Config::SetConfig(CTX, FEXCore::Config::CONFIG_ABI_NO_PF, AbiNoPF());
|
||||
FEXCore::Context::SetCustomCPUBackendFactory(CTX, HostCPUFactory::HostCPUCreationFactory);
|
||||
|
||||
FEXCore::Context::AddGuestMemoryRegion(CTX, SHM);
|
||||
|
||||
Reference in new issue
Block a user