Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions FEXCore/Source/Interface/Config/Config.json.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@
"Enable expensive validation when loading code caches"
]
},
"JITFeatures": {
"Type": "strenum",
"Default": "FEXCore::Config::JITFeatures::OFF",
"AffectsCodeGen": "true",
"Enums": {
"ENABLEX87FIP": "enablex87fip"
},
"Desc": [
"Allows controlling JIT features in the unified location",
"\toff: Default JIT features.",
"\tenablex86fip: Turns on the x87 FIP emulation feature"
]
},
"HostFeatures": {
"Type": "strenum",
"Default": "FEXCore::Config::HostFeatures::OFF",
Expand Down
1 change: 1 addition & 0 deletions FEXCore/Source/Interface/Context/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ class ContextImpl final : public FEXCore::Context::Context, public CPU::SharedCo
FEX_CONFIG_OPT(SoftwareRNG, SOFTWARERNG);
FEX_CONFIG_OPT(StrictInProcessSplitLocks, STRICTINPROCESSSPLITLOCKS);
FEX_CONFIG_OPT(MonoHacks, MONOHACKS);
FEX_CONFIG_OPT(JITFeatures, JITFEATURES);
} Config;

bool SoftwareRNGEnabled() const {
Expand Down
5 changes: 4 additions & 1 deletion FEXCore/Source/Interface/Core/CPUID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,9 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) const {
const uint32_t SupportsWFXT = CTX->HostFeatures.SupportsWFXT;

const uint32_t SupportsRAND = CTX->HostFeatures.SupportsRAND || CTX->SoftwareRNGEnabled();
// When the X87 FIP feature is enabled, we update the state pointers on every instruction.
// We don't even update them on exception so this isn't quite true the other way anyway.
const uint32_t X87DataPtrExcept = (CTX->Config.JITFeatures & FEXCore::Config::JITFeatures::ENABLEX87FIP) == 0;

// Number of subfunctions
// TODO: For now, subfunction 1 only exposes AVX-VNNI so we make it conditional
Expand All @@ -708,7 +711,7 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_07h(uint32_t Leaf) const {
(SupportsAVX() << 3) | // BMI1
(0 << 4) | // Intel Hardware Lock Elison
(SupportsAVX() << 5) | // AVX2 support
(1 << 6) | // FPU data pointer updated only on exception
(X87DataPtrExcept << 6) | // FPU data pointer updated only on exception
(1 << 7) | // SMEP support
(SupportsAVX() << 8) | // BMI2
(SupportsEnhancedREPMOVS << 9) | // Enhanced REP MOVSB/STOSB
Expand Down
1 change: 1 addition & 0 deletions FEXCore/Source/Interface/Core/CPUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class CPUIDEmu final {
bool Hybrid {};
uint32_t Cores {};
FEX_CONFIG_OPT(HideHypervisorBit, HIDEHYPERVISORBIT);
FEX_CONFIG_OPT(JITFeatures, JITFEATURES);

// XFEATURE_ENABLED_MASK
// Mask that configures what features are enabled on the CPU.
Expand Down
7 changes: 7 additions & 0 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,7 @@ class OpDispatchBuilder final : public IREmitter {
void X87LDENV(OpcodeArgs);
void X87ModifySTP(OpcodeArgs, bool Inc);
void X87OpHelper(OpcodeArgs, FEXCore::IR::IROps IROp, bool ZeroC2);
void X87NOP(OpcodeArgs);

enum class FCOMIFlags {
FLAGS_X87,
Expand Down Expand Up @@ -2497,6 +2498,12 @@ class OpDispatchBuilder final : public IREmitter {
void SetX87FTW(Ref FTW);
Ref GetX87FTW_Helper();
void SetX87Top(Ref Value);
void StoreX87FIP(FEXCore::X86Tables::DecodedOp Op) {
if (CTX->Config.JITFeatures & FEXCore::Config::JITFeatures::ENABLEX87FIP) {
// Only store FIP if the feature is enabled.
_StoreContextGPR(OpSize::i64Bit, GetRelocatedPC(Op, -Op->InstSize), offsetof(FEXCore::Core::CPUState, FIP));
}
}

void ChgStateX87_MMX() override {
LOGMAN_THROW_A_FMT(MMXState == MMXState_X87, "Expected state to be x87");
Expand Down
32 changes: 32 additions & 0 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,30 +67,35 @@ void OpDispatchBuilder::FLD(OpcodeArgs, IR::OpSize Width) {
ConvertedData = _F80CVTTo(Data, Width);
}
_PushStack(ConvertedData, Data, Width);
StoreX87FIP(Op);
}

// Float LoaD operation with memory operand
void OpDispatchBuilder::FLDFromStack(OpcodeArgs) {
_CopyPushStack(Op->OP & 7);
StoreX87FIP(Op);
}

void OpDispatchBuilder::FBLD(OpcodeArgs) {
// Read from memory
Ref Data = LoadSourceFPR_WithOpSize(Op, Op->Src[0], OpSize::f80Bit, Op->Flags);
Ref ConvertedData = _F80BCDLoad(Data);
_PushStack(ConvertedData, Invalid(), OpSize::iInvalid);
StoreX87FIP(Op);
}

void OpDispatchBuilder::FBSTP(OpcodeArgs) {
Ref converted = _F80BCDStore(_ReadStackValue(0));
StoreResultFPR_WithOpSize(Op, Op->Dest, converted, OpSize::f80Bit, OpSize::i8Bit);
_PopStackDestroy();
StoreX87FIP(Op);
}

void OpDispatchBuilder::FLD_Const(OpcodeArgs, NamedVectorConstant K) {
// Update TOP
Ref Data = LoadAndCacheNamedVectorConstant(OpSize::i128Bit, K);
_PushStack(Data, Data, OpSize::f80Bit);
StoreX87FIP(Op);
}

void OpDispatchBuilder::FILD(OpcodeArgs) {
Expand Down Expand Up @@ -122,6 +127,7 @@ void OpDispatchBuilder::FILD(OpcodeArgs) {

Ref ConvertedData = _VLoadTwoGPRs(shifted, upper);
_PushStack(ConvertedData, Invalid(), OpSize::iInvalid);
StoreX87FIP(Op);
}

void OpDispatchBuilder::FST(OpcodeArgs, IR::OpSize Width) {
Expand All @@ -135,6 +141,7 @@ void OpDispatchBuilder::FST(OpcodeArgs, IR::OpSize Width) {
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::FSTToStack(OpcodeArgs) {
Expand All @@ -144,6 +151,7 @@ void OpDispatchBuilder::FSTToStack(OpcodeArgs) {
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

// Store integer to memory (possibly with truncation)
Expand Down Expand Up @@ -183,6 +191,7 @@ void OpDispatchBuilder::FIST(OpcodeArgs, bool Truncate) {
if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::FADD(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispatchBuilder::OpResult ResInST0) {
Expand All @@ -197,6 +206,7 @@ void OpDispatchBuilder::FADD(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispa
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
return;
}

Expand All @@ -213,6 +223,7 @@ void OpDispatchBuilder::FADD(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispa

// top of stack is at offset zero
_F80AddValue(0, Arg);
StoreX87FIP(Op);
}

void OpDispatchBuilder::FMUL(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispatchBuilder::OpResult ResInST0) {
Expand All @@ -227,6 +238,7 @@ void OpDispatchBuilder::FMUL(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispa
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
return;
}

Expand All @@ -247,6 +259,7 @@ void OpDispatchBuilder::FMUL(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispa
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::FDIV(OpcodeArgs, IR::OpSize Width, bool Integer, bool Reverse, OpDispatchBuilder::OpResult ResInST0) {
Expand All @@ -264,6 +277,7 @@ void OpDispatchBuilder::FDIV(OpcodeArgs, IR::OpSize Width, bool Integer, bool Re
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
return;
}

Expand All @@ -288,6 +302,7 @@ void OpDispatchBuilder::FDIV(OpcodeArgs, IR::OpSize Width, bool Integer, bool Re
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::FSUB(OpcodeArgs, IR::OpSize Width, bool Integer, bool Reverse, OpDispatchBuilder::OpResult ResInST0) {
Expand All @@ -305,6 +320,7 @@ void OpDispatchBuilder::FSUB(OpcodeArgs, IR::OpSize Width, bool Integer, bool Re
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
return;
}

Expand All @@ -329,6 +345,7 @@ void OpDispatchBuilder::FSUB(OpcodeArgs, IR::OpSize Width, bool Integer, bool Re
if (Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

Ref OpDispatchBuilder::GetX87FTW_Helper() {
Expand Down Expand Up @@ -627,6 +644,7 @@ void OpDispatchBuilder::FXCH(OpcodeArgs) {
_F80StackXchange(Offset);
}
SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(Constant(0));
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87FYL2X(OpcodeArgs, bool IsFYL2XP1) {
Expand All @@ -635,6 +653,7 @@ void OpDispatchBuilder::X87FYL2X(OpcodeArgs, bool IsFYL2XP1) {
} else {
_F80FYL2XStack();
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::FCOMI(OpcodeArgs, IR::OpSize Width, bool Integer, OpDispatchBuilder::FCOMIFlags WhichFlags, bool PopTwice) {
Expand Down Expand Up @@ -699,6 +718,7 @@ void OpDispatchBuilder::FCOMI(OpcodeArgs, IR::OpSize Width, bool Integer, OpDisp
} else if ((Op->TableInfo->Flags & X86Tables::InstFlags::FLAGS_POP) != 0) {
_PopStackDestroy();
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::FTST(OpcodeArgs) {
Expand All @@ -718,13 +738,15 @@ void OpDispatchBuilder::FTST(OpcodeArgs) {
// Set Invalid Operation flag when unordered (NaN comparison)
// The x87 exception flags are sticky. Preserve earlier result
SetRFLAG<FEXCore::X86State::X87FLAG_IE_LOC>(_Or(OpSize::i32Bit, GetRFLAG(FEXCore::X86State::X87FLAG_IE_LOC), HostFlag_Unordered));
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87OpHelper(OpcodeArgs, FEXCore::IR::IROps IROp, bool ZeroC2) {
DeriveOp(Result, IROp, _F80SCALEStack());
if (ZeroC2) {
SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(Constant(0));
}
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87ModifySTP(OpcodeArgs, bool Inc) {
Expand All @@ -736,6 +758,7 @@ void OpDispatchBuilder::X87ModifySTP(OpcodeArgs, bool Inc) {

// C1 set to 0
SetRFLAG<FEXCore::X86State::X87FLAG_C1_LOC>(Constant(0));
StoreX87FIP(Op);
}

// Operations dealing with loading and storing environment pieces
Expand Down Expand Up @@ -824,11 +847,13 @@ void OpDispatchBuilder::FNINIT(OpcodeArgs) {

void OpDispatchBuilder::X87FFREE(OpcodeArgs) {
_InvalidateStack(Op->OP & 7);
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87EMMS(OpcodeArgs) {
// Tags all get set to 0b11
_InvalidateStack(0xff);
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87FCMOV(OpcodeArgs) {
Expand Down Expand Up @@ -867,6 +892,7 @@ void OpDispatchBuilder::X87FCMOV(OpcodeArgs) {

Ref VecCond = _VDupFromGPR(OpSize::i128Bit, OpSize::i64Bit, SelectCC0All1(CC));
_F80VBSLStack(OpSize::i128Bit, VecCond, Op->OP & 7, 0);
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87FXAM(OpcodeArgs) {
Expand Down Expand Up @@ -971,6 +997,7 @@ void OpDispatchBuilder::X87FXAM(OpcodeArgs) {
SetRFLAG<FEXCore::X86State::X87FLAG_C0_LOC>(C0);
SetRFLAG<FEXCore::X86State::X87FLAG_C2_LOC>(C2);
SetRFLAG<FEXCore::X86State::X87FLAG_C3_LOC>(C3);
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87FXTRACT(OpcodeArgs) {
Expand All @@ -981,6 +1008,11 @@ void OpDispatchBuilder::X87FXTRACT(OpcodeArgs) {
auto Sig = _F80XTRACT_SIG(Top);
_PushStack(Exp, Invalid(), OpSize::iInvalid);
_PushStack(Sig, Invalid(), OpSize::iInvalid);
StoreX87FIP(Op);
}

void OpDispatchBuilder::X87NOP(OpcodeArgs) {
StoreX87FIP(Op);
}

} // namespace FEXCore::IR
Loading
Loading