This commit is contained in:
Wunk 2025-08-06 12:25:32 +02:00 committed by GitHub
commit 6ba5e337bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 132 additions and 25 deletions

View File

@ -54,7 +54,7 @@ filter("configurations:Checked")
defines({
"DEBUG",
})
filter({"configurations:Checked", "platforms:Windows"})
filter({"configurations:Checked", "platforms:Windows-*"})
buildoptions({
"/RTCsu", -- Full Run-Time Checks.
})
@ -153,7 +153,7 @@ filter("platforms:Android-*")
"log",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
system("windows")
toolset("msc")
buildoptions({
@ -179,8 +179,12 @@ filter("platforms:Windows")
"_CRT_SECURE_NO_WARNINGS",
"WIN32",
"_WIN64=1",
"_AMD64=1",
})
filter("architecture:x86_64")
defines({
"_AMD64=1",
})
filter({})
linkoptions({
"/ignore:4006", -- Ignores complaints about empty obj files.
"/ignore:4221",
@ -198,7 +202,7 @@ filter("platforms:Windows")
})
-- Embed the manifest for things like dependencies and DPI awareness.
filter({"platforms:Windows", "kind:ConsoleApp or WindowedApp"})
filter({"platforms:Windows-*", "kind:ConsoleApp or WindowedApp"})
files({
"src/xenia/base/app_win32.manifest"
})
@ -228,7 +232,12 @@ workspace("xenia")
["ARCHS"] = "x86_64"
})
elseif os.istarget("windows") then
platforms({"Windows"})
platforms({"Windows-ARM64", "Windows-x86_64"})
filter("platforms:Windows-ARM64")
architecture("ARM64")
filter("platforms:Windows-x86_64")
architecture("x86_64")
filter({})
-- 10.0.15063.0: ID3D12GraphicsCommandList1::SetSamplePositions.
-- 10.0.19041.0: D3D12_HEAP_FLAG_CREATE_NOT_ZEROED.
-- 10.0.22000.0: DWMWA_WINDOW_CORNER_PREFERENCE.
@ -284,7 +293,11 @@ workspace("xenia")
include("src/xenia/apu/nop")
include("src/xenia/base")
include("src/xenia/cpu")
include("src/xenia/cpu/backend/x64")
filter("architecture:x86_64")
include("src/xenia/cpu/backend/x64")
filter({})
include("src/xenia/debug/ui")
include("src/xenia/gpu")
include("src/xenia/gpu/null")

View File

