Browse Source
[xbyak] fix odr violation on MSVC
[xbyak] fix odr violation on MSVC
Signed-off-by: lizzie <lizzie@eden-emu.dev>lizzie/msvcfix1234
22 changed files with 280 additions and 308 deletions
-
277src/common/x64/xbyak.h
-
2src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/abi.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/block_of_code.h
-
2src/dynarmic/src/dynarmic/backend/x64/callback.h
-
2src/dynarmic/src/dynarmic/backend/x64/constant_pool.h
-
2src/dynarmic/src/dynarmic/backend/x64/emit_x64.h
-
2src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h
-
2src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/hostloc.h
-
2src/dynarmic/src/dynarmic/backend/x64/oparg.h
-
2src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp
-
2src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h
-
13src/dynarmic/src/dynarmic/backend/x64/xbyak.h
-
2src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp
-
2src/dynarmic/src/dynarmic/common/spin_lock_x64.h
-
2src/dynarmic/tests/x64_cpu_info.cpp
-
260src/video_core/macro.cpp
@ -1,287 +1,12 @@ |
|||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
||||
// SPDX-License-Identifier: GPL-3.0-or-later |
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
|
||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project |
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later |
|
||||
|
|
||||
#pragma once |
#pragma once |
||||
|
|
||||
#include <type_traits> |
|
||||
#include <bitset> |
|
||||
#include <initializer_list> |
|
||||
#include "common/assert.h" |
|
||||
|
|
||||
// xbyak hates human beings |
|
||||
#ifdef __GNUC__ |
|
||||
#pragma GCC diagnostic ignored "-Wconversion" |
|
||||
#pragma GCC diagnostic ignored "-Wshadow" |
|
||||
#endif |
|
||||
#ifdef __clang__ |
|
||||
#pragma clang diagnostic ignored "-Wconversion" |
|
||||
#pragma clang diagnostic ignored "-Wshadow" |
|
||||
#endif |
|
||||
|
|
||||
// You must ensure this matches with src/common/x64/xbyak.h on root dir |
// You must ensure this matches with src/common/x64/xbyak.h on root dir |
||||
#include <ankerl/unordered_dense.h> |
#include <ankerl/unordered_dense.h> |
||||
#include <boost/unordered_map.hpp> |
|
||||
#define XBYAK_STD_UNORDERED_SET ankerl::unordered_dense::set |
#define XBYAK_STD_UNORDERED_SET ankerl::unordered_dense::set |
||||
#define XBYAK_STD_UNORDERED_MAP ankerl::unordered_dense::map |
#define XBYAK_STD_UNORDERED_MAP ankerl::unordered_dense::map |
||||
#define XBYAK_STD_UNORDERED_MULTIMAP boost::unordered_multimap |
|
||||
|
#define XBYAK_STD_UNORDERED_MULTIMAP std::multimap |
||||
#include <xbyak/xbyak.h> |
#include <xbyak/xbyak.h> |
||||
#include <xbyak/xbyak_util.h> |
#include <xbyak/xbyak_util.h> |
||||
|
|
||||
#include <xbyak/xbyak.h> |
|
||||
|
|
||||
namespace Common::X64 { |
|
||||
|
|
||||
constexpr size_t RegToIndex(const Xbyak::Reg& reg) { |
|
||||
using Kind = Xbyak::Reg::Kind; |
|
||||
ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0, |
|
||||
"RegSet only support GPRs and XMM registers."); |
|
||||
ASSERT_MSG(reg.getIdx() < 16, "RegSet only supports XXM0-15."); |
|
||||
return static_cast<size_t>(reg.getIdx()) + (reg.getKind() == Kind::REG ? 0 : 16); |
|
||||
} |
|
||||
|
|
||||
constexpr Xbyak::Reg64 IndexToReg64(size_t reg_index) { |
|
||||
ASSERT(reg_index < 16); |
|
||||
return Xbyak::Reg64(static_cast<int>(reg_index)); |
|
||||
} |
|
||||
|
|
||||
constexpr Xbyak::Xmm IndexToXmm(size_t reg_index) { |
|
||||
ASSERT(reg_index >= 16 && reg_index < 32); |
|
||||
return Xbyak::Xmm(static_cast<int>(reg_index - 16)); |
|
||||
} |
|
||||
|
|
||||
constexpr Xbyak::Reg IndexToReg(size_t reg_index) { |
|
||||
if (reg_index < 16) { |
|
||||
return IndexToReg64(reg_index); |
|
||||
} else { |
|
||||
return IndexToXmm(reg_index); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
constexpr std::bitset<32> BuildRegSet(std::initializer_list<Xbyak::Reg> regs) { |
|
||||
size_t bits = 0; |
|
||||
for (const Xbyak::Reg& reg : regs) { |
|
||||
bits |= size_t{1} << RegToIndex(reg); |
|
||||
} |
|
||||
return {bits}; |
|
||||
} |
|
||||
|
|
||||
constexpr inline std::bitset<32> ABI_ALL_GPRS(0x0000FFFF); |
|
||||
constexpr inline std::bitset<32> ABI_ALL_XMMS(0xFFFF0000); |
|
||||
|
|
||||
constexpr inline Xbyak::Reg ABI_JIT_REG = Xbyak::util::rbx; |
|
||||
#ifdef _WIN32 |
|
||||
|
|
||||
// Microsoft x64 ABI |
|
||||
constexpr inline Xbyak::Reg ABI_RETURN = Xbyak::util::rax; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM1 = Xbyak::util::rcx; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM2 = Xbyak::util::rdx; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM3 = Xbyak::util::r8; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM4 = Xbyak::util::r9; |
|
||||
|
|
||||
constexpr inline std::bitset<32> ABI_ALL_CALLER_SAVED = BuildRegSet({ |
|
||||
// GPRs |
|
||||
Xbyak::util::rcx, |
|
||||
Xbyak::util::rdx, |
|
||||
Xbyak::util::r8, |
|
||||
Xbyak::util::r9, |
|
||||
Xbyak::util::r10, |
|
||||
Xbyak::util::r11, |
|
||||
// XMMs |
|
||||
Xbyak::util::xmm0, |
|
||||
Xbyak::util::xmm1, |
|
||||
Xbyak::util::xmm2, |
|
||||
Xbyak::util::xmm3, |
|
||||
Xbyak::util::xmm4, |
|
||||
Xbyak::util::xmm5, |
|
||||
}); |
|
||||
|
|
||||
constexpr inline std::bitset<32> ABI_ALL_CALLEE_SAVED = BuildRegSet({ |
|
||||
// GPRs |
|
||||
Xbyak::util::rbx, |
|
||||
Xbyak::util::rsi, |
|
||||
Xbyak::util::rdi, |
|
||||
Xbyak::util::rbp, |
|
||||
Xbyak::util::r12, |
|
||||
Xbyak::util::r13, |
|
||||
Xbyak::util::r14, |
|
||||
Xbyak::util::r15, |
|
||||
// XMMs |
|
||||
Xbyak::util::xmm6, |
|
||||
Xbyak::util::xmm7, |
|
||||
Xbyak::util::xmm8, |
|
||||
Xbyak::util::xmm9, |
|
||||
Xbyak::util::xmm10, |
|
||||
Xbyak::util::xmm11, |
|
||||
Xbyak::util::xmm12, |
|
||||
Xbyak::util::xmm13, |
|
||||
Xbyak::util::xmm14, |
|
||||
Xbyak::util::xmm15, |
|
||||
}); |
|
||||
|
|
||||
constexpr size_t ABI_SHADOW_SPACE = 0x20; |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
// System V x86-64 ABI |
|
||||
constexpr inline Xbyak::Reg ABI_RETURN = Xbyak::util::rax; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM1 = Xbyak::util::rdi; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM2 = Xbyak::util::rsi; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM3 = Xbyak::util::rdx; |
|
||||
constexpr inline Xbyak::Reg ABI_PARAM4 = Xbyak::util::rcx; |
|
||||
|
|
||||
constexpr inline std::bitset<32> ABI_ALL_CALLER_SAVED = BuildRegSet({ |
|
||||
// GPRs |
|
||||
Xbyak::util::rcx, |
|
||||
Xbyak::util::rdx, |
|
||||
Xbyak::util::rdi, |
|
||||
Xbyak::util::rsi, |
|
||||
Xbyak::util::r8, |
|
||||
Xbyak::util::r9, |
|
||||
Xbyak::util::r10, |
|
||||
Xbyak::util::r11, |
|
||||
// XMMs |
|
||||
Xbyak::util::xmm0, |
|
||||
Xbyak::util::xmm1, |
|
||||
Xbyak::util::xmm2, |
|
||||
Xbyak::util::xmm3, |
|
||||
Xbyak::util::xmm4, |
|
||||
Xbyak::util::xmm5, |
|
||||
Xbyak::util::xmm6, |
|
||||
Xbyak::util::xmm7, |
|
||||
Xbyak::util::xmm8, |
|
||||
Xbyak::util::xmm9, |
|
||||
Xbyak::util::xmm10, |
|
||||
Xbyak::util::xmm11, |
|
||||
Xbyak::util::xmm12, |
|
||||
Xbyak::util::xmm13, |
|
||||
Xbyak::util::xmm14, |
|
||||
Xbyak::util::xmm15, |
|
||||
}); |
|
||||
|
|
||||
constexpr inline std::bitset<32> ABI_ALL_CALLEE_SAVED = BuildRegSet({ |
|
||||
// GPRs |
|
||||
Xbyak::util::rbx, |
|
||||
Xbyak::util::rbp, |
|
||||
Xbyak::util::r12, |
|
||||
Xbyak::util::r13, |
|
||||
Xbyak::util::r14, |
|
||||
Xbyak::util::r15, |
|
||||
}); |
|
||||
|
|
||||
constexpr size_t ABI_SHADOW_SPACE = 0; |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
struct ABIFrameInfo { |
|
||||
s32 subtraction; |
|
||||
s32 xmm_offset; |
|
||||
}; |
|
||||
|
|
||||
inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<32> regs, size_t rsp_alignment, |
|
||||
size_t needed_frame_size) { |
|
||||
const auto count = (regs & ABI_ALL_GPRS).count(); |
|
||||
rsp_alignment -= count * 8; |
|
||||
size_t subtraction = 0; |
|
||||
const auto xmm_count = (regs & ABI_ALL_XMMS).count(); |
|
||||
if (xmm_count) { |
|
||||
// If we have any XMMs to save, we must align the stack here. |
|
||||
subtraction = rsp_alignment & 0xF; |
|
||||
} |
|
||||
subtraction += 0x10 * xmm_count; |
|
||||
size_t xmm_base_subtraction = subtraction; |
|
||||
subtraction += needed_frame_size; |
|
||||
subtraction += ABI_SHADOW_SPACE; |
|
||||
// Final alignment. |
|
||||
rsp_alignment -= subtraction; |
|
||||
subtraction += rsp_alignment & 0xF; |
|
||||
|
|
||||
return ABIFrameInfo{ |
|
||||
s32(subtraction), |
|
||||
s32(subtraction - xmm_base_subtraction) |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bitset<32> regs, size_t rsp_alignment, size_t needed_frame_size = 0) { |
|
||||
auto frame_info = ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size); |
|
||||
|
|
||||
for (size_t i = 0; i < regs.size(); ++i) { |
|
||||
if (regs[i] && ABI_ALL_GPRS[i]) { |
|
||||
code.push(IndexToReg64(i)); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (frame_info.subtraction != 0) { |
|
||||
code.sub(code.rsp, frame_info.subtraction); |
|
||||
} |
|
||||
|
|
||||
for (size_t i = 0; i < regs.size(); ++i) { |
|
||||
if (regs[i] && ABI_ALL_XMMS[i]) { |
|
||||
code.movaps(code.xword[code.rsp + frame_info.xmm_offset], IndexToXmm(i)); |
|
||||
frame_info.xmm_offset += 0x10; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ABI_SHADOW_SPACE; |
|
||||
} |
|
||||
|
|
||||
inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bitset<32> regs, size_t rsp_alignment, size_t needed_frame_size = 0) { |
|
||||
auto frame_info = ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size); |
|
||||
|
|
||||
for (size_t i = 0; i < regs.size(); ++i) { |
|
||||
if (regs[i] && ABI_ALL_XMMS[i]) { |
|
||||
code.movaps(IndexToXmm(i), code.xword[code.rsp + frame_info.xmm_offset]); |
|
||||
frame_info.xmm_offset += 0x10; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (frame_info.subtraction != 0) { |
|
||||
code.add(code.rsp, frame_info.subtraction); |
|
||||
} |
|
||||
|
|
||||
// GPRs need to be popped in reverse order |
|
||||
for (size_t j = 0; j < regs.size(); ++j) { |
|
||||
const size_t i = regs.size() - j - 1; |
|
||||
if (regs[i] && ABI_ALL_GPRS[i]) { |
|
||||
code.pop(IndexToReg64(i)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Constants for use with cmpps/cmpss |
|
||||
enum { |
|
||||
CMP_EQ = 0, |
|
||||
CMP_LT = 1, |
|
||||
CMP_LE = 2, |
|
||||
CMP_UNORD = 3, |
|
||||
CMP_NEQ = 4, |
|
||||
CMP_NLT = 5, |
|
||||
CMP_NLE = 6, |
|
||||
CMP_ORD = 7, |
|
||||
}; |
|
||||
|
|
||||
constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) { |
|
||||
const u64 distance = target - (ref + 5); |
|
||||
return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL); |
|
||||
} |
|
||||
|
|
||||
inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) { |
|
||||
return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target); |
|
||||
} |
|
||||
|
|
||||
template <typename T> |
|
||||
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { |
|
||||
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer."); |
|
||||
size_t addr = reinterpret_cast<size_t>(f); |
|
||||
if (IsWithin2G(code, addr)) { |
|
||||
code.call(f); |
|
||||
} else { |
|
||||
// ABI_RETURN is a safe temp register to use before a call |
|
||||
code.mov(ABI_RETURN, addr); |
|
||||
code.call(ABI_RETURN); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} // namespace Common::X64 |
|
||||
@ -1,13 +0,0 @@ |
|||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
// You must ensure this matches with src/common/x64/xbyak.h on root dir |
|
||||
#include <ankerl/unordered_dense.h> |
|
||||
#include <boost/unordered_map.hpp> |
|
||||
#define XBYAK_STD_UNORDERED_SET ankerl::unordered_dense::set |
|
||||
#define XBYAK_STD_UNORDERED_MAP ankerl::unordered_dense::map |
|
||||
#define XBYAK_STD_UNORDERED_MULTIMAP boost::unordered_multimap |
|
||||
#include <xbyak/xbyak.h> |
|
||||
#include <xbyak/xbyak_util.h> |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue