diff --git a/premake5.lua b/premake5.lua index 6739d6dba..81e2e5b64 100644 --- a/premake5.lua +++ b/premake5.lua @@ -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") diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 86fcef758..b63675682 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -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 diff --git a/src/xenia/base/exception_handler_win.cc b/src/xenia/base/exception_handler_win.cc index 786a129a5..49e49643f 100644 --- a/src/xenia/base/exception_handler_win.cc +++ b/src/xenia/base/exception_handler_win.cc @@ -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; } } diff --git a/src/xenia/base/host_thread_context.cc b/src/xenia/base/host_thread_context.cc index bf668bdd3..24b2b6e12 100644 --- a/src/xenia/base/host_thread_context.cc +++ b/src/xenia/base/host_thread_context.cc @@ -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: diff --git a/src/xenia/base/host_thread_context.h b/src/xenia/base/host_thread_context.h index 554d09f44..6379f62f8 100644 --- a/src/xenia/base/host_thread_context.h +++ b/src/xenia/base/host_thread_context.h @@ -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]; diff --git a/src/xenia/base/main_init_win.cc b/src/xenia/base/main_init_win.cc index 6b0a9059a..e67e50b66 100644 --- a/src/xenia/base/main_init_win.cc +++ b/src/xenia/base/main_init_win.cc @@ -11,6 +11,8 @@ #include +#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 \ No newline at end of file diff --git a/src/xenia/base/math.h b/src/xenia/base/math.h index 55dce4b45..1037e8518 100644 --- a/src/xenia/base/math.h +++ b/src/xenia/base/math.h @@ -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(__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(_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)); diff --git a/src/xenia/cpu/backend/x64/premake5.lua b/src/xenia/cpu/backend/x64/premake5.lua index f2a990f29..90e5288cf 100644 --- a/src/xenia/cpu/backend/x64/premake5.lua +++ b/src/xenia/cpu/backend/x64/premake5.lua @@ -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", diff --git a/src/xenia/cpu/ppc/testing/premake5.lua b/src/xenia/cpu/ppc/testing/premake5.lua index bca2bb81e..66f8bf1ba 100644 --- a/src/xenia/cpu/ppc/testing/premake5.lua +++ b/src/xenia/cpu/ppc/testing/premake5.lua @@ -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", diff --git a/src/xenia/cpu/stack_walker_win.cc b/src/xenia/cpu/stack_walker_win.cc index aaaab140a..2fe8470c4 100644 --- a/src/xenia/cpu/stack_walker_win.cc +++ b/src/xenia/cpu/stack_walker_win.cc @@ -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 diff --git a/src/xenia/debug/ui/debug_window.cc b/src/xenia/debug/ui/debug_window.cc index 07d4404db..df85b15a5 100644 --- a/src/xenia/debug/ui/debug_window.cc +++ b/src/xenia/debug/ui/debug_window.cc @@ -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(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(); } } diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index cca28982f..a96e045ba 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -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 } } diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 971d6ef70..850580ca2 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -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 diff --git a/src/xenia/gpu/vulkan/premake5.lua b/src/xenia/gpu/vulkan/premake5.lua index 90ae7c46e..fe51bcd2d 100644 --- a/src/xenia/gpu/vulkan/premake5.lua +++ b/src/xenia/gpu/vulkan/premake5.lua @@ -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 diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index 4e961f623..844a313f4 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -53,7 +53,7 @@ project("xenia-hid-demo") "X11-xcb", }) - filter("platforms:Windows") + filter("platforms:Windows-*") links({ "xenia-hid-winkey", "xenia-hid-xinput", diff --git a/src/xenia/ui/premake5.lua b/src/xenia/ui/premake5.lua index 6aff82bec..8f50fd515 100644 --- a/src/xenia/ui/premake5.lua +++ b/src/xenia/ui/premake5.lua @@ -19,7 +19,7 @@ project("xenia-ui") -- Exports JNI functions. wholelib("On") - filter("platforms:Windows") + filter("platforms:Windows-*") links({ "dwmapi", "dxgi", diff --git a/third_party/SDL2.lua b/third_party/SDL2.lua index 972aa1aa7..2186de6b7 100644 --- a/third_party/SDL2.lua +++ b/third_party/SDL2.lua @@ -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", }) diff --git a/third_party/discord-rpc.lua b/third_party/discord-rpc.lua index 1f6e795f8..ca7d0370e 100644 --- a/third_party/discord-rpc.lua +++ b/third_party/discord-rpc.lua @@ -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" diff --git a/third_party/microprofile/microprofileui.h b/third_party/microprofile/microprofileui.h index d422445dd..8f47a619d 100644 --- a/third_party/microprofile/microprofileui.h +++ b/third_party/microprofile/microprofileui.h @@ -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) diff --git a/third_party/mspack.lua b/third_party/mspack.lua index c1d1b44a5..94d6a6c81 100644 --- a/third_party/mspack.lua +++ b/third_party/mspack.lua @@ -28,7 +28,7 @@ project("mspack") "mspack/system.h", }) - filter("platforms:Windows") + filter("platforms:Windows-*") defines({ }) filter("platforms:Linux") diff --git a/third_party/snappy.lua b/third_party/snappy.lua index bf13b762e..3e6b1009d 100644 --- a/third_party/snappy.lua +++ b/third_party/snappy.lua @@ -18,5 +18,5 @@ project("snappy") "snappy/snappy.h", }) - filter("platforms:Windows") + filter("platforms:Windows-*") warnings("Off") -- Too many warnings. diff --git a/tools/build/scripts/platform_files.lua b/tools/build/scripts/platform_files.lua index ec1579cf0..332436dad 100644 --- a/tools/build/scripts/platform_files.lua +++ b/tools/build/scripts/platform_files.lua @@ -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", diff --git a/xenia-build b/xenia-build index 130032323..cfd134143 100755 --- a/xenia-build +++ b/xenia-build @@ -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':