mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-11-23 06:30:01 +00:00
clang-format: left-align escaped newlines
alternative to #3638. this is theoretically better for side-by-side diffs. in practice it may make other diffs worse since all the \'s change when part of the macro change. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
parent
048c8ded88
commit
a10f984b1c
@ -7,7 +7,7 @@ AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: Consecutive
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
|
@ -359,14 +359,14 @@ void CPUIDEmu::SetupFeatures() {
|
||||
return;
|
||||
}
|
||||
|
||||
#define ENABLE_DISABLE_OPTION(FeatureName, name, enum_name) \
|
||||
do { \
|
||||
const bool Disable##name = (CPUIDFeatures() & FEXCore::Config::CPUID::DISABLE##enum_name) != 0; \
|
||||
const bool Enable##name = (CPUIDFeatures() & FEXCore::Config::CPUID::ENABLE##enum_name) != 0; \
|
||||
#define ENABLE_DISABLE_OPTION(FeatureName, name, enum_name) \
|
||||
do { \
|
||||
const bool Disable##name = (CPUIDFeatures() & FEXCore::Config::CPUID::DISABLE##enum_name) != 0; \
|
||||
const bool Enable##name = (CPUIDFeatures() & FEXCore::Config::CPUID::ENABLE##enum_name) != 0; \
|
||||
LogMan::Throw::AFmt(!(Disable##name && Enable##name), "Disabling and Enabling CPU feature (" #name ") is mutually exclusive"); \
|
||||
const bool AlreadyEnabled = Features.FeatureName; \
|
||||
const bool Result = (AlreadyEnabled | Enable##name) & !Disable##name; \
|
||||
Features.FeatureName = Result; \
|
||||
const bool AlreadyEnabled = Features.FeatureName; \
|
||||
const bool Result = (AlreadyEnabled | Enable##name) & !Disable##name; \
|
||||
Features.FeatureName = Result; \
|
||||
} while (0)
|
||||
|
||||
ENABLE_DISABLE_OPTION(SHA, SHA, SHA);
|
||||
|
@ -59,19 +59,19 @@ static void OverrideFeatures(HostFeatures* Features) {
|
||||
return;
|
||||
}
|
||||
|
||||
#define ENABLE_DISABLE_OPTION(FeatureName, name, enum_name) \
|
||||
do { \
|
||||
const bool Disable##name = (HostFeatures() & FEXCore::Config::HostFeatures::DISABLE##enum_name) != 0; \
|
||||
const bool Enable##name = (HostFeatures() & FEXCore::Config::HostFeatures::ENABLE##enum_name) != 0; \
|
||||
#define ENABLE_DISABLE_OPTION(FeatureName, name, enum_name) \
|
||||
do { \
|
||||
const bool Disable##name = (HostFeatures() & FEXCore::Config::HostFeatures::DISABLE##enum_name) != 0; \
|
||||
const bool Enable##name = (HostFeatures() & FEXCore::Config::HostFeatures::ENABLE##enum_name) != 0; \
|
||||
LogMan::Throw::AFmt(!(Disable##name && Enable##name), "Disabling and Enabling CPU feature (" #name ") is mutually exclusive"); \
|
||||
const bool AlreadyEnabled = Features->FeatureName; \
|
||||
const bool Result = (AlreadyEnabled | Enable##name) & !Disable##name; \
|
||||
Features->FeatureName = Result; \
|
||||
const bool AlreadyEnabled = Features->FeatureName; \
|
||||
const bool Result = (AlreadyEnabled | Enable##name) & !Disable##name; \
|
||||
Features->FeatureName = Result; \
|
||||
} while (0)
|
||||
|
||||
#define GET_SINGLE_OPTION(name, enum_name) \
|
||||
#define GET_SINGLE_OPTION(name, enum_name) \
|
||||
const bool Disable##name = (HostFeatures() & FEXCore::Config::HostFeatures::DISABLE##enum_name) != 0; \
|
||||
const bool Enable##name = (HostFeatures() & FEXCore::Config::HostFeatures::ENABLE##enum_name) != 0; \
|
||||
const bool Enable##name = (HostFeatures() & FEXCore::Config::HostFeatures::ENABLE##enum_name) != 0; \
|
||||
LogMan::Throw::AFmt(!(Disable##name && Enable##name), "Disabling and Enabling CPU feature (" #name ") is mutually exclusive");
|
||||
|
||||
ENABLE_DISABLE_OPTION(SupportsAVX, AVX, AVX);
|
||||
|
@ -185,22 +185,22 @@ bool InterpreterOps::GetFallbackHandler(bool SupportsPreserveAllABI, const IR::I
|
||||
break;
|
||||
}
|
||||
|
||||
#define COMMON_UNARY_X87_OP(OP) \
|
||||
case IR::OP_F80##OP: { \
|
||||
#define COMMON_UNARY_X87_OP(OP) \
|
||||
case IR::OP_F80##OP: { \
|
||||
*Info = {FABI_F80_I16_F80, (void*)&FEXCore::CPU::OpHandlers<IR::OP_F80##OP>::handle, Core::OPINDEX_F80##OP, SupportsPreserveAllABI}; \
|
||||
return true; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define COMMON_BINARY_X87_OP(OP) \
|
||||
case IR::OP_F80##OP: { \
|
||||
#define COMMON_BINARY_X87_OP(OP) \
|
||||
case IR::OP_F80##OP: { \
|
||||
*Info = {FABI_F80_I16_F80_F80, (void*)&FEXCore::CPU::OpHandlers<IR::OP_F80##OP>::handle, Core::OPINDEX_F80##OP, SupportsPreserveAllABI}; \
|
||||
return true; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define COMMON_F64_OP(OP) \
|
||||
case IR::OP_F64##OP: { \
|
||||
#define COMMON_F64_OP(OP) \
|
||||
case IR::OP_F64##OP: { \
|
||||
*Info = GetFallbackInfo(&FEXCore::CPU::OpHandlers<IR::OP_F64##OP>::handle, Core::OPINDEX_F64##OP); \
|
||||
return true; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
// Unary
|
||||
|
@ -384,15 +384,15 @@ DEF_OP(Vector_FToI) {
|
||||
// frinti having AdvSIMD, AdvSIMD scalar, and an SVE version),
|
||||
// we can't just use a lambda without some seriously ugly casting.
|
||||
// This is fairly self-contained otherwise.
|
||||
#define ROUNDING_FN(name) \
|
||||
if (ElementSize == 2) { \
|
||||
name(Dst.H(), Vector.H()); \
|
||||
#define ROUNDING_FN(name) \
|
||||
if (ElementSize == 2) { \
|
||||
name(Dst.H(), Vector.H()); \
|
||||
} else if (ElementSize == 4) { \
|
||||
name(Dst.S(), Vector.S()); \
|
||||
name(Dst.S(), Vector.S()); \
|
||||
} else if (ElementSize == 8) { \
|
||||
name(Dst.D(), Vector.D()); \
|
||||
} else { \
|
||||
FEX_UNREACHABLE; \
|
||||
name(Dst.D(), Vector.D()); \
|
||||
} else { \
|
||||
FEX_UNREACHABLE; \
|
||||
}
|
||||
|
||||
switch (Op->Round) {
|
||||
|
@ -1580,9 +1580,9 @@ private:
|
||||
// replaced with NewOp. Useful for generic building code. Not safe in general.
|
||||
// but does the right handling of ImplicitFlagClobber at least and must be
|
||||
// used instead of raw Op mutation.
|
||||
#define DeriveOp(Dest, NewOp, Expr) \
|
||||
#define DeriveOp(Dest, NewOp, Expr) \
|
||||
if (ImplicitFlagClobber(NewOp)) SaveNZCV(NewOp); \
|
||||
auto Dest = (Expr); \
|
||||
auto Dest = (Expr); \
|
||||
Dest.first->Header.Op = (NewOp)
|
||||
|
||||
// Named constant cache for the current block.
|
||||
|
@ -22,13 +22,13 @@ namespace FEXCore::Utils::SpinWaitLock {
|
||||
*/
|
||||
#ifdef _M_ARM_64
|
||||
|
||||
#define LOADEXCLUSIVE(LoadExclusiveOp, RegSize) \
|
||||
#define LOADEXCLUSIVE(LoadExclusiveOp, RegSize) \
|
||||
/* Prime the exclusive monitor with the passed in address. */ \
|
||||
#LoadExclusiveOp " %" #RegSize "[Result], [%[Futex]];"
|
||||
|
||||
#define SPINLOOP_BODY(LoadAtomicOp, RegSize) \
|
||||
#define SPINLOOP_BODY(LoadAtomicOp, RegSize) \
|
||||
/* WFE will wait for either the memory to change or spurious wake-up. */ \
|
||||
"wfe;" /* Load with acquire to get the result of memory. */ \
|
||||
"wfe;" /* Load with acquire to get the result of memory. */ \
|
||||
#LoadAtomicOp " %" #RegSize "[Result], [%[Futex]]; "
|
||||
|
||||
#define SPINLOOP_WFE_LDX_8BIT LOADEXCLUSIVE(ldaxrb, w)
|
||||
|
@ -136,10 +136,10 @@ namespace DefaultValues {
|
||||
#define OPT_STRARRAY(group, enum, json, default) OPT_STR(group, enum, json, default)
|
||||
#include <FEXCore/Config/ConfigValues.inl>
|
||||
} // namespace Type
|
||||
#define FEX_CONFIG_OPT(name, enum) \
|
||||
#define FEX_CONFIG_OPT(name, enum) \
|
||||
FEXCore::Config::Value<FEXCore::Config::DefaultValues::Type::enum> name { \
|
||||
FEXCore::Config::CONFIG_##enum, \
|
||||
FEXCore::Config::DefaultValues::enum \
|
||||
FEXCore::Config::CONFIG_##enum, \
|
||||
FEXCore::Config::DefaultValues::enum \
|
||||
}
|
||||
|
||||
#undef P
|
||||
|
@ -2,27 +2,27 @@
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
|
||||
#define FEX_DEF_ENUM_CLASS_BIN_OP(Enum, Op) \
|
||||
[[maybe_unused]] static constexpr Enum operator Op(Enum lhs, Enum rhs) { \
|
||||
using Type = std::underlying_type_t<Enum>; \
|
||||
Type _lhs = static_cast<Type>(lhs); \
|
||||
Type _rhs = static_cast<Type>(rhs); \
|
||||
return static_cast<Enum>(_lhs Op _rhs); \
|
||||
} \
|
||||
#define FEX_DEF_ENUM_CLASS_BIN_OP(Enum, Op) \
|
||||
[[maybe_unused]] static constexpr Enum operator Op(Enum lhs, Enum rhs) { \
|
||||
using Type = std::underlying_type_t<Enum>; \
|
||||
Type _lhs = static_cast<Type>(lhs); \
|
||||
Type _rhs = static_cast<Type>(rhs); \
|
||||
return static_cast<Enum>(_lhs Op _rhs); \
|
||||
} \
|
||||
[[maybe_unused]] static constexpr uint64_t operator Op(uint64_t lhs, Enum rhs) { \
|
||||
using Type = std::underlying_type_t<Enum>; \
|
||||
Type _rhs = static_cast<Type>(rhs); \
|
||||
return lhs Op _rhs; \
|
||||
using Type = std::underlying_type_t<Enum>; \
|
||||
Type _rhs = static_cast<Type>(rhs); \
|
||||
return lhs Op _rhs; \
|
||||
}
|
||||
|
||||
#define FEX_DEF_ENUM_CLASS_UNARY_OP(Enum, Op) \
|
||||
#define FEX_DEF_ENUM_CLASS_UNARY_OP(Enum, Op) \
|
||||
[[maybe_unused]] static constexpr Enum operator Op(Enum rhs) { \
|
||||
using Type = std::underlying_type_t<Enum>; \
|
||||
Type _rhs = static_cast<Type>(rhs); \
|
||||
return static_cast<Enum>(Op _rhs); \
|
||||
using Type = std::underlying_type_t<Enum>; \
|
||||
Type _rhs = static_cast<Type>(rhs); \
|
||||
return static_cast<Enum>(Op _rhs); \
|
||||
}
|
||||
|
||||
#define FEX_DEF_NUM_OPS(Enum) \
|
||||
#define FEX_DEF_NUM_OPS(Enum) \
|
||||
FEX_DEF_ENUM_CLASS_BIN_OP(Enum, |) \
|
||||
FEX_DEF_ENUM_CLASS_BIN_OP(Enum, &) \
|
||||
FEX_DEF_ENUM_CLASS_BIN_OP(Enum, ^) \
|
||||
|
@ -10,52 +10,52 @@ namespace FEXCore {
|
||||
// Macro that defines all of the built in operators for conveniently using
|
||||
// enum classes as flag types without needing to define all of the basic
|
||||
// boilerplate.
|
||||
#define FEX_DECLARE_ENUM_FLAG_OPERATORS(type) \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator|(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
#define FEX_DECLARE_ENUM_FLAG_OPERATORS(type) \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator|(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) | static_cast<T>(b)); \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator&(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator&(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) & static_cast<T>(b)); \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator^(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator^(type a, type b) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(static_cast<T>(a) ^ static_cast<T>(b)); \
|
||||
} \
|
||||
constexpr type& operator|=(type& a, type b) noexcept { \
|
||||
a = a | b; \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type& operator&=(type& a, type b) noexcept { \
|
||||
a = a & b; \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type& operator^=(type& a, type b) noexcept { \
|
||||
a = a ^ b; \
|
||||
return a; \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator~(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(~static_cast<T>(key)); \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr bool True(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<T>(key) != 0; \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr bool False(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<T>(key) == 0; \
|
||||
} \
|
||||
constexpr type& operator|=(type& a, type b) noexcept { \
|
||||
a = a | b; \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type& operator&=(type& a, type b) noexcept { \
|
||||
a = a & b; \
|
||||
return a; \
|
||||
} \
|
||||
constexpr type& operator^=(type& a, type b) noexcept { \
|
||||
a = a ^ b; \
|
||||
return a; \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr type \
|
||||
operator~(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<type>(~static_cast<T>(key)); \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr bool True(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<T>(key) != 0; \
|
||||
} \
|
||||
[[nodiscard]] \
|
||||
constexpr bool False(type key) noexcept { \
|
||||
using T = std::underlying_type_t<type>; \
|
||||
return static_cast<T>(key) == 0; \
|
||||
}
|
||||
|
||||
// Equivalent to C++23's std::to_underlying.
|
||||
|
@ -63,25 +63,25 @@ namespace Throw {
|
||||
MFmt(fmt, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
#define LOGMAN_THROW_A_FMT(pred, ...) \
|
||||
do { \
|
||||
#define LOGMAN_THROW_A_FMT(pred, ...) \
|
||||
do { \
|
||||
LogMan::Throw::AFmt(pred, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define LOGMAN_THROW_AA_FMT(pred, ...) \
|
||||
do { \
|
||||
#define LOGMAN_THROW_AA_FMT(pred, ...) \
|
||||
do { \
|
||||
LogMan::Throw::AFmt(pred, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
static inline void AFmt(bool, const char*, ...) {}
|
||||
#define LOGMAN_THROW_A_FMT(pred, ...) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
static inline void AAFmt(bool pred, const char*, ...) {
|
||||
__builtin_assume(pred);
|
||||
}
|
||||
#define LOGMAN_THROW_AA_FMT(pred, ...) \
|
||||
do { \
|
||||
__builtin_assume(pred); \
|
||||
do { \
|
||||
__builtin_assume(pred); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
@ -144,31 +144,31 @@ namespace Msg {
|
||||
MFmtImpl(ASSERT, fmt, fmt::make_format_args(args...));
|
||||
FEX_TRAP_EXECUTION;
|
||||
}
|
||||
#define LOGMAN_MSG_A_FMT(...) \
|
||||
do { \
|
||||
#define LOGMAN_MSG_A_FMT(...) \
|
||||
do { \
|
||||
LogMan::Msg::AFmt(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
template<typename... Args>
|
||||
static inline void AFmt(const char*, const Args&...) {}
|
||||
#define LOGMAN_MSG_A_FMT(...) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define WARN_ONCE_FMT(...) \
|
||||
do { \
|
||||
static bool Warned {}; \
|
||||
if (!Warned) { \
|
||||
#define WARN_ONCE_FMT(...) \
|
||||
do { \
|
||||
static bool Warned {}; \
|
||||
if (!Warned) { \
|
||||
LogMan::Msg::DFmt(__VA_ARGS__); \
|
||||
Warned = true; \
|
||||
} \
|
||||
Warned = true; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define ERROR_AND_DIE_FMT(...) \
|
||||
do { \
|
||||
#define ERROR_AND_DIE_FMT(...) \
|
||||
do { \
|
||||
LogMan::Msg::EFmt(__VA_ARGS__); \
|
||||
FEX_TRAP_EXECUTION; \
|
||||
FEX_TRAP_EXECUTION; \
|
||||
} while (0)
|
||||
|
||||
} // namespace Msg
|
||||
|
@ -54,10 +54,10 @@ static void TraceObject(std::string_view const Format) {}
|
||||
static void TraceObject(std::string_view const, uint64_t) {}
|
||||
|
||||
#define FEXCORE_PROFILE_INSTANT(...) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#define FEXCORE_PROFILE_SCOPED(...) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
} // namespace FEXCore::Profiler
|
||||
|
@ -92,16 +92,16 @@ static inline void Shutdown(const fextl::string& ApplicationName) {}
|
||||
#define FEXCORE_TELEMETRY_STATIC_INIT(Name, Type)
|
||||
#define FEXCORE_TELEMETRY_INIT(Name, Type)
|
||||
#define FEXCORE_TELEMETRY(Name, Value) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#define FEXCORE_TELEMETRY_SET(Name, Value) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#define FEXCORE_TELEMETRY_OR(Name, Value) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#define FEXCORE_TELEMETRY_INC(Name) \
|
||||
do { \
|
||||
do { \
|
||||
} while (0)
|
||||
#define FEXCORE_TELEMETRY_Addr(Name) reinterpret_cast<std::atomic<uint64_t>*>(nullptr)
|
||||
#endif
|
||||
|
@ -105,17 +105,17 @@ bool OpenFile(fextl::string Filename, bool LoadDefault = false) {
|
||||
LoadedConfig->Load();
|
||||
|
||||
// Load default options and only overwrite only if the option didn't exist
|
||||
#define OPT_BASE(type, group, enum, json, default) \
|
||||
if (!LoadedConfig->OptionExists(FEXCore::Config::ConfigOption::CONFIG_##enum)) { \
|
||||
#define OPT_BASE(type, group, enum, json, default) \
|
||||
if (!LoadedConfig->OptionExists(FEXCore::Config::ConfigOption::CONFIG_##enum)) { \
|
||||
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_##enum, std::to_string(default)); \
|
||||
}
|
||||
#define OPT_STR(group, enum, json, default) \
|
||||
#define OPT_STR(group, enum, json, default) \
|
||||
if (!LoadedConfig->OptionExists(FEXCore::Config::ConfigOption::CONFIG_##enum)) { \
|
||||
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_##enum, default); \
|
||||
}
|
||||
#define OPT_STRARRAY(group, enum, json, default) // Do nothing
|
||||
#define OPT_STRENUM(group, enum, json, default) \
|
||||
if (!LoadedConfig->OptionExists(FEXCore::Config::ConfigOption::CONFIG_##enum)) { \
|
||||
#define OPT_STRENUM(group, enum, json, default) \
|
||||
if (!LoadedConfig->OptionExists(FEXCore::Config::ConfigOption::CONFIG_##enum)) { \
|
||||
LoadedConfig->EraseSet(FEXCore::Config::ConfigOption::CONFIG_##enum, std::to_string(FEXCore::ToUnderlying(default))); \
|
||||
}
|
||||
#include <FEXCore/Config/ConfigValues.inl>
|
||||
|
@ -124,8 +124,8 @@ fextl::string GenerateCPUInfo(FEXCore::Context::Context* ctx, uint32_t CPUCores)
|
||||
// Generate the flags data up front
|
||||
// This is the same per core
|
||||
{
|
||||
#define FLAG(flag, name) \
|
||||
if (flag) { \
|
||||
#define FLAG(flag, name) \
|
||||
if (flag) { \
|
||||
flags_data << name << " "; \
|
||||
}
|
||||
FLAG(res_1.edx & (1 << 0), "fpu")
|
||||
|
@ -393,15 +393,15 @@ private:
|
||||
|
||||
uint64_t HandleSyscall(SyscallHandler* Handler, FEXCore::Core::CpuStateFrame* Frame, FEXCore::HLE::SyscallArguments* Args);
|
||||
|
||||
#define SYSCALL_ERRNO() \
|
||||
do { \
|
||||
#define SYSCALL_ERRNO() \
|
||||
do { \
|
||||
if (Result == -1) return -errno; \
|
||||
return Result; \
|
||||
return Result; \
|
||||
} while (0)
|
||||
#define SYSCALL_ERRNO_NULL() \
|
||||
do { \
|
||||
#define SYSCALL_ERRNO_NULL() \
|
||||
do { \
|
||||
if (Result == 0) return -errno; \
|
||||
return Result; \
|
||||
return Result; \
|
||||
} while (0)
|
||||
|
||||
extern FEX::HLE::SyscallHandler* _SyscallHandler;
|
||||
@ -414,9 +414,9 @@ extern FEX::HLE::SyscallHandler* _SyscallHandler;
|
||||
template<typename T>
|
||||
struct ArgToFmtString;
|
||||
|
||||
#define ARG_TO_STR(tpy, str) \
|
||||
template<> \
|
||||
struct FEX::HLE::ArgToFmtString<tpy> { \
|
||||
#define ARG_TO_STR(tpy, str) \
|
||||
template<> \
|
||||
struct FEX::HLE::ArgToFmtString<tpy> { \
|
||||
inline static const char* const Format = str; \
|
||||
};
|
||||
|
||||
@ -614,8 +614,8 @@ namespace FaultSafeMemcpy {
|
||||
|
||||
#define REGISTER_SYSCALL_IMPL_PASS_FLAGS(name, flags, lambda) REGISTER_SYSCALL_IMPL_INTERNAL(name, SYSCALL_DEF(name), flags, lambda)
|
||||
|
||||
#define REGISTER_SYSCALL_IMPL_INTERNAL(name, number, flags, lambda) \
|
||||
do { \
|
||||
#define REGISTER_SYSCALL_IMPL_INTERNAL(name, number, flags, lambda) \
|
||||
do { \
|
||||
FEX::HLE::x64::RegisterSyscall(Handler, FEX::HLE::x64::SYSCALL_x64_##name, (number), (flags), #name, (lambda)); \
|
||||
FEX::HLE::x32::RegisterSyscall(Handler, FEX::HLE::x32::SYSCALL_x86_##name, (number), (flags), #name, (lambda)); \
|
||||
} while (false)
|
||||
|
@ -13,10 +13,10 @@ $end_info$
|
||||
#include <stdint.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#define REGISTER_SYSCALL_NOT_IMPL(name) \
|
||||
#define REGISTER_SYSCALL_NOT_IMPL(name) \
|
||||
REGISTER_SYSCALL_IMPL(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \
|
||||
LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \
|
||||
return -ENOSYS; \
|
||||
LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \
|
||||
return -ENOSYS; \
|
||||
});
|
||||
|
||||
#define REGISTER_SYSCALL_NO_PERM(name) REGISTER_SYSCALL_IMPL(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { return -EPERM; });
|
||||
|
@ -15,10 +15,10 @@ $end_info$
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define SYSCALL_STUB(name) \
|
||||
do { \
|
||||
#define SYSCALL_STUB(name) \
|
||||
do { \
|
||||
ERROR_AND_DIE_FMT("Syscall: " #name " stub!"); \
|
||||
return -ENOSYS; \
|
||||
return -ENOSYS; \
|
||||
} while (0)
|
||||
|
||||
namespace FEXCore::Core {
|
||||
|
@ -10,14 +10,14 @@
|
||||
#ifndef _BASIC_META
|
||||
// Meta typedef variable in unnamed and matches upstream
|
||||
// Use this for the super basic ioctl passthrough path
|
||||
#define _BASIC_META(x) \
|
||||
#define _BASIC_META(x) \
|
||||
__attribute__((annotate("fex-match"))) \
|
||||
__attribute__((annotate("ioctl-alias-x86_32-_" #x STRINGY1(__LINE__)))) typedef uint8_t STRINGY(_##x, __LINE__)[x];
|
||||
#endif
|
||||
|
||||
#ifndef _BASIC_META_VAR
|
||||
// This is similar to _BASIC_META except that it allows you to pass variadic arguments to the original ioctl definition
|
||||
#define _BASIC_META_VAR(x, args...) \
|
||||
#define _BASIC_META_VAR(x, args...) \
|
||||
__attribute__((annotate("fex-match"))) \
|
||||
__attribute__((annotate("ioctl-alias-x86_32-_" #x STRINGY1(__LINE__)))) typedef uint8_t STRINGY(_##x, __LINE__)[x(args)];
|
||||
#endif
|
||||
@ -27,8 +27,8 @@
|
||||
// Generates a FEX_<name> version of the ioctl with custom ioctl definition
|
||||
// eg: _CUSTOM_META(DRM_IOCTL_AMDGPU_GEM_METADATA, DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, FEX::HLE::x32::AMDGPU::fex_drm_amdgpu_gem_metadata));
|
||||
// Allows you to effectively pass in the original ioctl definition with custom type replacing the upstream type
|
||||
#define _CUSTOM_META(name, ioctl_num) \
|
||||
typedef uint8_t _meta_##name[name]; \
|
||||
#define _CUSTOM_META(name, ioctl_num) \
|
||||
typedef uint8_t _meta_##name[name]; \
|
||||
__attribute__((annotate("ioctl-alias-x86_32-_meta_" #name))) typedef uint8_t _##name[ioctl_num]; \
|
||||
constexpr static uint32_t FEX_##name = ioctl_num;
|
||||
#endif
|
||||
@ -36,8 +36,8 @@
|
||||
#ifndef _CUSTOM_META_OFFSET
|
||||
// Same as _CUSTOM_META but allows you to define multiple types from an offset
|
||||
// Required to have an ioctl covering a range which some ioctls do
|
||||
#define _CUSTOM_META_OFFSET(name, ioctl_num, offset) \
|
||||
typedef uint8_t _meta_##name[ioctl_num + offset]; \
|
||||
#define _CUSTOM_META_OFFSET(name, ioctl_num, offset) \
|
||||
typedef uint8_t _meta_##name[ioctl_num + offset]; \
|
||||
__attribute__((annotate("ioctl-alias-x86_32-_meta_" #name))) typedef uint8_t _##name[ioctl_num + offset]; \
|
||||
constexpr static uint32_t FEX_##name = ioctl_num + offset;
|
||||
#endif
|
||||
|
@ -379,16 +379,16 @@ namespace DRM {
|
||||
}
|
||||
|
||||
uint32_t I915_Handler(int fd, uint32_t cmd, uint32_t args) {
|
||||
#define SIMPLE(enum, type) \
|
||||
case _IOC_NR(FEX_##enum): { \
|
||||
#define SIMPLE(enum, type) \
|
||||
case _IOC_NR(FEX_##enum): { \
|
||||
I915::fex_##type* guest = reinterpret_cast<I915::fex_##type*>(args); \
|
||||
type host = *guest; \
|
||||
uint64_t Result = ::ioctl(fd, enum, &host); \
|
||||
if (Result != -1) { \
|
||||
*guest = host; \
|
||||
} \
|
||||
SYSCALL_ERRNO(); \
|
||||
break; \
|
||||
type host = *guest; \
|
||||
uint64_t Result = ::ioctl(fd, enum, &host); \
|
||||
if (Result != -1) { \
|
||||
*guest = host; \
|
||||
} \
|
||||
SYSCALL_ERRNO(); \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
@ -606,16 +606,16 @@ namespace DRM {
|
||||
}
|
||||
|
||||
uint32_t Handler(int fd, uint32_t cmd, uint32_t args) {
|
||||
#define SIMPLE(enum, type) \
|
||||
case _IOC_NR(FEX_##enum): { \
|
||||
#define SIMPLE(enum, type) \
|
||||
case _IOC_NR(FEX_##enum): { \
|
||||
DRM::fex_##type* guest = reinterpret_cast<DRM::fex_##type*>(args); \
|
||||
type host = *guest; \
|
||||
uint64_t Result = ::ioctl(fd, enum, &host); \
|
||||
if (Result != -1) { \
|
||||
*guest = host; \
|
||||
} \
|
||||
SYSCALL_ERRNO(); \
|
||||
break; \
|
||||
type host = *guest; \
|
||||
uint64_t Result = ::ioctl(fd, enum, &host); \
|
||||
if (Result != -1) { \
|
||||
*guest = host; \
|
||||
} \
|
||||
SYSCALL_ERRNO(); \
|
||||
break; \
|
||||
}
|
||||
|
||||
switch (_IOC_NR(cmd)) {
|
||||
|
@ -16,10 +16,10 @@ struct CpuStateFrame;
|
||||
}
|
||||
|
||||
namespace FEX::HLE::x32 {
|
||||
#define REGISTER_SYSCALL_NOT_IMPL_X32(name) \
|
||||
#define REGISTER_SYSCALL_NOT_IMPL_X32(name) \
|
||||
REGISTER_SYSCALL_IMPL_X32(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \
|
||||
LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \
|
||||
return -ENOSYS; \
|
||||
LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \
|
||||
return -ENOSYS; \
|
||||
});
|
||||
#define REGISTER_SYSCALL_NO_PERM_X32(name) \
|
||||
REGISTER_SYSCALL_IMPL_X32(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { return -EPERM; });
|
||||
|
@ -14,10 +14,10 @@ $end_info$
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define SYSCALL_STUB(name) \
|
||||
do { \
|
||||
#define SYSCALL_STUB(name) \
|
||||
do { \
|
||||
ERROR_AND_DIE_FMT("Syscall: " #name " stub!"); \
|
||||
return -ENOSYS; \
|
||||
return -ENOSYS; \
|
||||
} while (0)
|
||||
|
||||
namespace FEXCore::Core {
|
||||
|
@ -124,7 +124,7 @@ void RegisterSyscall(SyscallHandler* _Handler, int num, int32_t HostSyscallNumbe
|
||||
#define REGISTER_SYSCALL_IMPL_X32_PASS_MANUAL_FLAGS(name, hostname, flags, lambda) \
|
||||
REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, SYSCALL_DEF(hostname), flags, lambda)
|
||||
|
||||
#define REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, number, flags, lambda) \
|
||||
do { \
|
||||
#define REGISTER_SYSCALL_IMPL_X32_INTERNAL(name, number, flags, lambda) \
|
||||
do { \
|
||||
FEX::HLE::x32::RegisterSyscall(Handler, x32::SYSCALL_x86_##name, number, flags, #name, lambda); \
|
||||
} while (false)
|
||||
|
@ -10,14 +10,14 @@
|
||||
#ifndef _BASIC_META
|
||||
// Meta typedef variable in unnamed and matches upstream
|
||||
// Use this for the super basic ioctl passthrough path
|
||||
#define _BASIC_META(x) \
|
||||
#define _BASIC_META(x) \
|
||||
__attribute__((annotate("fex-match"))) \
|
||||
__attribute__((annotate("ioctl-alias-x86_64-_" #x STRINGY1(__LINE__)))) typedef uint8_t STRINGY(_##x, __LINE__)[x];
|
||||
#endif
|
||||
|
||||
#ifndef _BASIC_META_VAR
|
||||
// This is similar to _BASIC_META except that it allows you to pass variadic arguments to the original ioctl definition
|
||||
#define _BASIC_META_VAR(x, args...) \
|
||||
#define _BASIC_META_VAR(x, args...) \
|
||||
__attribute__((annotate("fex-match"))) \
|
||||
__attribute__((annotate("ioctl-alias-x86_64-_" #x STRINGY1(__LINE__)))) typedef uint8_t STRINGY(_##x, __LINE__)[x(args)];
|
||||
#endif
|
||||
@ -27,8 +27,8 @@
|
||||
// Generates a FEX_<name> version of the ioctl with custom ioctl definition
|
||||
// eg: _CUSTOM_META(DRM_IOCTL_AMDGPU_GEM_METADATA, DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, FEX::HLE::x64::AMDGPU::fex_drm_amdgpu_gem_metadata));
|
||||
// Allows you to effectively pass in the original ioctl definition with custom type replacing the upstream type
|
||||
#define _CUSTOM_META(name, ioctl_num) \
|
||||
typedef uint8_t _meta_##name[name]; \
|
||||
#define _CUSTOM_META(name, ioctl_num) \
|
||||
typedef uint8_t _meta_##name[name]; \
|
||||
__attribute__((annotate("ioctl-alias-x86_64-_meta_" #name))) typedef uint8_t _##name[ioctl_num]; \
|
||||
constexpr static uint32_t FEX_##name = ioctl_num;
|
||||
#endif
|
||||
@ -38,8 +38,8 @@
|
||||
// Generates a FEX_<name> version of the ioctl with custom ioctl definition
|
||||
// eg: _CUSTOM_META(DRM_IOCTL_AMDGPU_GEM_METADATA, DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_METADATA, FEX::HLE::x64::AMDGPU::fex_drm_amdgpu_gem_metadata));
|
||||
// Allows you to effectively pass in the original ioctl definition with custom type replacing the upstream type
|
||||
#define _CUSTOM_META_MATCH(name, ioctl_num) \
|
||||
typedef uint8_t _meta_##name[ioctl_num]; \
|
||||
#define _CUSTOM_META_MATCH(name, ioctl_num) \
|
||||
typedef uint8_t _meta_##name[ioctl_num]; \
|
||||
__attribute__((annotate("fex-match"))) typedef uint8_t _##name[ioctl_num]; \
|
||||
constexpr static uint32_t FEX_##name = ioctl_num;
|
||||
#endif
|
||||
@ -47,8 +47,8 @@
|
||||
#ifndef _CUSTOM_META_OFFSET
|
||||
// Same as _CUSTOM_META but allows you to define multiple types from an offset
|
||||
// Required to have an ioctl covering a range which some ioctls do
|
||||
#define _CUSTOM_META_OFFSET(name, ioctl_num, offset) \
|
||||
typedef uint8_t _meta_##name[ioctl_num + offset]; \
|
||||
#define _CUSTOM_META_OFFSET(name, ioctl_num, offset) \
|
||||
typedef uint8_t _meta_##name[ioctl_num + offset]; \
|
||||
__attribute__((annotate("ioctl-alias-x86_64-_meta_" #name))) typedef uint8_t _##name[ioctl_num + offset]; \
|
||||
constexpr static uint32_t FEX_##name = ioctl_num + offset;
|
||||
#endif
|
||||
|
@ -17,10 +17,10 @@ struct CpuStateFrame;
|
||||
}
|
||||
|
||||
namespace FEX::HLE::x64 {
|
||||
#define REGISTER_SYSCALL_NOT_IMPL_X64(name) \
|
||||
#define REGISTER_SYSCALL_NOT_IMPL_X64(name) \
|
||||
REGISTER_SYSCALL_IMPL_X64(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { \
|
||||
LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \
|
||||
return -ENOSYS; \
|
||||
LogMan::Msg::DFmt("Using deprecated/removed syscall: " #name); \
|
||||
return -ENOSYS; \
|
||||
});
|
||||
#define REGISTER_SYSCALL_NO_PERM_X64(name) \
|
||||
REGISTER_SYSCALL_IMPL_X64(name, [](FEXCore::Core::CpuStateFrame* Frame) -> uint64_t { return -EPERM; });
|
||||
|
@ -112,7 +112,7 @@ void RegisterSyscall(SyscallHandler* _Handler, int num, int32_t HostSyscallNumbe
|
||||
|
||||
#define REGISTER_SYSCALL_IMPL_X64_PASS_FLAGS(name, flags, lambda) REGISTER_SYSCALL_IMPL_X64_INTERNAL(name, SYSCALL_DEF(name), flags, lambda)
|
||||
|
||||
#define REGISTER_SYSCALL_IMPL_X64_INTERNAL(name, number, flags, lambda) \
|
||||
do { \
|
||||
#define REGISTER_SYSCALL_IMPL_X64_INTERNAL(name, number, flags, lambda) \
|
||||
do { \
|
||||
FEX::HLE::x64::RegisterSyscall(Handler, x64::SYSCALL_x64_##name, (number), (flags), #name, (lambda)); \
|
||||
} while (false)
|
||||
|
@ -18,28 +18,28 @@ template<typename signature>
|
||||
THUNK_ABI const int (*fexthunks_invoke_callback)(void*);
|
||||
|
||||
#ifndef _M_ARM_64
|
||||
#define MAKE_THUNK(lib, name, hash) \
|
||||
#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);
|
||||
|
||||
#define MAKE_CALLBACK_THUNK(name, signature, hash) \
|
||||
#define MAKE_CALLBACK_THUNK(name, signature, hash) \
|
||||
extern "C" __attribute__((visibility("hidden"))) THUNK_ABI int fexthunks_##name(void* args); \
|
||||
asm(".text\nfexthunks_" #name ":\n.byte 0xF, 0x3F\n.byte " hash); \
|
||||
template<> \
|
||||
asm(".text\nfexthunks_" #name ":\n.byte 0xF, 0x3F\n.byte " hash); \
|
||||
template<> \
|
||||
THUNK_ABI inline constexpr int (*fexthunks_invoke_callback<signature>)(void*) = fexthunks_##name;
|
||||
|
||||
#else
|
||||
// We're compiling for IDE integration, so provide a dummy-implementation that just calls an undefined function.
|
||||
// The name of that function serves as an error message if this library somehow gets loaded at runtime.
|
||||
extern "C" void BROKEN_INSTALL___TRIED_LOADING_AARCH64_BUILD_OF_GUEST_THUNK();
|
||||
#define MAKE_THUNK(lib, name, hash) \
|
||||
extern "C" int fexthunks_##lib##_##name(void* args) { \
|
||||
#define MAKE_THUNK(lib, name, hash) \
|
||||
extern "C" int fexthunks_##lib##_##name(void* args) { \
|
||||
BROKEN_INSTALL___TRIED_LOADING_AARCH64_BUILD_OF_GUEST_THUNK(); \
|
||||
return 0; \
|
||||
return 0; \
|
||||
}
|
||||
#define MAKE_CALLBACK_THUNK(name, signature, hash) \
|
||||
extern "C" int fexthunks_##name(void* args); \
|
||||
template<> \
|
||||
extern "C" int fexthunks_##name(void* args); \
|
||||
template<> \
|
||||
inline constexpr int (*fexthunks_invoke_callback<signature>)(void*) = fexthunks_##name;
|
||||
#endif
|
||||
|
||||
@ -73,11 +73,11 @@ MAKE_THUNK(fex, allocate_host_trampoline_for_guest_function,
|
||||
"0x9b, 0xb2, 0xf4, 0xb4, 0x83, 0x7d, 0x28, 0x93, 0x40, 0xcb, 0xf4, 0x7a, 0x0b, 0x47, 0x85, 0x87, 0xf9, 0xbc, 0xb5, 0x27, 0xca, "
|
||||
"0xa6, 0x93, 0xa5, 0xc0, 0x73, 0x27, 0x24, 0xae, 0xc8, 0xb8, 0x5a")
|
||||
|
||||
#define LOAD_LIB_BASE(name, init_fn) \
|
||||
#define LOAD_LIB_BASE(name, init_fn) \
|
||||
__attribute__((constructor)) static void loadlib() { \
|
||||
LoadlibArgs args = {#name}; \
|
||||
fexthunks_fex_loadlib(&args); \
|
||||
if ((init_fn)) ((void (*)())init_fn)(); \
|
||||
LoadlibArgs args = {#name}; \
|
||||
fexthunks_fex_loadlib(&args); \
|
||||
if ((init_fn)) ((void (*)())init_fn)(); \
|
||||
}
|
||||
|
||||
#define LOAD_LIB(name) LOAD_LIB_BASE(name, nullptr)
|
||||
|
@ -53,19 +53,19 @@ struct ExportEntry {
|
||||
|
||||
typedef void fex_call_callback_t(uintptr_t callback, void* arg0, void* arg1);
|
||||
|
||||
#define EXPORTS(name) \
|
||||
extern "C" { \
|
||||
#define EXPORTS(name) \
|
||||
extern "C" { \
|
||||
ExportEntry* fexthunks_exports_##name() { \
|
||||
if (!fexldr_init_##name()) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
return exports; \
|
||||
} \
|
||||
if (!fexldr_init_##name()) { \
|
||||
return nullptr; \
|
||||
} \
|
||||
return exports; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOAD_LIB_INIT(init_fn) \
|
||||
#define LOAD_LIB_INIT(init_fn) \
|
||||
__attribute__((constructor)) static void loadlib() { \
|
||||
init_fn(); \
|
||||
init_fn(); \
|
||||
}
|
||||
|
||||
struct GuestcallInfo {
|
||||
|
@ -19,40 +19,40 @@ enum trapno {
|
||||
};
|
||||
|
||||
#define CONCAT(x, y) x##y
|
||||
#define TestSymbols(num) \
|
||||
#define TestSymbols(num) \
|
||||
extern "C" uint64_t CONCAT(TestBegin_, num); \
|
||||
extern "C" uint64_t CONCAT(TestEnd_, num);
|
||||
|
||||
#define Test(num, asm, trapno, errno, si_code, signal) \
|
||||
#define Test(num, asm, trapno, errno, si_code, signal) \
|
||||
capturing_handler_skip = (unsigned long)&CONCAT(TestEnd_, num) - (unsigned long)&CONCAT(TestBegin_, num); \
|
||||
const unsigned long EXPECTED_RIP = (unsigned long)&CONCAT(TestBegin_, num); \
|
||||
const int EXPECTED_TRAPNO = trapno; \
|
||||
const int EXPECTED_ERR = errno; \
|
||||
const int EXPECTED_SI_CODE = si_code; \
|
||||
const int EXPECTED_SIGNAL = signal; \
|
||||
__asm volatile("TestBegin_" #num ":" asm ";" \
|
||||
"TestEnd_" #num ":" :: \
|
||||
const unsigned long EXPECTED_RIP = (unsigned long)&CONCAT(TestBegin_, num); \
|
||||
const int EXPECTED_TRAPNO = trapno; \
|
||||
const int EXPECTED_ERR = errno; \
|
||||
const int EXPECTED_SI_CODE = si_code; \
|
||||
const int EXPECTED_SIGNAL = signal; \
|
||||
__asm volatile("TestBegin_" #num ":" asm ";" \
|
||||
"TestEnd_" #num ":" :: \
|
||||
: "memory");
|
||||
|
||||
|
||||
#define TEST(num, name, asm, trapno, errno, _si_code, _signal) \
|
||||
TestSymbols(num); \
|
||||
TEST_CASE("Signals: " #name) { \
|
||||
struct sigaction act {}; \
|
||||
act.sa_sigaction = CapturingHandler; \
|
||||
act.sa_flags = SA_SIGINFO; \
|
||||
sigaction(SIGSEGV, &act, nullptr); \
|
||||
sigaction(SIGTRAP, &act, nullptr); \
|
||||
sigaction(SIGILL, &act, nullptr); \
|
||||
\
|
||||
Test(num, asm, trapno, errno, _si_code, _signal); \
|
||||
\
|
||||
REQUIRE(from_handler.has_value()); \
|
||||
CHECK(from_handler->mctx.gregs[REG_RIP] == EXPECTED_RIP); \
|
||||
#define TEST(num, name, asm, trapno, errno, _si_code, _signal) \
|
||||
TestSymbols(num); \
|
||||
TEST_CASE("Signals: " #name) { \
|
||||
struct sigaction act {}; \
|
||||
act.sa_sigaction = CapturingHandler; \
|
||||
act.sa_flags = SA_SIGINFO; \
|
||||
sigaction(SIGSEGV, &act, nullptr); \
|
||||
sigaction(SIGTRAP, &act, nullptr); \
|
||||
sigaction(SIGILL, &act, nullptr); \
|
||||
\
|
||||
Test(num, asm, trapno, errno, _si_code, _signal); \
|
||||
\
|
||||
REQUIRE(from_handler.has_value()); \
|
||||
CHECK(from_handler->mctx.gregs[REG_RIP] == EXPECTED_RIP); \
|
||||
CHECK(from_handler->mctx.gregs[REG_TRAPNO] == EXPECTED_TRAPNO); \
|
||||
CHECK(from_handler->mctx.gregs[REG_ERR] == EXPECTED_ERR); \
|
||||
CHECK(from_handler->si_code == EXPECTED_SI_CODE); \
|
||||
CHECK(from_handler->signal == EXPECTED_SIGNAL); \
|
||||
CHECK(from_handler->mctx.gregs[REG_ERR] == EXPECTED_ERR); \
|
||||
CHECK(from_handler->si_code == EXPECTED_SI_CODE); \
|
||||
CHECK(from_handler->signal == EXPECTED_SIGNAL); \
|
||||
}
|
||||
|
||||
// Instructions that explicitly are supported but must only work in CPL-0
|
||||
|
@ -9,27 +9,27 @@
|
||||
#include <linux/futex.h>
|
||||
|
||||
#if __SIZEOF_POINTER__ == 4
|
||||
#define DO_ASM(x, y) \
|
||||
#define DO_ASM(x, y) \
|
||||
__asm volatile(x /* Need to late move syscall number since incoming asm will overwrite eax */ \
|
||||
" mov eax, %[Syscall];" /* Notify we are ready (Without touching flags) */ \
|
||||
"mov dword ptr [%[ReadyNotify]], 1;" /* Do a futex */ \
|
||||
"int 0x80;" y \
|
||||
: \
|
||||
: [Syscall] "i"(SYS_futex), "b"(Futex), "c"(FUTEX_WAIT), "d"(0), "S"(0), [ReadyNotify] "r"(ReadyNotify) \
|
||||
" mov eax, %[Syscall];" /* Notify we are ready (Without touching flags) */ \
|
||||
"mov dword ptr [%[ReadyNotify]], 1;" /* Do a futex */ \
|
||||
"int 0x80;" y \
|
||||
: \
|
||||
: [Syscall] "i"(SYS_futex), "b"(Futex), "c"(FUTEX_WAIT), "d"(0), "S"(0), [ReadyNotify] "r"(ReadyNotify) \
|
||||
: "cc", "memory", "eax")
|
||||
#else
|
||||
|
||||
#define DO_ASM(x, y) \
|
||||
__asm volatile( \
|
||||
x /* Do a futex */ \
|
||||
" mov rax, %[Syscall];" \
|
||||
" mov rdi, %[FutexAddr];" \
|
||||
" mov rsi, %[FutexOp];" \
|
||||
" mov rdx, %[ExpectedValue];" \
|
||||
" mov r10, %[TimeoutAddr];" /* Notify we are ready (Without touching flags) */ \
|
||||
"mov dword ptr [%[ReadyNotify]], 1;" \
|
||||
"syscall;" y \
|
||||
: \
|
||||
#define DO_ASM(x, y) \
|
||||
__asm volatile( \
|
||||
x /* Do a futex */ \
|
||||
" mov rax, %[Syscall];" \
|
||||
" mov rdi, %[FutexAddr];" \
|
||||
" mov rsi, %[FutexOp];" \
|
||||
" mov rdx, %[ExpectedValue];" \
|
||||
" mov r10, %[TimeoutAddr];" /* Notify we are ready (Without touching flags) */ \
|
||||
"mov dword ptr [%[ReadyNotify]], 1;" \
|
||||
"syscall;" y \
|
||||
: \
|
||||
: [Syscall] "i"(SYS_futex), [FutexAddr] "r"(Futex), [FutexOp] "i"(FUTEX_WAIT), [ExpectedValue] "i"(0), [TimeoutAddr] "i"(0), [ReadyNotify] "r"(ReadyNotify) \
|
||||
: "cc", "memory", "rax", "rdi", "rsi", "rdx", "r10")
|
||||
#endif
|
||||
|
@ -21,10 +21,10 @@ void key_dtor(void* ptr) {
|
||||
}
|
||||
|
||||
#define handle_error_en(en, msg) \
|
||||
do { \
|
||||
errno = en; \
|
||||
perror(msg); \
|
||||
exit(EXIT_FAILURE); \
|
||||
do { \
|
||||
errno = en; \
|
||||
perror(msg); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static void* thread_func(void* ignored_argument) {
|
||||
|
Loading…
Reference in New Issue
Block a user