[cmake] refactor: compiler and architecture handling

- Do compiler/architecture checks EARLY, don't waste time doing random
  configuration stuff if the user can't even compile in the first place
- MSVC is unsupported, I assume? So add a check to disallow. There's
  literally no MSVC or MSC_VER checks anywhere, so...
- Rather than using the MSVC architecture definitions, use our own
  `ARCHITECTURE_arm64` et al. Hijacking existing "standard" definitions
  is a very bad idea. Also makes it more readable in CMake
- Change the x86 host check to `x86|amd64`. Some systems still refer to
  themselves as x86 despite being 64-bit for... reasons, and I saw one a
  very long time ago that referred to it as amd64. This should
  basically never come up, nor is it really relevant given that FEX is
  for arm64... but it kinda annoyed me so whatever.

TODOs:
- Should we check `CMAKE_SIZEOF_VOID_P (equal) 64`? I don't think anyone
  is even trying to compile this thing on armv7 or older, but might as
  well? maybe?
- What's the status of *BSD, Solaris, macOS? Technically macOS does
  support Wine, not sure about the others.

Signed-off-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
crueter committed 2025-12-29 14:05:09 -05:00
1 parent 900c1790d3
commit 9e8463d6d7
63 files changed
+170 -169

No files matched your search

+39 -37
View File
@@ -40,6 +40,7 @@ set(X86_64_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Data/CMake/toolchain_x86_
set(X86_DEV_ROOTFS "/" CACHE FILEPATH "Path to the sysroot used for cross-compiling for i686 and x86_64")
set(DATA_DIRECTORY "" CACHE PATH "Global data directory (override)")
set(HOSTLIBS_DATA_DIRECTORY "" CACHE PATH "Global data directory (override)")
if (NOT DATA_DIRECTORY)
set(DATA_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/fex-emu")
endif()
@@ -49,7 +50,14 @@ if (NOT HOSTLIBS_DATA_DIRECTORY)
set(HOSTLIBS_DATA_DIRECTORY "${CMAKE_INSTALL_FULL_LIBDIR}/fex-emu")
endif()
if (MINGW)
## Platform and Compiler Checks ##
# TODO: *BSD? Solaris? macOS (lol)?
# GCC and MSVC are unsupported
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message(FATAL_ERROR "FEX doesn't support GCC! Use Clang instead.")
elseif (MSVC)
message(FATAL_ERROR "FEX doesn't support MSVC! Use Clang on MinGW instead.")
elseif (MINGW)
message(STATUS "Building for MinGW")
set(ENABLE_JEMALLOC TRUE)
set(ENABLE_JEMALLOC_GLIBC_ALLOC FALSE)
@@ -61,6 +69,32 @@ else ()
endif()
endif()
## Architecture Handling ##
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86|amd64")
option(ENABLE_X86_HOST_DEBUG "Enables compiling on x86_64 host" FALSE)
if (NOT ENABLE_X86_HOST_DEBUG)
message(FATAL_ERROR
" FEX doesn't support compiling for x86-64 hosts!"
" This is /only/ a supported configuration for FEX CI and nothing else!")
else()
message(STATUS "x86_64 debug build")
endif()
set(ARCHITECTURE_x86_64 1)
add_definitions(-DARCHITECTURE_x86_64=1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcx16")
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64|^arm64|^armv8\.*")
set(ARCHITECTURE_arm64 1)
add_definitions(-DARCHITECTURE_arm64=1)
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64ec")
set(ARCHITECTURE_arm64ec 1)
add_definitions(-DARCHITECTURE_arm64ec=1)
endif()
if (BUILD_STEAM_SUPPORT)
add_definitions(-DFEX_STEAM_SUPPORT=1)
endif()
@@ -132,7 +166,6 @@ if (ENABLE_GDB_SYMBOLS)
add_definitions(-DGDB_SYMBOLS_ENABLED=1)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Bin)
@@ -142,33 +175,7 @@ cmake_policy(SET CMP0083 NEW) # Follow new PIE policy
include(CheckPIESupported)
check_pie_supported()
if (ENABLE_LTO)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
option(ENABLE_X86_HOST_DEBUG "Enables compiling on x86_64 host" FALSE)
if (NOT ENABLE_X86_HOST_DEBUG)
message(FATAL_ERROR
" FEX-Emu doesn't support compiling for x86-64 hosts!"
" This is /only/ a supported configuration for FEX CI and nothing else!")
endif()
set(_M_X86_64 1)
add_definitions(-D_M_X86_64=1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcx16")
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64|^arm64|^armv8\.*")
set(_M_ARM_64 1)
add_definitions(-D_M_ARM_64=1)
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64ec")
set(_M_ARM_64EC 1)
add_definitions(-D_M_ARM_64EC=1)
endif()
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS "-std=c++11 -Wattributes -Werror=attributes")
@@ -192,7 +199,7 @@ if (HAS_CLANG_PRESERVE_ALL)
endif()
endif ()
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
if (ARCHITECTURE_arm64 AND HAS_CLANG_PRESERVE_ALL)
add_definitions("-DFEX_PRESERVE_ALL_ATTR=__attribute__((preserve_all))" "-DFEX_HAS_PRESERVE_ALL_ATTR=1")
else()
add_definitions("-DFEX_PRESERVE_ALL_ATTR=" "-DFEX_HAS_PRESERVE_ALL_ATTR=0")
@@ -318,11 +325,6 @@ if (ENABLE_FEXCORE_PROFILER AND FEXCORE_PROFILER_BACKEND STREQUAL "TRACY")
add_subdirectory(External/tracy)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# This means we were attempted to get compiled with GCC
message(FATAL_ERROR "FEX doesn't support getting compiled with GCC!")
endif()
find_package(PkgConfig REQUIRED)
find_package(Python 3.9 REQUIRED COMPONENTS Interpreter)
@@ -413,7 +415,7 @@ if (NOT TUNE_ARCH STREQUAL "generic")
endif()
if (TUNE_CPU STREQUAL "native")
if(_M_ARM_64)
if(ARCHITECTURE_arm64)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 999999.0)
# Clang 12.0 fixed the -mcpu=native bug with mixed big.little implementers
# Clang can not currently check for native Apple M1 type in hypervisor. Currently disabled
@@ -516,7 +518,7 @@ add_subdirectory(FEXHeaderUtils/)
add_subdirectory(CodeEmitter/)
add_subdirectory(FEXCore/)
if (_M_ARM_64 AND NOT MINGW AND NOT BUILD_STEAM_SUPPORT)
if (ARCHITECTURE_arm64 AND NOT MINGW AND NOT BUILD_STEAM_SUPPORT)
# Binfmt_misc files must be installed prior to Source/ installs
add_subdirectory(Data/binfmts/)
endif()
+1 -1
View File
@@ -129,4 +129,4 @@
"variables": []
}
]
}
}
+1 -1
View File
@@ -84,7 +84,7 @@ add_library(softfloat_3e STATIC
src/s_normSubnormalF32Sig.c
src/s_f32UIToCommonNaN.c)
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
if (ARCHITECTURE_arm64 AND HAS_CLANG_PRESERVE_ALL)
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=__attribute__((preserve_all));-DFEXCORE_HAS_PRESERVE_ALL_ATTR=1")
else()
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=;-DFEXCORE_HAS_PRESERVE_ALL_ATTR=0")
+2 -2
View File
@@ -5,12 +5,12 @@ project(${PROJECT_NAME}
LANGUAGES CXX)
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
set(_M_X86_64 1)
set(ARCHITECTURE_x86_64 1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcx16")
endif()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64|^arm64|^armv8\.*")
set(_M_ARM_64 1)
set(ARCHITECTURE_arm64 1)
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+7 -7
View File
@@ -69,7 +69,7 @@ set(SRCS
Utils/Threads.cpp
Utils/Profiler.cpp)
if (_M_ARM_64)
if (ARCHITECTURE_arm64)
list(APPEND SRCS Utils/ArchHelpers/Arm64.cpp)
else()
list(APPEND SRCS Utils/ArchHelpers/Arm64_stubs.cpp)
@@ -82,19 +82,19 @@ endif()
set(DEFINES -DJIT_ARM64)
if (_M_X86_64)
list(APPEND DEFINES -D_M_X86_64=1)
if (ARCHITECTURE_x86_64)
list(APPEND DEFINES -DARCHITECTURE_x86_64=1)
endif()
if (_M_ARM_64)
list(APPEND DEFINES -D_M_ARM_64=1)
if (ARCHITECTURE_arm64)
list(APPEND DEFINES -DARCHITECTURE_arm64=1)
endif()
if (ENABLE_VIXL_DISASSEMBLER)
list(APPEND DEFINES -DVIXL_DISASSEMBLER=1)
endif()
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
if (ARCHITECTURE_arm64 AND HAS_CLANG_PRESERVE_ALL)
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=__attribute__((preserve_all));-DFEXCORE_HAS_PRESERVE_ALL_ATTR=1")
else()
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=;-DFEXCORE_HAS_PRESERVE_ALL_ATTR=0")
@@ -110,7 +110,7 @@ if (NOT MINGW)
list (APPEND LIBS dl)
else()
list (APPEND LIBS synchronization)
if (_M_ARM_64EC)
if (ARCHITECTURE_arm64ec)
list (APPEND LIBS mincore)
endif()
endif()
+2 -2
View File
@@ -19,7 +19,7 @@ extern "C" {
}
struct FEX_PACKED X80SoftFloat {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// Define this to push some operations to x87
// Only useful to see if precision loss is killing something
// #define DEBUG_X86_FLOAT
@@ -30,7 +30,7 @@ struct FEX_PACKED X80SoftFloat {
#define BIGFLOAT float128_t
#define BIGFLOATSIZE 16
#endif
#elif defined(_M_ARM_64)
#elif defined(ARCHITECTURE_arm64)
#define BIGFLOAT float128_t
#define BIGFLOATSIZE 16
#else
+3 -3
View File
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
#pragma once
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#include <xmmintrin.h>
#include <immintrin.h>
#else
@@ -13,7 +13,7 @@ struct VectorScalarF64Pair {
double val[2];
};
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// Can't use uint8x16_t directly from arm_neon.h here.
// Overrides softfloat-3e's defines which causes problems.
using VectorRegType = __attribute__((neon_vector_type(16))) uint8_t;
@@ -25,7 +25,7 @@ static inline VectorRegPairType MakeVectorRegPair(VectorRegType low, VectorRegTy
return VectorRegPairType {low, high};
}
#elif defined(_M_X86_64)
#elif defined(ARCHITECTURE_x86_64)
using VectorRegType = __m128i;
using VectorRegPairType = __m256i;
@@ -41,7 +41,7 @@ namespace FEXCore::CPU {
// r19-r29 and SP.
namespace x64 {
#ifndef _M_ARM_64EC
#ifndef ARCHITECTURE_arm64ec
// All but x19 and x29 are caller saved
// Note that rax/rdx are rearranged here so we can coalesce cmpxchg.
constexpr std::array<ARMEmitter::Register, 18> SRA = {
@@ -802,7 +802,7 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
auto TmpReg = *OptionalReg;
auto TmpReg2 = *OptionalReg2;
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
// Load STATE in from the CPU area as x28 is not callee saved in the ARM64EC ABI.
ldr(TmpReg.X(), ARMEmitter::Reg::r18, TEB_CPU_AREA_OFFSET);
ldr(STATE, TmpReg, CPU_AREA_EMULATOR_DATA_OFFSET);
@@ -32,7 +32,7 @@ namespace FEXCore::CPU {
// Contains the address to the currently available CPU state
constexpr auto STATE = ARMEmitter::XReg::x28;
#ifndef _M_ARM_64EC
#ifndef ARCHITECTURE_arm64ec
// GPR temporaries. Only x3 can be used across spill boundaries
// so if these ever need to change, be very careful about that.
constexpr auto TMP1 = ARMEmitter::XReg::x0;
+5 -5
View File
@@ -24,7 +24,7 @@ $end_info$
namespace FEXCore {
namespace ProductNames {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
static const char ARM_UNKNOWN[] = "Unknown ARM CPU";
static const char ARM_A57[] = "Cortex-A57";
static const char ARM_A72[] = "Cortex-A72";
@@ -140,7 +140,7 @@ constexpr uint32_t FAMILY_IDENTIFIER = GenerateFamily(CPUFamily {
});
#endif
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
uint32_t GetCycleCounterFrequency() {
uint64_t Result {};
__asm("mrs %[Res], CNTFRQ_EL0" : [Res] "=r"(Result));
@@ -857,10 +857,10 @@ FEXCore::CPUID::FunctionResults CPUIDEmu::Function_4000_0001h(uint32_t Leaf) con
constexpr uint32_t MaximumSubLeafNumber = 2;
if (Leaf == 0) {
// EAX[3:0] Is the host architecture that FEX is running under
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// EAX[3:0] = 1 = x86_64 host architecture
Res.eax |= 0b0001;
#elif defined(_M_ARM_64)
#elif defined(ARCHITECTURE_arm64)
// EAX[3:0] = 2 = AArch64 host architecture
Res.eax |= 0b0010;
#else
@@ -1230,7 +1230,7 @@ CPUIDEmu::CPUIDEmu(const FEXCore::Context::ContextImpl* ctx)
SetupFeatures();
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
if (SupportsCPUIndexInTPIDRRO) {
GetCPUID = GetCPUID_TPIDRRO;
}
+1 -1
View File
@@ -159,7 +159,7 @@ private:
struct CPUData {
const char* ProductName {};
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
uint32_t MIDR {};
#endif
bool IsBig {};
+1 -1
View File
@@ -345,7 +345,7 @@ bool ContextImpl::InitCore() {
// Set up the SignalDelegator config since core is initialized.
SignalDelegation->SetConfig(Dispatcher->MakeSignalDelegatorConfig());
#if defined(_WIN32) && !defined(_M_ARM_64EC)
#if defined(_WIN32) && !defined(ARCHITECTURE_arm64ec)
// WOW64 always needs the interrupt fault check to be enabled.
Config.NeedsPendingInterruptFaultCheck = true;
#endif
@@ -96,7 +96,7 @@ void Dispatcher::EmitDispatcher() {
ARMEmitter::BiDirectionalLabel LoopTop {};
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
(void)b(&LoopTop);
AbsoluteLoopTopAddressEnterECFillSRA = GetCursorAddress<uint64_t>();
@@ -147,7 +147,7 @@ void Dispatcher::EmitDispatcher() {
// Load in our RIP
ldr(RipReg, STATE_PTR(CpuStateFrame, State.rip));
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
// Clobbers TMP1/2
// Check the EC code bitmap incase we need to exit the JIT to call into native code.
ARMEmitter::ForwardLabel l_NotECCode;
@@ -259,7 +259,7 @@ void Dispatcher::EmitDispatcher() {
str(TMP2, STATE, offsetof(FEXCore::Core::CPUState, DeferredSignalRefCount));
#endif
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
ldr(TMP2, ARMEmitter::XReg::x18, TEB_CPU_AREA_OFFSET);
LoadConstant(ARMEmitter::Size::i32Bit, TMP1, 1, CPU::Arm64Emitter::PadType::NOPAD);
strb(TMP1.W(), TMP2, CPU_AREA_IN_SYSCALL_CALLBACK_OFFSET);
@@ -267,7 +267,7 @@ void Dispatcher::EmitDispatcher() {
Body();
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
ldr(TMP2, ARMEmitter::XReg::x18, TEB_CPU_AREA_OFFSET);
strb(ARMEmitter::WReg::zr, TMP2, CPU_AREA_IN_SYSCALL_CALLBACK_OFFSET);
#endif
+1 -1
View File
@@ -1149,7 +1149,7 @@ void Decoder::BranchTargetInMultiblockRange() {
constexpr uint64_t MAX_FORWARD_BRANCH_DIST = FEXCore::Utils::FEX_PAGE_SIZE * 4;
bool ValidMultiblockMember = TargetRIP >= EntryPoint && TargetRIP < std::min(InstEnd + MAX_FORWARD_BRANCH_DIST, SectionMaxAddress);
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
ValidMultiblockMember = ValidMultiblockMember && !RtlIsEcCode(TargetRIP);
#endif
@@ -2,14 +2,14 @@
#include "Interface/Core/Interpreter/Fallbacks/VectorFallbacks.h"
#include "Interface/IR/IR.h"
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
#include <arm_neon.h>
#endif
#include <cstring>
namespace FEXCore::CPU {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
FEXCORE_PRESERVE_ALL_ATTR static int32_t GetImplicitLength(FEXCore::VectorRegType data, uint16_t control) {
const auto is_using_words = (control & 1) != 0;
@@ -56,7 +56,7 @@ DEF_OP(ExitFunction) {
uint64_t NewRIP;
if (IsInlineConstant(Op->NewRIP, &NewRIP) || IsInlineEntrypointOffset(Op->NewRIP, &NewRIP)) {
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
if (NewRIP < EC_CODE_BITMAP_MAX_ADDRESS && RtlIsEcCode(NewRIP)) {
str(REG_CALLRET_SP, STATE_PTR(CpuStateFrame, State.callret_sp));
add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, StaticRegisters[X86State::REG_RSP], 0);
@@ -159,7 +159,7 @@ DEF_OP(ExitFunction) {
EmitLinkedBranch(NewRIP, Op->Hint == IR::BranchHint::Call);
(void)Bind(&l_CallReturn);
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
}
#endif
} else {
+2 -2
View File
@@ -590,7 +590,7 @@ uint64_t Arm64JITCore::ExitFunctionLink(FEXCore::Core::CpuStateFrame* Frame, FEX
} else {
// This case is common between calls and jumps as the thunk callsite can be left untouched.
std::atomic_ref<uint64_t>(Record->HostCode).store(HostCode, std::memory_order::seq_cst);
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// Make memory write visible to other threads reading the same location
asm volatile("dc cvau, %0; dsb ish" : : "r"(Record->HostCode) :);
#endif
@@ -778,7 +778,7 @@ void Arm64JITCore::EmitSuspendInterruptCheck() {
offsetof(FEXCore::Core::InternalThreadState, InterruptFaultPage) - offsetof(FEXCore::Core::InternalThreadState, BaseFrameState));
}
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
static constexpr uint16_t SuspendMagic {0xCAFE};
ldr(TMP2.W(), STATE_PTR(CpuStateFrame, SuspendDoorbell));
@@ -241,7 +241,7 @@ DEF_OP(ProcessorID) {
sub(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, 16);
// Load the getcpu syscall number
#if defined(_M_X86_64)
#if defined(ARCHITECTURE_x86_64)
// Just to ensure the syscall number doesn't change if compiled for an x86_64 host.
constexpr auto GetCPUSyscallNum = 0xa8;
#else
@@ -305,7 +305,7 @@ DEF_OP(MonoBackpatcherWrite) {
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r3, TMP4);
}
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
ldr(TMP2, ARMEmitter::XReg::x18, TEB_CPU_AREA_OFFSET);
LoadConstant(ARMEmitter::Size::i32Bit, TMP1, 1, CPU::Arm64Emitter::PadType::NOPAD);
strb(TMP1.W(), TMP2, CPU_AREA_IN_SYSCALL_CALLBACK_OFFSET);
@@ -318,7 +318,7 @@ DEF_OP(MonoBackpatcherWrite) {
blr(ARMEmitter::Reg::r4);
}
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
ldr(TMP2, ARMEmitter::XReg::x18, TEB_CPU_AREA_OFFSET);
strb(ARMEmitter::WReg::zr, TMP2, CPU_AREA_IN_SYSCALL_CALLBACK_OFFSET);
#endif
@@ -4635,7 +4635,7 @@ void OpDispatchBuilder::INTOp(OpcodeArgs) {
}
#endif
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
// This is used when QueryPerformanceCounter is called on recent Windows versions, it causes CNTVCT to be written into RAX.
constexpr uint8_t GET_CNTVCT_LITERAL = 0x81;
if (Literal == GET_CNTVCT_LITERAL) {
@@ -192,7 +192,7 @@ void OSAllocator_64Bit::DetermineVASize() {
UPPER_BOUND = Size;
#if _M_X86_64 // Last page cannot be allocated on x86
#if ARCHITECTURE_x86_64 // Last page cannot be allocated on x86
UPPER_BOUND -= FEXCore::Utils::FEX_PAGE_SIZE;
#endif
+1 -1
View File
@@ -1923,7 +1923,7 @@ static uint64_t HandleAtomicLoadstoreExclusive(uintptr_t ProgramCounter, uint64_
[[nodiscard]]
std::optional<int32_t> HandleUnalignedAccess(FEXCore::Core::InternalThreadState* Thread, UnalignedHandlerType HandleType,
uintptr_t ProgramCounter, uint64_t* GPRs, bool IsJIT) {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
constexpr bool is_arm64 = true;
#else
constexpr bool is_arm64 = false;
@@ -5,7 +5,7 @@
namespace FEXCore::ArchHelpers::Arm64 {
#ifndef _M_ARM_64
#ifndef ARCHITECTURE_arm64
// These are stub implementations that exist only to allow instantiating the arm64 jit
// on non arm platforms.
+1 -1
View File
@@ -3,7 +3,7 @@ namespace FEXCore::Assert {
// This function can not be inlined
[[noreturn]]
__attribute__((noinline, naked)) void ForcedAssert() {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
asm volatile("ud2");
#else
asm volatile("hlt #1");
+1 -1
View File
@@ -5,7 +5,7 @@
#include <cstring>
namespace FEXCore::UncheckedLongJump {
#if defined(_M_ARM_64)
#if defined(ARCHITECTURE_arm64)
[[nodiscard]]
FEX_DEFAULT_VISIBILITY FEX_NAKED uint64_t SetJump(JumpBuf& Buffer) {
__asm volatile(R"(
@@ -20,13 +20,13 @@ public:
}
uintptr_t GetConvertedPointer() const {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// Itanium C++ ABI (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// Low bit of ptr specifies if this Member function pointer is virtual or not
// Throw an assert if we were trying to cast a virtual member
LOGMAN_THROW_A_FMT((PMF.ptr & 1) == 0, "C++ Pointer-To-Member representation didn't have low bit set to 0. Are you trying to cast a "
"virtual member?");
#elif defined(_M_ARM_64)
#elif defined(ARCHITECTURE_arm64)
// C++ ABI for the Arm 64-bit Architecture (IHI 0059E)
// 4.2.1 Representation of pointer to member function
// Differs from Itanium specification
@@ -39,14 +39,14 @@ public:
// Gets the vtable entry position of a virtual member function.
size_t GetVTableOffset() const {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// Itanium C++ ABI (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// Low bit of ptr specifies if this Member function pointer is virtual or not
// Throw an assert if we are not loading a virtual member.
LOGMAN_THROW_A_FMT((PMF.ptr & 1) == 1, "C++ Pointer-To-Member representation didn't have low bit set to 1. This cast only works for "
"virtual members.");
return PMF.ptr & ~1ULL;
#elif defined(_M_ARM_64)
#elif defined(ARCHITECTURE_arm64)
// C++ ABI for the Arm 64-bit Architecture (IHI 0059E)
// 4.2.1 Representation of pointer to member function
// Differs from Itanium specification
+1 -1
View File
@@ -2,7 +2,7 @@
#include "Utils/SpinWaitLock.h"
namespace FEXCore::Utils::SpinWaitLock {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
constexpr uint64_t NanosecondsInSecond = 1'000'000'000ULL;
static uint32_t GetCycleCounterFrequency() {
+1 -1
View File
@@ -29,7 +29,7 @@ namespace FEXCore::Utils::SpinWaitLock {
*
* On non-ARM platforms it is truly a spin-loop, which is okay for debugging only.
*/
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
#define LOADEXCLUSIVE(LoadExclusiveOp, RegSize) \
/* Prime the exclusive monitor with the passed in address. */ \
+2 -2
View File
@@ -291,7 +291,7 @@ private:
// WFE-read-lock is actually quite likely to succeed.
// Return: true if the lock was acquired.
bool Attempt_WFE_WriteLock() {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
const auto Begin = FEXCore::Utils::SpinWaitLock::GetCycleCounter();
auto Now = Begin;
const auto Duration = FEXCore::Utils::SpinWaitLock::CycleCounterFrequency / CYCLECOUNT_DIVISOR;
@@ -320,7 +320,7 @@ private:
// Return: true if the lock was acquired.
bool Attempt_WFE_ReadLock() {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// Spin on a WFE for a short-amount of time, waiting for write-owned and writer-count to be zero.
// - Attempt to acquire read-lock at that point.
// - Don't add read-waiters bit on failure, return false.
+1 -1
View File
@@ -420,7 +420,7 @@ struct CpuStateFrame {
InternalThreadState* Thread;
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
// Set by the kernel on ARM64EC whenever the JIT should cooperatively suspend running guest code.
uint32_t SuspendDoorbell {};
#endif
@@ -31,7 +31,7 @@ FEX_DEF_NUM_OPS(ProtectOptions)
inline void* VirtualAlloc(void* Base, size_t Size, bool Execute = false, bool Commit = true) {
// Allocate top-down to avoid polluting the lower VA space, as even on 64-bit some programs (i.e. LuaJIT) require allocations below 4GB.
DWORD Flags = (Commit ? MEM_COMMIT : 0) | MEM_RESERVE | MEM_TOP_DOWN;
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
MEM_EXTENDED_PARAMETER Parameter {};
if (Execute) {
Parameter.Type = MemExtendedParameterAttributeFlags;
+1 -1
View File
@@ -9,7 +9,7 @@
// a libc implementation that does not implement std::longjmp.
namespace FEXCore::UncheckedLongJump {
// JumpBuf definition needs to be public because the frontend needs to understand it.
#if defined(_M_ARM_64)
#if defined(ARCHITECTURE_arm64)
struct JumpBuf {
// All the registers that are required by AAPCS64 to save.
// GPRs
+2 -2
View File
@@ -4,12 +4,12 @@
#include <cstddef>
#include <cstdint>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#include <x86intrin.h>
#endif
namespace FEXCore::SHMStats {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
/**
* @brief Get the raw cycle counter with synchronizing isb.
*
@@ -127,7 +127,7 @@ public:
~DeferredSignalRefCountGuard() {
if (Thread) {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// Needs to be atomic so that operations can't end up getting reordered around this.
// Without this, the refcount and the signal access could get reordered.
auto Result = Thread->CurrentFrame->State.DeferredSignalRefCount.Decrement(1);
+1 -1
View File
@@ -534,7 +534,7 @@ def main():
"-isystem", "/usr/x86_64-linux-gnu/include/",
"-O2",
"--target=x86_64-linux-unknown",
"-D_M_X86_64",
"-DARCHITECTURE_x86_64",
]
# Add all the arguments to the different lists
+2 -2
View File
@@ -669,14 +669,14 @@ def main():
"-isystem", "/usr/x86_64-linux-gnu/include",
"-O2",
"--target=x86_64-linux-unknown",
"-D_M_X86_64",
"-DARCHITECTURE_x86_64",
]
args_aarch64 = [
"-isystem", "/usr/aarch64-linux-gnu/include",
"-O2",
"--target=aarch64-linux-unknown",
"-D_M_ARM_64",
"-DARCHITECTURE_arm64",
]
args_x86_win32 = [
+10 -10
View File
@@ -10,7 +10,7 @@
#include <range/v3/view/split.hpp>
#include <range/v3/view/transform.hpp>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#include "Common/X86Features.h"
#endif
@@ -19,7 +19,7 @@ namespace FEX {
void FillMIDRInformationViaLinux(FEXCore::HostFeatures* Features) {
auto Cores = FEX::CPUInfo::CalculateNumberOfCPUs();
Features->CPUMIDRs.resize(Cores);
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
for (size_t i = 0; i < Cores; ++i) {
std::error_code ec {};
fextl::string MIDRPath = fextl::fmt::format("/sys/devices/system/cpu/cpu{}/regs/identification/midr_el1", i);
@@ -38,7 +38,7 @@ void FillMIDRInformationViaLinux(FEXCore::HostFeatures* Features) {
#endif
}
#if defined(_M_ARM_64) && !defined(VIXL_SIMULATOR)
#if defined(ARCHITECTURE_arm64) && !defined(VIXL_SIMULATOR)
__attribute__((naked)) static uint64_t ReadSVEVectorLengthInBits() {
///< Can't use rdvl instruction directly because compilers will complain that sve/sme is required.
__asm(R"(
@@ -54,7 +54,7 @@ static int ReadSVEVectorLengthInBits() {
}
#endif
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
#define GetSysReg(name, reg) \
static uint64_t Get_##name() { \
uint64_t Result {}; \
@@ -446,7 +446,7 @@ void FEX::CPUFeatures::FillFeatureFlags() {
}
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
static uint32_t GetFPCR() {
uint64_t Result {};
__asm("mrs %[Res], FPCR" : [Res] "=r"(Result));
@@ -550,7 +550,7 @@ static void HandleErrata(FEXCore::HostFeatures* HostFeatures, uint64_t MIDR) {
const uint32_t MIDR_Implementer = GetMIDRImplementer(MIDR);
const uint32_t MIDR_PartNum = GetMIDRPartNum(MIDR);
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
if (MIDR_Implementer == Implementer_QCOM && MIDR_PartNum == PartNum_Oryon1) {
// Work around an errata in Qualcomm's Oryon.
// While this CPU implements the RAND extension:
@@ -646,7 +646,7 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe
WARN_ONCE_FMT("Host CPU doesn't support atomics. Expect bad performance");
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// Test if this CPU supports float exception trapping by attempting to enable
// On unsupported these bits are architecturally defined as RAZ/WI
constexpr uint32_t ExceptionEnableTraps = (1U << 8) | // Invalid Operation float exception trap enable
@@ -696,7 +696,7 @@ void FetchHostFeatures(FEX::CPUFeatures& Features, FEXCore::HostFeatures& HostFe
HostFeatures.DCacheLineSize = HostFeatures.ICacheLineSize = 64;
}
#if defined(_M_X86_64) && !defined(VIXL_SIMULATOR)
#if defined(ARCHITECTURE_x86_64) && !defined(VIXL_SIMULATOR)
FEX::X86::Features Feature {};
HostFeatures.SupportsAES = Feature.Feat_aes;
HostFeatures.SupportsCRC = Feature.Feat_crc;
@@ -725,7 +725,7 @@ FEXCore::HostFeatures FetchHostFeatures() {
if (!CPUFeatureRegisters().empty()) {
Features = GetCPUFeaturesFromConfig(CPUFeatureRegisters());
} else {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
Features = CPUFeaturesAll {};
// Vixl simulator doesn't support AFP.
@@ -739,7 +739,7 @@ FEXCore::HostFeatures FetchHostFeatures() {
uint64_t CTR = 0;
uint64_t MIDR = 0;
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// We need to get the CPU's cache line size
// We expect sane targets that have correct cacheline sizes across clusters
__asm volatile("mrs %[ctr], ctr_el0" : [ctr] "=r"(CTR));
+1 -1
View File
@@ -12,7 +12,7 @@ namespace FEXCore::Core {
struct InternalThreadState;
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
static inline void store_memory_barrier() {
asm volatile("dmb ishst;" ::: "memory");
}
+1 -1
View File
@@ -1,7 +1,7 @@
#pragma once
#include <cstdint>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#include <cpuid.h>
namespace FEX::X86 {
+3 -3
View File
@@ -22,7 +22,7 @@ struct TSOEmulationFacts {
bool LRCPC1 {}, LRCPC2 {}, LRCPC3 {};
};
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
bool CheckForHardwareTSO() {
// Check to see if this is supported.
auto Result = prctl(PR_GET_MEM_MODEL, 0, 0, 0, 0);
@@ -113,7 +113,7 @@ int main(int argc, char** argv, char** envp) {
Parser.add_option("--tso-emulation-info").action("store_true").help("Print how FEX is emulating the x86-TSO memory model.");
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
Parser.add_option("--identification-reg-info").action("store_true").help("Print identification registers");
#endif
@@ -235,7 +235,7 @@ int main(int argc, char** argv, char** envp) {
fprintf(stdout, "\t64-Byte strict split-lock emulation: %s\n", StrictInProcessSplitLocks() ? "In-process mutex" : "Tearing");
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
if (Options.is_set_by_user("identification_reg_info")) {
auto Features = FEX::GetCPUFeaturesFromIDRegisters();
fextl::string features {};
+1 -1
View File
@@ -51,7 +51,7 @@ install(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/FEX
DESTINATION bin
COMPONENT LegacyRuntime)
if (_M_ARM_64)
if (ARCHITECTURE_arm64)
if (NOT USE_LEGACY_BINFMTMISC)
# Just restart the systemd service
add_custom_target(binfmt_misc
@@ -448,7 +448,7 @@ int main(int argc, char** argv, char** const envp) {
if (!Loader.ELFWasLoaded()) {
// Loader couldn't load this program for some reason
fextl::fmt::print(stderr, "Invalid or Unsupported elf file.\n");
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
fextl::fmt::print(stderr, "This is likely due to a misconfigured x86-64 RootFS\n");
fextl::fmt::print(stderr, "Current RootFS path set to '{}'\n", LDPath());
if (LDPath().empty() || FHU::Filesystem::Exists(LDPath()) == false) {
@@ -2,7 +2,7 @@
#include "ArchHelpers/MContext.h"
namespace FEX::ArchHelpers::Context {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
std::string_view GetESRName(uint64_t ESR) {
switch ((ESR & ESR1_EC) >> 26) {
case 0b000'000: return "Unknown";
@@ -93,7 +93,7 @@ static inline mcontext_t* GetMContext(void* ucontext) {
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
constexpr uint32_t FPR_MAGIC = 0x46508001U;
constexpr uint32_t ESR1_MAGIC = 0x45535201U;
@@ -300,7 +300,7 @@ static inline void RestoreContext(void* ucontext, T* Backup) {
#endif
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
static inline uint64_t GetSp(void* ucontext) {
return GetMContext(ucontext)->gregs[REG_RSP];
@@ -5,7 +5,7 @@
#include <winnt.h>
namespace FEX::ArchHelpers::Context {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
static inline uint64_t GetSp(PCONTEXT Context) {
return Context->Sp;
}
@@ -35,7 +35,7 @@ static inline uint64_t* GetArmGPRs(PCONTEXT Context) {
}
#endif
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
static inline uint64_t GetSp(PCONTEXT Context) {
return Context->Rsp;
}
@@ -2,7 +2,7 @@
#include "LinuxSyscalls/Syscalls.h"
namespace FEX::HLE::FaultSafeUserMemAccess {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
__attribute__((naked)) size_t CopyFromUser(void* Dest, const void* Src, size_t Size) {
__asm volatile(R"(
// Early exit if a memcpy of size zero.
@@ -47,7 +47,7 @@ void* const CopyFromUser_FaultLocation = &CopyFromUser_FaultInst;
extern "C" uint64_t CopyToUser_FaultInst;
void* const CopyToUser_FaultLocation = &CopyToUser_FaultInst;
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED && defined(_M_ARM_64)
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED && defined(ARCHITECTURE_arm64)
__attribute__((naked)) bool VerifyIsReadableImpl(const void* Src, size_t Size) {
__asm volatile(R"(
// Early exit if size is zero.
@@ -157,7 +157,7 @@ bool IsFaultLocation(uint64_t PC) {
bool IsMemcpyFault = false;
IsMemcpyFault |= reinterpret_cast<void*>(PC) == CopyToUser_FaultLocation;
IsMemcpyFault |= reinterpret_cast<void*>(PC) == CopyFromUser_FaultLocation;
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED && defined(_M_ARM_64)
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED && defined(ARCHITECTURE_arm64)
IsMemcpyFault |= reinterpret_cast<void*>(PC) == UserReadable_FaultLocation;
IsMemcpyFault |= reinterpret_cast<void*>(PC) == UserWritable_FaultLocation;
IsMemcpyFault |= reinterpret_cast<void*>(PC) == UserStringReadable_FaultLocation;
@@ -42,7 +42,7 @@ $end_info$
#endif
namespace FEX::HLE {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
__attribute__((naked)) static void sigrestore() {
__asm volatile("syscall;" ::"a"(0xF) : "memory");
}
@@ -110,7 +110,7 @@ void SignalDelegator::RegisterHostSignalHandler(int Signal, HostSignalDelegatorF
}
void SignalDelegator::SpillSRA(FEXCore::Core::InternalThreadState* Thread, void* ucontext, uint32_t IgnoreMask) {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
Thread->CurrentFrame->State.rip = CTX->RestoreRIPFromHostPC(Thread, ArchHelpers::Context::GetPc(ucontext));
for (size_t i = 0; i < Config.SRAGPRCount; i++) {
@@ -305,7 +305,7 @@ bool SignalDelegator::HandleDispatcherGuestSignal(FEXCore::Core::InternalThreadS
// Otherwise we might load garbage
if (WasInJIT) {
uint32_t IgnoreMask {};
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
if (Frame->InSyscallInfo != 0) {
// We are in a syscall, this means we are in a weird register state
// We need to spill SRA but only some of it, since some values have already been spilled
@@ -581,7 +581,7 @@ bool SignalDelegator::HandleFrontendSIGSEGV(FEXCore::Core::InternalThreadState*
ERROR_AND_DIE_FMT("Received invalid data to syscall. Crashing now!");
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
if (Signal == SIGSEGV && SigInfo.si_code == SEGV_ACCERR && SigInfo.si_addr >= reinterpret_cast<void*>(Thread->JITGuardPage) &&
SigInfo.si_addr < reinterpret_cast<void*>(Thread->JITGuardPage + FEXCore::Utils::FEX_PAGE_SIZE)) {
FEXCore::UncheckedLongJump::ManuallyLoadJumpBuf(Thread->RestartJump, Thread->JITGuardOverflowArgument,
@@ -630,7 +630,7 @@ void SignalDelegator::HandleGuestSignal(FEX::HLE::ThreadStateObject* ThreadObjec
// - If there are *no* deferred signals
// - No need to mprotect, it is already RW
} else {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// If RefCount != 0 then that means we hit an access with nested signal-deferring sections.
// Increment the PC past the `str zr, [x1]` to continue code execution until we reach the outermost section.
ArchHelpers::Context::SetPc(UContext, ArchHelpers::Context::GetPc(UContext) + 4);
@@ -791,7 +791,7 @@ bool SignalDelegator::UpdateHostThunk(int Signal) {
SignalHandler.HostAction.sa_flags = CheckAndAddFlags(SignalHandler.HostAction.sa_flags, SignalHandler.GuestAction.sa_flags,
SA_NOCLDSTOP | SA_NOCLDWAIT | SA_NODEFER | SA_RESTART);
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#define SA_RESTORER 0x04000000
SignalHandler.HostAction.sa_flags |= SA_RESTORER;
SignalHandler.HostAction.restorer = sigrestore;
@@ -922,7 +922,7 @@ SignalDelegator::SignalDelegator(FEXCore::Context::Context* _CTX, const std::str
ucontext_t* _context = (ucontext_t*)ucontext;
auto& mcontext = _context->uc_mcontext;
uint64_t PC {};
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
PC = mcontext.pc;
#else
PC = mcontext.gregs[REG_RIP];
@@ -960,7 +960,7 @@ SignalDelegator::SignalDelegator(FEXCore::Context::Context* _CTX, const std::str
RegisterHostSignalHandler(SIGILL, SigillHandler, true);
RegisterHostSignalHandler(SIGSEGV, SigsegvHandler, true);
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
// Register SIGBUS signal handler.
const auto SigbusHandler = [](FEXCore::Core::InternalThreadState* Thread, int Signal, void* _info, void* ucontext) -> bool {
const auto PC = ArchHelpers::Context::GetPc(ucontext);
@@ -38,9 +38,9 @@ $end_info$
#include <stdint.h>
#include <type_traits>
#include <list>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#define SYSCALL_ARCH_NAME x64
#elif _M_ARM_64
#elif ARCHITECTURE_arm64
#include "LinuxSyscalls/Arm64/SyscallsEnum.h"
#define SYSCALL_ARCH_NAME Arm64
#endif
@@ -464,9 +464,9 @@ struct clone3_args {
uint64_t CloneHandler(FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::clone3_args* args);
inline static int RemapFromX86Flags(int flags) {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// Nothing to change here
#elif _M_ARM_64
#elif ARCHITECTURE_arm64
constexpr int X86_64_FLAG_O_DIRECT = 040000;
constexpr int X86_64_FLAG_O_LARGEFILE = 0100000;
constexpr int X86_64_FLAG_O_DIRECTORY = 0200000;
@@ -502,9 +502,9 @@ inline static int RemapFromX86Flags(int flags) {
}
inline static int RemapToX86Flags(int flags) {
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
// Nothing to change here
#elif _M_ARM_64
#elif ARCHITECTURE_arm64
constexpr int X86_64_FLAG_O_DIRECT = 040000;
constexpr int X86_64_FLAG_O_LARGEFILE = 0100000;
constexpr int X86_64_FLAG_O_DIRECTORY = 0200000;
@@ -582,7 +582,7 @@ namespace FaultSafeUserMemAccess {
size_t CopyFromUser(void* Dest, const void* Src, size_t Size);
[[nodiscard]]
size_t CopyToUser(void* Dest, const void* Src, size_t Size);
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED && defined(_M_ARM_64)
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED && defined(ARCHITECTURE_arm64)
// These helpers just check if the user pointer is readable and writable.
// This is useful in an assert build that can be safely sprinkled through the syscall handler without overhead in release builds.
void VerifyIsReadable(const void* Src, size_t Size);
@@ -16,7 +16,7 @@ $end_info$
#include <sys/epoll.h>
namespace FEX::HLE {
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
template<int syscall_num>
requires (syscall_num != -1)
uint64_t SyscallPassthrough0(FEXCore::Core::CpuStateFrame* Frame) {
@@ -122,7 +122,7 @@ void StackTracker::DeallocateStackObjectAndExit(void* Ptr, int Status) {
*ReadyToBeReaped = true;
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
__asm volatile("mov x8, %[SyscallNum];"
"mov w0, %w[Result];"
"svc #0;" ::[SyscallNum] "i"(SYSCALL_DEF(exit)),
@@ -137,7 +137,7 @@ void StackTracker::DeallocateStackObjectAndExit(void* Ptr, int Status) {
FEX_UNREACHABLE;
}
#ifdef _M_ARM_64
#ifdef ARCHITECTURE_arm64
__attribute__((naked)) void StackPivotAndCall(void* Arg, FEXCore::Threads::ThreadFunc Func, uint64_t StackPivot) {
// x0: Arg
// x1: Function to call
@@ -53,7 +53,7 @@ static constexpr int SanitizeIOCount(int count) {
return std::max(0, count);
}
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
uint32_t ioctl_32(FEXCore::Core::CpuStateFrame*, int fd, uint32_t cmd, uint32_t args) {
uint32_t Result {};
__asm volatile("int $0x80;" : "=a"(Result) : "a"(SYSCALL_x86_ioctl), "b"(fd), "c"(cmd), "d"(args) : "memory");
+2 -2
View File
@@ -41,14 +41,14 @@ FEX_DEFAULT_VISIBILITY JEMALLOC_NOTHROW extern int glibc_je_is_known_allocation(
#endif
static __attribute__((aligned(16), naked, section("HostToGuestTrampolineTemplate"))) void HostToGuestTrampolineTemplate() {
#if defined(_M_X86_64)
#if defined(ARCHITECTURE_x86_64)
asm("lea 0f(%rip), %r11 \n"
"jmpq *0f(%rip) \n"
".align 8 \n"
"0: \n"
".quad 0, 0, 0, 0 \n" // TrampolineInstanceInfo
);
#elif defined(_M_ARM_64)
#elif defined(ARCHITECTURE_arm64)
asm(
// x11 is part of the custom ABI and needs to point to the TrampolineInstanceInfo.
"ldr x16, 0f \n"
@@ -43,7 +43,7 @@ $end_info$
#include <sys/types.h>
#include <utility>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#include "Common/X86Features.h"
#endif
@@ -265,7 +265,7 @@ int main(int argc, char** argv, char** const envp) {
bool IsHostRunner = false;
#if !defined(VIXL_SIMULATOR) && defined(_M_X86_64)
#if !defined(VIXL_SIMULATOR) && defined(ARCHITECTURE_x86_64)
IsHostRunner = true;
///< Features that are only unsupported when running using the HostRunner and the CI machine doesn't support the feature getting tested.
FEX::X86::Features Feature {};
@@ -11,7 +11,7 @@
#include <FEXCore/fextl/unordered_set.h>
#include <FEXCore/Utils/LogManager.h>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
#include "Common/X86Features.h"
#include <asm/ldt.h>
#include <sys/syscall.h>
@@ -23,7 +23,7 @@
#include <signal.h>
#ifdef _M_X86_64
#ifdef ARCHITECTURE_x86_64
static inline int modify_ldt(int func, void* ldt) {
return ::syscall(SYS_modify_ldt, func, ldt, sizeof(struct user_desc));
}
+2 -2
View File
@@ -28,8 +28,8 @@ build_implib(wow64)
add_subdirectory(Common)
if (_M_ARM_64EC)
if (ARCHITECTURE_arm64ec)
add_subdirectory(ARM64EC)
elseif (_M_ARM_64)
elseif (ARCHITECTURE_arm64)
add_subdirectory(WOW64)
endif()
+1 -1
View File
@@ -77,7 +77,7 @@ FEXCore::HostFeatures CPUFeatures::FetchHostFeatures(bool IsWine) {
}
CPUFeatures::CPUFeatures(FEXCore::Context::Context& CTX) {
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
// Report as a 64-bit host for ARM64EC.
CpuInfo.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
#else
+1 -1
View File
@@ -23,7 +23,7 @@ class Context;
}
namespace FEX::Windows {
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
using ArchImageNtHeaders = IMAGE_NT_HEADERS64;
using ArchImageLoadConfigDirectory = _IMAGE_LOAD_CONFIG_DIRECTORY64;
#else
+2 -2
View File
@@ -32,7 +32,7 @@ extern "C" {
#define STATUS_EMULATION_SYSCALL ((NTSTATUS)0x40000039)
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
typedef struct _CHPE_V2_CPU_AREA_INFO {
BOOLEAN InSimulation; /* 000 */
BOOLEAN InSyscallCallback; /* 001 */
@@ -341,7 +341,7 @@ typedef struct __TEB { /* win32/win64 */
#ifdef _WIN64
union {
PVOID DeallocationBStore; /* /1788 */
#ifdef _M_ARM_64EC
#ifdef ARCHITECTURE_arm64ec
CHPE_V2_CPU_AREA_INFO* ChpeV2CpuAreaInfo; /* /1788 */
#endif
} DUMMYUNIONNAME;
+2 -2
View File
@@ -27,9 +27,9 @@ function(generate NAME SOURCE_FILE GUEST_BITNESS)
set(prop "$<TARGET_PROPERTY:${NAME}-${GUEST_BITNESS}-deps,INTERFACE_INCLUDE_DIRECTORIES>")
set(compile_prop "$<TARGET_PROPERTY:${NAME}-${GUEST_BITNESS}-deps,INTERFACE_COMPILE_DEFINITIONS>")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
list(APPEND compile_prop _M_X86_64=1)
list(APPEND compile_prop ARCHITECTURE_x86_64=1)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
list(APPEND compile_prop _M_ARM_64=1)
list(APPEND compile_prop ARCHITECTURE_arm64=1)
endif()
# Target for IDE integration
+2 -2
View File
@@ -17,7 +17,7 @@
template<typename signature>
THUNK_ABI const int (*fexthunks_invoke_callback)(void*);
#ifndef _M_ARM_64
#ifndef ARCHITECTURE_arm64
#define MAKE_THUNK(lib, name, hash) \
extern "C" __attribute__((visibility("hidden"))) THUNK_ABI int fexthunks_##lib##_##name(void* args); \
asm(".text\nfexthunks_" #lib "_" #name ":\n.byte 0xF, 0x3F\n.byte " hash);
@@ -110,7 +110,7 @@ inline bool IsLibLoaded(const char* libname) {
// fexfn_pack_* functions generated for global API functions.
template<auto Thunk, typename Result, typename... Args>
inline Result CallHostFunction(Args... args) {
#ifndef _M_ARM_64
#ifndef ARCHITECTURE_arm64
#if __SIZEOF_POINTER__ == 8
// This magic incantation of using a register variable with an empty asm block is necessary for correct operation!
// If we only use inline asm that sets a variable then the compiler will reorder the function
+2 -2
View File
@@ -78,9 +78,9 @@ struct GuestcallInfo {
// Helper macro for reading an internal argument passed through the `r11`
// host register. This macro must be placed at the very beginning of
// the function it is used in.
#if defined(_M_X86_64)
#if defined(ARCHITECTURE_x86_64)
#define LOAD_INTERNAL_GUESTPTR_VIA_CUSTOM_ABI(target_variable) asm volatile("mov %%r11, %0" : "=r"(target_variable))
#elif defined(_M_ARM_64)
#elif defined(ARCHITECTURE_arm64)
#define LOAD_INTERNAL_GUESTPTR_VIA_CUSTOM_ABI(target_variable) asm volatile("mov %0, x11" : "=r"(target_variable))
#endif
+2 -2
View File
@@ -49,7 +49,7 @@ foreach(ASM_SRC ${ASM_SOURCES})
list(APPEND ASM_DEPENDS "${OUTPUT_NAME};${OUTPUT_CONFIG_NAME}")
set(TEST_ARGS)
if (_M_ARM_64 OR ENABLE_VIXL_SIMULATOR)
if (ARCHITECTURE_arm64 OR ENABLE_VIXL_SIMULATOR)
list(APPEND TEST_ARGS
"FEX_SILENTLOG=0 FEX_DUMPGPRS=1 FEX_MAXINST=1 FEX_MULTIBLOCK=0 FEX_TSOENABLED=0" "jit_1" "jit"
"FEX_SILENTLOG=0 FEX_DUMPGPRS=1 FEX_MAXINST=500 FEX_MULTIBLOCK=0 FEX_TSOENABLED=0" "jit_500" "jit"
@@ -59,7 +59,7 @@ foreach(ASM_SRC ${ASM_SOURCES})
if (ENABLE_VIXL_SIMULATOR)
set(CPU_CLASS Simulator)
elseif (_M_X86_64)
elseif (ARCHITECTURE_x86_64)
list(APPEND TEST_ARGS
"FEX_SILENTLOG=0 FEX_DUMPGPRS=1" "host" "host"
)
+3 -4
View File
@@ -30,8 +30,7 @@ foreach(ASM_SRC ${ASM_SOURCES})
add_custom_command(OUTPUT ${TMP_FILE}
DEPENDS "${ASM_SRC}"
COMMAND "cp" ARGS "${ASM_SRC}" "${TMP_FILE}"
COMMAND "sed" ARGS "-i" "-e" "\'1s;^;BITS 64\\n;\'" "-e" "\'\$\$a\\ret\\n\'" "${TMP_FILE}"
)
COMMAND "sed" ARGS "-i" "-e" "\'1s;^;BITS 64\\n;\'" "-e" "\'\$\$a\\ret\\n\'" "${TMP_FILE}")
set(OUTPUT_NAME "${OUTPUT_ASM_FOLDER}/${ASM_NAME}.bin")
set(OUTPUT_CONFIG_NAME "${OUTPUT_ASM_FOLDER}/${ASM_NAME}.config.bin")
@@ -51,7 +50,7 @@ foreach(ASM_SRC ${ASM_SOURCES})
# Format is "<Test Arguments>" "<Test Name>" "<Test Type>"
set(TEST_ARGS)
if (_M_ARM_64 OR ENABLE_VIXL_SIMULATOR)
if (ARCHITECTURE_arm64 OR ENABLE_VIXL_SIMULATOR)
list(APPEND TEST_ARGS
"FEX_SILENTLOG=0 FEX_DUMPGPRS=1 FEX_MAXINST=1 FEX_MULTIBLOCK=0 FEX_TSOENABLED=0" "jit_1" "jit"
"FEX_SILENTLOG=0 FEX_DUMPGPRS=1 FEX_MAXINST=500 FEX_MULTIBLOCK=0 FEX_TSOENABLED=0" "jit_500" "jit"
@@ -61,7 +60,7 @@ foreach(ASM_SRC ${ASM_SOURCES})
if (ENABLE_VIXL_SIMULATOR)
set(CPU_CLASS Simulator)
elseif (_M_X86_64)
elseif (ARCHITECTURE_x86_64)
list(APPEND TEST_ARGS
"FEX_SILENTLOG=0 FEX_DUMPGPRS=1" "host" "host"
)
+1 -1
View File
@@ -63,7 +63,7 @@ function(AddTests Tests BinDirectory Bitness)
set_property(TEST "${TEST_CASE}.jit.flt" APPEND PROPERTY ENVIRONMENT "FEX_THUNKCONFIG=${CMAKE_SOURCE_DIR}/Data/CI/FEXLinuxTestsThunks.json")
endif()
if (_M_X86_64 AND NOT TEST_NAME STREQUAL "thunk_testlib")
if (ARCHITECTURE_x86_64 AND NOT TEST_NAME STREQUAL "thunk_testlib")
# Add host test case
add_test(NAME "${TEST_CASE}.host.flt"
COMMAND "python3" "${CMAKE_SOURCE_DIR}/Scripts/guest_test_runner.py"