From b6b5e93dbb5a9d3c2069d7eb661ec823c1ccf306 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:27:57 -0700 Subject: [PATCH 1/8] Config: Adds an option to disable vixl sim indirect runtime calls --- FEXCore/Source/Interface/Config/Config.json.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/FEXCore/Source/Interface/Config/Config.json.in b/FEXCore/Source/Interface/Config/Config.json.in index ed9412791..72df8b549 100644 --- a/FEXCore/Source/Interface/Config/Config.json.in +++ b/FEXCore/Source/Interface/Config/Config.json.in @@ -499,6 +499,15 @@ "IS64BIT_MODE": { "Type": "bool", "Default": "false" + }, + "DISABLE_VIXL_INDIRECT_RUNTIME_CALLS": { + "Type": "bool", + "Default": "true", + "Desc": [ + "This option is used for the InstructionCountCI so it can generate the same codegen between Arm64 hosts and vixl simulator hosts.", + "Vixl simulator indirect runtime calls are a special hlt instruction with metadata after it. Effectively making a custom call instruction.", + "With visual simulator calls disabled, the code generation would be the same as on a native Arm64 host, but running the code is broken." + ] } } } From 11db8e75062b08bdb804a3d7e1745ee813e6ecbe Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:29:44 -0700 Subject: [PATCH 2/8] FEXCore: Wire up the new option to disable vixl indirect runtimes Also so it compiles without the vixl simulator enabled. --- FEXCore/Source/Interface/Context/Context.h | 1 + .../Interface/Core/ArchHelpers/Arm64Emitter.h | 10 +- .../Interface/Core/Dispatcher/Dispatcher.cpp | 77 ++++---- .../Interface/Core/JIT/Arm64/BranchOps.cpp | 55 +++--- .../Source/Interface/Core/JIT/Arm64/JIT.cpp | 165 ++++++++++-------- .../Interface/Core/JIT/Arm64/MiscOps.cpp | 17 +- 6 files changed, 184 insertions(+), 141 deletions(-) diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index d9309cdfa..b15e2d27f 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -241,6 +241,7 @@ namespace FEXCore::Context { FEX_CONFIG_OPT(CacheObjectCodeCompilation, CACHEOBJECTCODECOMPILATION); FEX_CONFIG_OPT(x87ReducedPrecision, X87REDUCEDPRECISION); FEX_CONFIG_OPT(DisableTelemetry, DISABLETELEMETRY); + FEX_CONFIG_OPT(DisableVixlIndirectCalls, DISABLE_VIXL_INDIRECT_RUNTIME_CALLS); } Config; FEXCore::HostFeatures HostFeatures; diff --git a/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.h b/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.h index adec639b7..13a3701c7 100644 --- a/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.h +++ b/FEXCore/Source/Interface/Core/ArchHelpers/Arm64Emitter.h @@ -213,7 +213,15 @@ protected: // Call type dc32(vixl::aarch64::kCallRuntime); } - +#else + template + void GenerateRuntimeCall(R (*Function)(P...)) { + // Explicitly doing nothing. + } + template + void GenerateIndirectRuntimeCall(ARMEmitter::Register Reg) { + // Explicitly doing nothing. + } #endif #ifdef VIXL_SIMULATOR diff --git a/FEXCore/Source/Interface/Core/Dispatcher/Dispatcher.cpp b/FEXCore/Source/Interface/Core/Dispatcher/Dispatcher.cpp index 4d8f16227..2df54948e 100644 --- a/FEXCore/Source/Interface/Core/Dispatcher/Dispatcher.cpp +++ b/FEXCore/Source/Interface/Core/Dispatcher/Dispatcher.cpp @@ -214,11 +214,12 @@ void Dispatcher::EmitDispatcher() { mov(ARMEmitter::XReg::x1, ARMEmitter::XReg::lr); ldr(ARMEmitter::XReg::x2, STATE_PTR(CpuStateFrame, Pointers.Common.ExitFunctionLink)); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); -#else - blr(ARMEmitter::Reg::r2); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); + } + else { + blr(ARMEmitter::Reg::r2); + } if (config.StaticRegisterAllocation) FillStaticRegs(); @@ -250,11 +251,12 @@ void Dispatcher::EmitDispatcher() { ldr(ARMEmitter::XReg::x3, &l_CompileBlock); // X2 contains our guest RIP -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); // { CTX, Frame, RIP} -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); // { CTX, Frame, RIP} + } if (config.StaticRegisterAllocation) FillStaticRegs(); @@ -345,11 +347,12 @@ void Dispatcher::EmitDispatcher() { ldr(ARMEmitter::XReg::x0, &l_CTX); mov(ARMEmitter::XReg::x1, STATE); ldr(ARMEmitter::XReg::x2, &l_Sleep); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); -#else - blr(ARMEmitter::Reg::r2); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); + } + else { + blr(ARMEmitter::Reg::r2); + } PauseReturnInstruction = GetCursorAddress(); // Fault to start running again @@ -415,11 +418,12 @@ void Dispatcher::EmitDispatcher() { SpillStaticRegs(ARMEmitter::Reg::r3); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.AArch64.LUDIV)); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillStaticRegs(); // Result is now in x0 @@ -437,11 +441,12 @@ void Dispatcher::EmitDispatcher() { SpillStaticRegs(ARMEmitter::Reg::r3); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.AArch64.LDIV)); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillStaticRegs(); // Result is now in x0 @@ -459,11 +464,12 @@ void Dispatcher::EmitDispatcher() { SpillStaticRegs(ARMEmitter::Reg::r3); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.AArch64.LUREM)); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillStaticRegs(); // Result is now in x0 @@ -482,11 +488,12 @@ void Dispatcher::EmitDispatcher() { ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.AArch64.LREM)); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillStaticRegs(); // Result is now in x0 diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/BranchOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/BranchOps.cpp index 0508fef40..119e97df7 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/BranchOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/BranchOps.cpp @@ -210,11 +210,12 @@ DEF_OP(Syscall) { // SP supporting move add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r2, ARMEmitter::Reg::rsp, 0); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, SPOffset); @@ -349,11 +350,12 @@ DEF_OP(Thunk) { auto thunkFn = static_cast(ThreadState->CTX)->ThunkHandler->LookupThunk(Op->ThunkNameHash); LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r2, (uintptr_t)thunkFn); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); -#else - blr(ARMEmitter::Reg::r2); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); + } + else { + blr(ARMEmitter::Reg::r2); + } PopDynamicRegsAndLR(); @@ -422,11 +424,12 @@ DEF_OP(ThreadRemoveCodeEntry) { LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r1, Entry); ldr(ARMEmitter::XReg::x2, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.ThreadRemoveCodeEntryFromJIT)); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); -#else - blr(ARMEmitter::Reg::r2); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); + } + else { + blr(ARMEmitter::Reg::r2); + } FillStaticRegs(); // Fix the stack and any values that were stepped on @@ -446,11 +449,12 @@ DEF_OP(CPUID) { ldr(ARMEmitter::XReg::x3, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.CPUIDFunction)); mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r1, GetReg(Op->Function.ID())); mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r2, GetReg(Op->Leaf.ID())); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall<__uint128_t, void*, uint64_t, uint64_t>(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall<__uint128_t, void*, uint64_t, uint64_t>(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillStaticRegs(); @@ -474,11 +478,12 @@ DEF_OP(XGETBV) { ldr(ARMEmitter::XReg::x0, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.CPUIDObj)); ldr(ARMEmitter::XReg::x2, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.XCRFunction)); mov(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r1, GetReg(Op->Function.ID())); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); -#else - blr(ARMEmitter::Reg::r2); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r2); + } + else { + blr(ARMEmitter::Reg::r2); + } FillStaticRegs(); diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp index efa934668..9b2fb6f6d 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/JIT.cpp @@ -91,11 +91,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { fmov(ARMEmitter::SReg::s0, Src1.S()); ldrh(ARMEmitter::WReg::w0, STATE, offsetof(FEXCore::Core::CPUState, FCW)); ldr(ARMEmitter::XReg::x1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall<__uint128_t, uint16_t, float>(ARMEmitter::Reg::r1); -#else - blr(ARMEmitter::Reg::r1); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall<__uint128_t, uint16_t, float>(ARMEmitter::Reg::r1); + } + else { + blr(ARMEmitter::Reg::r1); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -113,11 +114,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { mov(ARMEmitter::DReg::d0, Src1.D()); ldrh(ARMEmitter::WReg::w0, STATE, offsetof(FEXCore::Core::CPUState, FCW)); ldr(ARMEmitter::XReg::x1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall<__uint128_t, uint16_t, double>(ARMEmitter::Reg::r1); -#else - blr(ARMEmitter::Reg::r1); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall<__uint128_t, uint16_t, double>(ARMEmitter::Reg::r1); + } + else { + blr(ARMEmitter::Reg::r1); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -141,11 +143,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { mov(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r1, Src1); } ldr(ARMEmitter::XReg::x2, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall<__uint128_t, uint16_t, uint32_t>(ARMEmitter::Reg::r2); -#else - blr(ARMEmitter::Reg::r2); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall<__uint128_t, uint16_t, uint32_t>(ARMEmitter::Reg::r2); + } + else { + blr(ARMEmitter::Reg::r2); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -166,11 +169,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r2, Src1, 4); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -189,11 +193,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r2, Src1, 4); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -210,11 +215,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { mov(ARMEmitter::DReg::d0, Src1.D()); ldrh(ARMEmitter::WReg::w0, STATE, offsetof(FEXCore::Core::CPUState, FCW)); ldr(ARMEmitter::XReg::x1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r1); -#else - blr(ARMEmitter::Reg::r1); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r1); + } + else { + blr(ARMEmitter::Reg::r1); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -233,11 +239,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { mov(ARMEmitter::DReg::d1, Src2.D()); ldrh(ARMEmitter::WReg::w0, STATE, offsetof(FEXCore::Core::CPUState, FCW)); ldr(ARMEmitter::XReg::x1, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r1); -#else - blr(ARMEmitter::Reg::r1); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r1); + } + else { + blr(ARMEmitter::Reg::r1); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -256,11 +263,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r2, Src1, 4); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -278,11 +286,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r2, Src1, 4); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -300,11 +309,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r2, Src1, 4); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillForABICall(Info.SupportsPreserveAllABI, true); const auto Dst = GetReg(Node); @@ -325,11 +335,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r4, Src2, 4); ldr(ARMEmitter::XReg::x5, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r5); -#else - blr(ARMEmitter::Reg::r5); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r5); + } + else { + blr(ARMEmitter::Reg::r5); + } FillForABICall(Info.SupportsPreserveAllABI, true); const auto Dst = GetReg(Node); @@ -346,11 +357,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r2, Src1, 4); ldr(ARMEmitter::XReg::x3, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall<__uint128_t, uint16_t, uint64_t, uint64_t>(ARMEmitter::Reg::r3); -#else - blr(ARMEmitter::Reg::r3); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall<__uint128_t, uint16_t, uint64_t, uint64_t>(ARMEmitter::Reg::r3); + } + else { + blr(ARMEmitter::Reg::r3); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -374,11 +386,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { umov(ARMEmitter::Reg::r4, Src2, 4); ldr(ARMEmitter::XReg::x5, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall<__uint128_t, uint16_t, uint64_t, uint64_t, uint64_t, uint64_t>(ARMEmitter::Reg::r5); -#else - blr(ARMEmitter::Reg::r5); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall<__uint128_t, uint16_t, uint64_t, uint64_t, uint64_t, uint64_t>(ARMEmitter::Reg::r5); + } + else { + blr(ARMEmitter::Reg::r5); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -411,11 +424,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { movz(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r6, Control); ldr(ARMEmitter::XReg::x7, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r7); -#else - blr(ARMEmitter::Reg::r7); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r7); + } + else { + blr(ARMEmitter::Reg::r7); + } FillForABICall(Info.SupportsPreserveAllABI, true); @@ -441,11 +455,12 @@ void Arm64JITCore::Op_Unhandled(IR::IROp_Header const *IROp, IR::NodeID Node) { movz(ARMEmitter::Size::i32Bit, ARMEmitter::Reg::r4, Control); ldr(ARMEmitter::XReg::x5, STATE_PTR(CpuStateFrame, Pointers.Common.FallbackHandlerPointers[Info.HandlerIndex])); -#ifdef VIXL_SIMULATOR - GenerateIndirectRuntimeCall(ARMEmitter::Reg::r5); -#else - blr(ARMEmitter::Reg::r5); -#endif + if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] { + GenerateIndirectRuntimeCall(ARMEmitter::Reg::r5); + } + else { + blr(ARMEmitter::Reg::r5); + } FillForABICall(Info.SupportsPreserveAllABI, true); diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp index c382776d3..a784c60f2 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/MiscOps.cpp @@ -9,6 +9,7 @@ $end_info$ #include #endif +#include "Interface/Context/Context.h" #include "Interface/Core/ArchHelpers/CodeEmitter/Emitter.h" #include "Interface/Core/JIT/Arm64/JITClass.h" #include "FEXCore/Debug/InternalThreadState.h" @@ -113,10 +114,10 @@ DEF_OP(SetRoundingMode) { mrs(TMP1, ARMEmitter::SystemRegister::FPCR); // vixl simulator doesn't support anything beyond ties-to-even rounding -#ifndef VIXL_SIMULATOR - // Insert the rounding flags - bfi(ARMEmitter::Size::i64Bit, TMP1, TMP2, 22, 2); -#endif + if (CTX->Config.DisableVixlIndirectCalls) [[likely]] { + // Insert the rounding flags + bfi(ARMEmitter::Size::i64Bit, TMP1, TMP2, 22, 2); + } // Insert the FTZ flag lsr(ARMEmitter::Size::i64Bit, TMP2, Src, 2); @@ -170,7 +171,13 @@ DEF_OP(ProcessorID) { sub(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, 16); // Load the getcpu syscall number - LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r8, SYS_getcpu); +#if defined(_M_X86_64) + // Just to ensure the syscall number doesn't change if compiled for an x86_64 host. + constexpr auto GetCPUSyscallNum = 0xa8; +#else + constexpr auto GetCPUSyscallNum = SYS_getcpu; +#endif + LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r8, GetCPUSyscallNum); // CPU pointer in x0 add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r0, ARMEmitter::Reg::rsp, 0); From 6964e65660900d7a77b77b0e0cd98cd494b1d0e9 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:30:23 -0700 Subject: [PATCH 3/8] HostFeatures: Hardcode icache and dcache line size on x86 64-byte is effectively part of x86's ABI anyway. No need to query it for our uses. --- FEXCore/Source/Interface/Core/HostFeatures.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/FEXCore/Source/Interface/Core/HostFeatures.cpp b/FEXCore/Source/Interface/Core/HostFeatures.cpp index db25fcc42..d1ff9e8dc 100644 --- a/FEXCore/Source/Interface/Core/HostFeatures.cpp +++ b/FEXCore/Source/Interface/Core/HostFeatures.cpp @@ -303,7 +303,12 @@ HostFeatures::HostFeatures() { } #endif -#if defined(_M_X86_64) && !defined(VIXL_SIMULATOR) +#if defined(_M_X86_64) + // Hardcoded cacheline size. + DCacheLineSize = 64U; + ICacheLineSize = 64U; + +#if !defined(VIXL_SIMULATOR) Xbyak::util::Cpu X86Features{}; SupportsAES = X86Features.has(Xbyak::util::Cpu::tAESNI); SupportsCRC = X86Features.has(Xbyak::util::Cpu::tSSE42); @@ -333,6 +338,7 @@ HostFeatures::HostFeatures() { SupportsFlushInputsToZero = true; SupportsFloatExceptions = true; +#endif #endif OverrideFeatures(this); } From 9933ef07ea770e48c5985bc85611bcac683642bb Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:31:12 -0700 Subject: [PATCH 4/8] Tools: Enable indirect vixl runtime calls if simulator is used So tests can still run. --- Source/Tools/FEXLoader/CMakeLists.txt | 11 +++++++++++ Source/Tools/FEXLoader/FEXLoader.cpp | 4 ++++ Source/Tools/FEXLoader/IRLoader.cpp | 4 ++++ Source/Tools/FEXLoader/TestHarnessRunner.cpp | 4 ++++ 4 files changed, 23 insertions(+) diff --git a/Source/Tools/FEXLoader/CMakeLists.txt b/Source/Tools/FEXLoader/CMakeLists.txt index 6ad1763a7..9fc8c8d26 100644 --- a/Source/Tools/FEXLoader/CMakeLists.txt +++ b/Source/Tools/FEXLoader/CMakeLists.txt @@ -1,5 +1,10 @@ list(APPEND LIBS FEXCore Common) +set (DEFINES) +if (ENABLE_VIXL_SIMULATOR) + list(APPEND DEFINES -DVIXL_SIMULATOR=1) +endif() + if (NOT MINGW_BUILD) add_subdirectory(LinuxSyscalls) @@ -14,6 +19,8 @@ if (NOT MINGW_BUILD) VDSO_Emulation.cpp AOT/AOTGenerator.cpp) + target_compile_definitions(${NAME} PRIVATE ${DEFINES}) + # Enable FEX APIs to be used by targets that use target_link_libraries on FEXLoader set_target_properties(${NAME} PROPERTIES ENABLE_EXPORTS 1) @@ -161,6 +168,8 @@ if (BUILD_TESTS) endif() add_executable(TestHarnessRunner ${SRCS}) + target_compile_definitions(TestHarnessRunner PRIVATE ${DEFINES}) + target_include_directories(TestHarnessRunner PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Source/ @@ -176,6 +185,8 @@ if (BUILD_TESTS) add_executable(IRLoader IRLoader.cpp ) + target_compile_definitions(IRLoader PRIVATE ${DEFINES}) + target_include_directories(IRLoader PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Source/ diff --git a/Source/Tools/FEXLoader/FEXLoader.cpp b/Source/Tools/FEXLoader/FEXLoader.cpp index 685bdaa95..66ea6a811 100644 --- a/Source/Tools/FEXLoader/FEXLoader.cpp +++ b/Source/Tools/FEXLoader/FEXLoader.cpp @@ -279,6 +279,10 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Config::ReloadMetaLayer(); FEXCore::Config::Set(FEXCore::Config::CONFIG_IS_INTERPRETER, IsInterpreter ? "1" : "0"); FEXCore::Config::Set(FEXCore::Config::CONFIG_INTERPRETER_INSTALLED, IsInterpreterInstalled() ? "1" : "0"); +#ifdef VIXL_SIMULATOR + // If running under the vixl simulator, ensure that indirect runtime calls are enabled. + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_DISABLE_VIXL_INDIRECT_RUNTIME_CALLS, "0"); +#endif // Early check for process stall // Doesn't use CONFIG_ROOTFS and we don't want it to spin up a squashfs instance diff --git a/Source/Tools/FEXLoader/IRLoader.cpp b/Source/Tools/FEXLoader/IRLoader.cpp index f4e7b99ea..81cd9a026 100644 --- a/Source/Tools/FEXLoader/IRLoader.cpp +++ b/Source/Tools/FEXLoader/IRLoader.cpp @@ -148,6 +148,10 @@ int main(int argc, char **argv, char **const envp) // This is to ensure that static register allocation in the JIT // is configured correctly for accesses to the top 8 GPRs and 8 XMM registers. FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_IS64BIT_MODE, "1"); +#ifdef VIXL_SIMULATOR + // If running under the vixl simulator, ensure that indirect runtime calls are enabled. + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_DISABLE_VIXL_INDIRECT_RUNTIME_CALLS, "0"); +#endif auto Args = FEX::ArgLoader::Get(); auto ParsedArgs = FEX::ArgLoader::GetParsedArgs(); diff --git a/Source/Tools/FEXLoader/TestHarnessRunner.cpp b/Source/Tools/FEXLoader/TestHarnessRunner.cpp index 7efdc6a68..86aa628ac 100644 --- a/Source/Tools/FEXLoader/TestHarnessRunner.cpp +++ b/Source/Tools/FEXLoader/TestHarnessRunner.cpp @@ -211,6 +211,10 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Config::ReloadMetaLayer(); FEXCore::Config::Set(FEXCore::Config::CONFIG_IS64BIT_MODE, Loader.Is64BitMode() ? "1" : "0"); +#ifdef VIXL_SIMULATOR + // If running under the vixl simulator, ensure that indirect runtime calls are enabled. + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_DISABLE_VIXL_INDIRECT_RUNTIME_CALLS, "0"); +#endif FEX_CONFIG_OPT(Core, CORE); From d5a4d9b17ff60d8c90c304414e5bbd427d35ddb4 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:32:44 -0700 Subject: [PATCH 5/8] InstCountCI: Adds option to disable cssc for tests One x87 instruction was using CSSC abs --- Scripts/InstructionCountParser.py | 3 +++ Source/Tools/CodeSizeValidation/Main.cpp | 9 +++++++++ unittests/InstructionCountCI/x87.json | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Scripts/InstructionCountParser.py b/Scripts/InstructionCountParser.py index 15b3063e0..d171c1f51 100755 --- a/Scripts/InstructionCountParser.py +++ b/Scripts/InstructionCountParser.py @@ -47,6 +47,8 @@ class HostFeatures(Flag) : FEATURE_CLZERO = (1 << 2) FEATURE_RNG = (1 << 3) FEATURE_FCMA = (1 << 4) + FEATURE_CSSC = (1 << 5) + HostFeaturesLookup = { "SVE128" : HostFeatures.FEATURE_SVE128, @@ -54,6 +56,7 @@ HostFeaturesLookup = { "CLZERO" : HostFeatures.FEATURE_CLZERO, "RNG" : HostFeatures.FEATURE_RNG, "FCMA" : HostFeatures.FEATURE_FCMA, + "CSSC" : HostFeatures.FEATURE_CSSC, } def GetHostFeatures(data): diff --git a/Source/Tools/CodeSizeValidation/Main.cpp b/Source/Tools/CodeSizeValidation/Main.cpp index 8f1ee7fd9..cc337ff1d 100644 --- a/Source/Tools/CodeSizeValidation/Main.cpp +++ b/Source/Tools/CodeSizeValidation/Main.cpp @@ -451,6 +451,8 @@ int main(int argc, char **argv, char **const envp) { FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_IS64BIT_MODE, TestHeaderData->Bitness == 64 ? "1" : "0"); // Disable telemetry, it can affect instruction counts. FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_DISABLETELEMETRY, "1"); + // Disable vixl simulator indirect calls as it can affect instruction counts. + FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_DISABLE_VIXL_INDIRECT_RUNTIME_CALLS, "1"); // Host feature override. Only supports overriding SVE width. enum HostFeatures { @@ -459,6 +461,7 @@ int main(int argc, char **argv, char **const envp) { FEATURE_CLZERO = (1U << 2), FEATURE_RNG = (1U << 3), FEATURE_FCMA = (1U << 4), + FEATURE_CSSC = (1U << 5), }; uint64_t SVEWidth = 0; @@ -480,6 +483,9 @@ int main(int argc, char **argv, char **const envp) { if (TestHeaderData->EnabledHostFeatures & FEATURE_FCMA) { HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::ENABLEFCMA); } + if (TestHeaderData->EnabledHostFeatures & FEATURE_CSSC) { + HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::ENABLECSSC); + } // Always enable ARMv8.1 LSE atomics. HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::ENABLEATOMICS); @@ -499,6 +505,9 @@ int main(int argc, char **argv, char **const envp) { if (TestHeaderData->DisabledHostFeatures & FEATURE_FCMA) { HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::DISABLEFCMA); } + if (TestHeaderData->DisabledHostFeatures & FEATURE_CSSC) { + HostFeatureControl |= static_cast(FEXCore::Config::HostFeatures::DISABLECSSC); + } FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_HOSTFEATURES, fextl::fmt::format("{}", HostFeatureControl)); FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_FORCESVEWIDTH, fextl::fmt::format("{}", SVEWidth)); diff --git a/unittests/InstructionCountCI/x87.json b/unittests/InstructionCountCI/x87.json index a66f402ac..61879171a 100644 --- a/unittests/InstructionCountCI/x87.json +++ b/unittests/InstructionCountCI/x87.json @@ -4,7 +4,8 @@ "EnabledHostFeatures": [], "DisabledHostFeatures": [ "SVE128", - "SVE256" + "SVE256", + "CSSC" ] }, "Instructions": { From 978489fce1f2cee710de8f8952e6271108a80bef Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:33:13 -0700 Subject: [PATCH 6/8] InstCountCI: Explicitly disable SVE256 for one test group These instructions are specifically testing the SVE128 implementations, don't want SVE256 mucking up the instructions. --- unittests/InstructionCountCI/Secondary_OpSize_SVE128.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unittests/InstructionCountCI/Secondary_OpSize_SVE128.json b/unittests/InstructionCountCI/Secondary_OpSize_SVE128.json index fe05ed8d4..a81ac51a8 100644 --- a/unittests/InstructionCountCI/Secondary_OpSize_SVE128.json +++ b/unittests/InstructionCountCI/Secondary_OpSize_SVE128.json @@ -4,7 +4,9 @@ "EnabledHostFeatures": [ "SVE128" ], - "DisabledHostFeatures": [] + "DisabledHostFeatures": [ + "SVE256" + ] }, "Instructions": { "psrlw xmm0, xmm1": { From df369bd6a045efa709e95bea378687d2f719d112 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:33:56 -0700 Subject: [PATCH 7/8] InstCountCI: Enable running on x86 hosts This is a quality of life improvement for people that want to tinker with the InstCountCI but they may not necessarily have an Arm64 device available immediately for poking. As long as the vixl disassembler is enabled then the InstCountCI tests can run and get bit-accurate encodings just like on an Arm64 device. This also ensures that behaviour is consistent with or without the vixl simulator enabled which is very important when running on x86 hosts. --- unittests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index a8f040a46..9939c468d 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -19,7 +19,7 @@ endif() add_subdirectory(ASM/) add_subdirectory(32Bit_ASM/) -if (ENABLE_VIXL_DISASSEMBLER AND (ENABLE_JIT_ARM64 OR CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64|^arm64|^armv8\.*")) +if (ENABLE_VIXL_DISASSEMBLER) # Tests are only valid to run if the vixl disassembler is enabled and the active JIT is the ARM64 JIT. add_subdirectory(InstructionCountCI/) endif() From 5925eef213a154c60c6c8803594a89dcc245523a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 30 Sep 2023 08:39:45 -0700 Subject: [PATCH 8/8] Github/InstCountCI: Enables x86 runner To ensure we don't break this path for developers. --- .github/workflows/instcountci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/instcountci.yml b/.github/workflows/instcountci.yml index 7abc589e0..7c6f94ec6 100644 --- a/.github/workflows/instcountci.yml +++ b/.github/workflows/instcountci.yml @@ -20,7 +20,7 @@ jobs: runs-on: ${{ matrix.arch }} strategy: matrix: - arch: [[self-hosted, ARM64]] + arch: [[self-hosted, x64], [self-hosted, ARM64]] fail-fast: false steps: @@ -64,7 +64,7 @@ jobs: # Note the current convention is to use the -S and -B options here to specify source # and build directories, but this is only available with CMake 3.13 and higher. # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_VIXL_SIMULATOR=False -DENABLE_VIXL_DISASSEMBLER=True -DENABLE_LTO=False -DENABLE_ASSERTIONS=True + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G Ninja -DENABLE_VIXL_SIMULATOR=False -DENABLE_VIXL_DISASSEMBLER=True -DENABLE_LTO=False -DENABLE_ASSERTIONS=True -DENABLE_X86_HOST_DEBUG=True - name: Build working-directory: ${{runner.workspace}}/build