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 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." + ] } } } 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/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); } 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); 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/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); 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() 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": { 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": {