@ -32,6 +32,7 @@ project("xenia-app")
"libavcodec",
"libavutil",
"mspack",
"SDL2",
"snappy",
"xxhash",
})
@ -78,7 +79,7 @@ project("xenia-app")
"xenia_main.cc",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
files({
"main_resources.rc",
})
@ -104,7 +105,7 @@ project("xenia-app")
"SDL2",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
links({
"xenia-apu-xaudio2",
"xenia-gpu-d3d12",
@ -113,13 +114,13 @@ project("xenia-app")
"xenia-ui-d3d12",
})
filter({"platforms:Windows", SINGLE_LIBRARY_FILTER})
filter({"platforms:Windows-*", SINGLE_LIBRARY_FILTER})
links({
"xenia-gpu-d3d12-trace-viewer",
"xenia-ui-window-d3d12-demo",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-app.vcxproj.user"
if not os.isfile(user_file) then

View File

@ -36,12 +36,22 @@ LONG CALLBACK ExceptionHandlerCallback(PEXCEPTION_POINTERS ex_info) {
}
HostThreadContext thread_context;
#if XE_ARCH_AMD64
thread_context.rip = ex_info->ContextRecord->Rip;
thread_context.eflags = ex_info->ContextRecord->EFlags;
std::memcpy(thread_context.int_registers, &ex_info->ContextRecord->Rax,
sizeof(thread_context.int_registers));
std::memcpy(thread_context.xmm_registers, &ex_info->ContextRecord->Xmm0,
sizeof(thread_context.xmm_registers));
#elif XE_ARCH_ARM64
thread_context.pc = ex_info->ContextRecord->Pc;
thread_context.cpsr = ex_info->ContextRecord->Cpsr;
std::memcpy(thread_context.x, &ex_info->ContextRecord->X,
sizeof(thread_context.x));
std::memcpy(thread_context.v, &ex_info->ContextRecord->V,
sizeof(thread_context.v));
#endif
// https://msdn.microsoft.com/en-us/library/ms679331(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
@ -78,6 +88,7 @@ LONG CALLBACK ExceptionHandlerCallback(PEXCEPTION_POINTERS ex_info) {
for (size_t i = 0; i < xe::countof(handlers_) && handlers_[i].first; ++i) {
if (handlers_[i].first(&ex, handlers_[i].second)) {
// Exception handled.
#if XE_ARCH_AMD64
ex_info->ContextRecord->Rip = thread_context.rip;
ex_info->ContextRecord->EFlags = thread_context.eflags;
uint32_t modified_register_index;
@ -98,6 +109,28 @@ LONG CALLBACK ExceptionHandlerCallback(PEXCEPTION_POINTERS ex_info) {
&thread_context.xmm_registers[modified_register_index],
sizeof(vec128_t));
}
#elif XE_ARCH_ARM64
ex_info->ContextRecord->Pc = thread_context.pc;
ex_info->ContextRecord->Cpsr = thread_context.cpsr;
uint32_t modified_register_index;
uint16_t modified_int_registers_remaining = ex.modified_x_registers();
while (xe::bit_scan_forward(modified_int_registers_remaining,
&modified_register_index)) {
modified_int_registers_remaining &=
~(UINT16_C(1) << modified_register_index);
ex_info->ContextRecord->X[modified_register_index] =
thread_context.x[modified_register_index];
}
uint16_t modified_xmm_registers_remaining = ex.modified_v_registers();
while (xe::bit_scan_forward(modified_xmm_registers_remaining,
&modified_register_index)) {
modified_xmm_registers_remaining &=
~(UINT16_C(1) << modified_register_index);
std::memcpy(&ex_info->ContextRecord->V + modified_register_index,
&thread_context.v[modified_register_index],
sizeof(vec128_t));
}
#endif
return EXCEPTION_CONTINUE_EXECUTION;
}
}

View File

@ -67,7 +67,7 @@ std::string HostThreadContext::GetStringFromValue(HostRegister reg,
case Arm64Register::kPc:
return hex ? string_util::to_hex_string(pc) : std::to_string(pc);
case Arm64Register::kPstate:
return hex ? string_util::to_hex_string(pstate) : std::to_string(pstate);
return hex ? string_util::to_hex_string(cpsr) : std::to_string(cpsr);
case Arm64Register::kFpsr:
return hex ? string_util::to_hex_string(fpsr) : std::to_string(fpsr);
case Arm64Register::kFpcr:

View File

@ -202,7 +202,7 @@ class HostThreadContext {
uint64_t x[31];
uint64_t sp;
uint64_t pc;
uint64_t pstate;
uint32_t cpsr;
uint32_t fpsr;
uint32_t fpcr;
vec128_t v[32];

View File

@ -11,6 +11,8 @@
#include <cstdlib>
#if XE_ARCH_AMD64
// Includes Windows headers, so it goes after platform_win.h.
#include "third_party/xbyak/xbyak/xbyak_util.h"
@ -39,3 +41,5 @@ class StartupAvxCheck {
#pragma warning(suppress : 4073)
#pragma init_seg(lib)
static StartupAvxCheck gStartupAvxCheck;
#endif

View File

@ -135,10 +135,17 @@ constexpr inline uint32_t bit_count(T v) {
}
#else
#if XE_COMPILER_MSVC || XE_COMPILER_INTEL
#if XE_ARCH_AMD64
inline uint32_t bit_count(uint32_t v) { return __popcnt(v); }
inline uint32_t bit_count(uint64_t v) {
return static_cast<uint32_t>(__popcnt64(v));
}
#elif XE_ARCH_ARM64
inline uint32_t bit_count(uint32_t v) { return _CountOneBits(v); }
inline uint32_t bit_count(uint64_t v) {
return static_cast<uint32_t>(_CountOneBits64(v));
}
#endif
#elif XE_COMPILER_GCC || XE_COMPILER_CLANG
static_assert(sizeof(unsigned int) == sizeof(uint32_t));
static_assert(sizeof(unsigned long long) == sizeof(uint64_t));

View File

@ -4,7 +4,11 @@ include(project_root.."/tools/build")
group("src")
project("xenia-cpu-backend-x64")
uuid("7d8d5dce-4696-4197-952a-09506f725afe")
kind("StaticLib")
filter("architecture:x86_64")
kind("StaticLib")
filter("architecture:not x86_64")
kind("None")
filter({})
language("C++")
links({
"capstone",

View File

@ -27,7 +27,7 @@ project("xenia-cpu-ppc-tests")
links({
"xenia-cpu-backend-x64",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
debugdir(project_root)
debugargs({
"2>&1",

View File

@ -173,32 +173,62 @@ class Win32StackWalker : public StackWalker {
} else {
// Copy thread context local. We will be modifying it during stack
// walking, so we don't want to mess with the incoming copy.
#if XE_ARCH_AMD64
thread_context.Rip = in_host_context->rip;
thread_context.EFlags = in_host_context->eflags;
std::memcpy(&thread_context.Rax, in_host_context->int_registers,
sizeof(in_host_context->int_registers));
std::memcpy(&thread_context.Xmm0, in_host_context->xmm_registers,
sizeof(in_host_context->xmm_registers));
#elif XE_ARCH_ARM64
thread_context.Pc = in_host_context->pc;
thread_context.Cpsr = in_host_context->cpsr;
std::memcpy(thread_context.X, in_host_context->x,
sizeof(in_host_context->x));
std::memcpy(&thread_context.V, in_host_context->v,
sizeof(in_host_context->v));
#endif
}
if (out_host_context) {
// Write out the captured thread context if the caller asked for it.
#if XE_ARCH_AMD64
out_host_context->rip = thread_context.Rip;
out_host_context->eflags = thread_context.EFlags;
std::memcpy(out_host_context->int_registers, &thread_context.Rax,
sizeof(out_host_context->int_registers));
std::memcpy(out_host_context->xmm_registers, &thread_context.Xmm0,
sizeof(out_host_context->xmm_registers));
#elif XE_ARCH_ARM64
out_host_context->pc = thread_context.Pc;
out_host_context->cpsr = thread_context.Cpsr;
std::memcpy(out_host_context->x, &thread_context.X,
sizeof(out_host_context->x));
std::memcpy(out_host_context->v, &thread_context.V,
sizeof(out_host_context->v));
#endif
}
// Setup the frame for walking.
STACKFRAME64 stack_frame = {0};
stack_frame.AddrPC.Mode = AddrModeFlat;
#if XE_ARCH_AMD64
stack_frame.AddrPC.Offset = thread_context.Rip;
#elif XE_ARCH_ARM64
stack_frame.AddrPC.Offset = thread_context.Pc;
#endif
stack_frame.AddrFrame.Mode = AddrModeFlat;
#if XE_ARCH_AMD64
stack_frame.AddrFrame.Offset = thread_context.Rbp;
#elif XE_ARCH_ARM64
stack_frame.AddrFrame.Offset = thread_context.Fp;
#endif
stack_frame.AddrStack.Mode = AddrModeFlat;
#if XE_ARCH_AMD64
stack_frame.AddrStack.Offset = thread_context.Rsp;
#elif XE_ARCH_ARM64
stack_frame.AddrStack.Offset = thread_context.Sp;
#endif
// Walk the stack.
// Note that StackWalk64 is thread safe, though other dbghelp functions are

View File

@ -958,6 +958,7 @@ void DebugWindow::DrawRegistersPane() {
} break;
case RegisterGroup::kHostGeneral: {
ImGui::BeginChild("##host_general");
#if XE_ARCH_AMD64
for (int i = 0; i < 18; ++i) {
auto reg = static_cast<X64Register>(i);
ImGui::BeginGroup();
@ -995,6 +996,9 @@ void DebugWindow::DrawRegistersPane() {
i, thread_info->host_context.xmm_registers[i].f32);
ImGui::EndGroup();
}
#elif XE_ARCH_ARM64
// TODO(wunkolo): print ARM64 registers
#endif
ImGui::EndChild();
}
}

View File

@ -172,11 +172,19 @@ X_STATUS Emulator::Setup(
if (cvars::cpu == "x64") {
backend.reset(new xe::cpu::backend::x64::X64Backend());
}
#elif XE_ARCH_ARM64
// TODO(wunkolo): Arm64 backend
if (cvars::cpu == "a64") {
backend.reset(new xe::cpu::backend::NullBackend());
}
#endif // XE_ARCH
if (cvars::cpu == "any") {
if (!backend) {
#if XE_ARCH_AMD64
backend.reset(new xe::cpu::backend::x64::X64Backend());
#elif XE_ARCH_ARM64
// TODO(wunkolo): Arm64 backend
backend.reset(new xe::cpu::backend::NullBackend());
#endif // XE_ARCH
}
}

View File

@ -43,7 +43,7 @@ project("xenia-gpu-shader-compiler")
"../base/console_app_main_"..platform_suffix..".cc",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-shader-compiler.vcxproj.user"
if not os.isfile(user_file) then

View File

@ -75,7 +75,7 @@ project("xenia-gpu-vulkan-trace-viewer")
"X11-xcb",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-viewer.vcxproj.user"
if not os.isfile(user_file) then
@ -138,7 +138,7 @@ project("xenia-gpu-vulkan-trace-dump")
"X11-xcb",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
-- Only create the .user file if it doesn't already exist.
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-dump.vcxproj.user"
if not os.isfile(user_file) then

View File

@ -53,7 +53,7 @@ project("xenia-hid-demo")
"X11-xcb",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
links({
"xenia-hid-winkey",
"xenia-hid-xinput",

View File

@ -19,7 +19,7 @@ project("xenia-ui")
-- Exports JNI functions.
wholelib("On")
filter("platforms:Windows")
filter("platforms:Windows-*")
links({
"dwmapi",
"dxgi",

View File

@ -26,7 +26,7 @@ end
-- Call this function in project scope to include the SDL2 headers.
--
function sdl2_include()
filter("platforms:Windows")
filter("platforms:Windows-*")
includedirs({
path.getrelative(".", third_party_path) .. "/SDL2/include",
})

View File

@ -30,7 +30,7 @@ project("discord-rpc")
files({
"discord-rpc/src/discord_register_osx.m"
})
filter("platforms:Windows")
filter("platforms:Windows-*")
files({
"discord-rpc/src/connection_win.cpp",
"discord-rpc/src/discord_register_win.cpp"

View File

@ -3252,7 +3252,7 @@ void MicroProfileDraw(uint32_t nWidth, uint32_t nHeight)
#if MICROPROFILE_CONTEXT_SWITCH_TRACE
MicroProfileStringArrayAddLiteral(&Debug, "Context Switch");
MicroProfileStringArrayFormat(&Debug, "%9d [%7d]", S.nContextSwitchUsage, MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE / S.nContextSwitchUsage );
MicroProfileStringArrayFormat(&Debug, "%9d [%7d]", S.nContextSwitchUsage, S.nContextSwitchUsage ? MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE / S.nContextSwitchUsage : 0 );
#endif
for(int i = 0; i < MICROPROFILE_MAX_THREADS; ++i)

View File

@ -28,7 +28,7 @@ project("mspack")
"mspack/system.h",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
defines({
})
filter("platforms:Linux")

View File

@ -18,5 +18,5 @@ project("snappy")
"snappy/snappy.h",
})
filter("platforms:Windows")
filter("platforms:Windows-*")
warnings("Off") -- Too many warnings.

View File

@ -20,7 +20,7 @@ local function match_platform_files(base_path, base_match)
removefiles({base_path.."/".."**_android.h", base_path.."/".."**_android.cc"})
removefiles({base_path.."/".."**_mac.h", base_path.."/".."**_mac.cc"})
removefiles({base_path.."/".."**_win.h", base_path.."/".."**_win.cc"})
filter("platforms:Windows")
filter("platforms:Windows-*")
files({
base_path.."/"..base_match.."_win.h",
base_path.."/"..base_match.."_win.cc",

View File

@ -781,6 +781,8 @@ class BaseBuildCommand(Command):
self.parser.add_argument(
'--target', action='append', default=[],
help='Builds only the given target(s).')
self.parser.add_argument(
'--arch', default='x86_64', help='Builds only the given architecture')
self.parser.add_argument(
'--force', action='store_true',
help='Forces a full rebuild.')
@ -823,6 +825,7 @@ class BaseBuildCommand(Command):
'/m',
'/v:m',
'/p:Configuration=' + args['config'],
'/p:Platform=' + "Windows-" + args['arch'],
] + ([targets] if targets is not None else []) + pass_args,
shell=False)
elif sys.platform == 'darwin':