From 737f2b582b5c747664827cddd27a771b67fa5a9e Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Fri, 10 May 2024 15:36:36 -0700 Subject: [PATCH] [UI] Implement Arm64 host register info --- src/xenia/base/platform.h | 8 +++ src/xenia/debug/ui/debug_window.cc | 100 +++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/xenia/base/platform.h b/src/xenia/base/platform.h index 439d0c467..c852ad649 100644 --- a/src/xenia/base/platform.h +++ b/src/xenia/base/platform.h @@ -66,6 +66,14 @@ #define XE_ARCH_PPC 1 #endif +#ifdef XE_ARCH_AMD64 +#define XE_HOST_ARCH_NAME "x64" +#elif XE_ARCH_ARM64 +#define XE_HOST_ARCH_NAME "a64" +#elif XE_ARCH_PPC +#define XE_HOST_ARCH_NAME "ppc" +#endif + #if XE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #define NOMINMAX // Don't want windows.h including min/max macros. diff --git a/src/xenia/debug/ui/debug_window.cc b/src/xenia/debug/ui/debug_window.cc index e7d6ada8f..73fe65e49 100644 --- a/src/xenia/debug/ui/debug_window.cc +++ b/src/xenia/debug/ui/debug_window.cc @@ -63,7 +63,13 @@ DebugWindow::DebugWindow(Emulator* emulator, processor_(emulator->processor()), app_context_(app_context), window_(xe::ui::Window::Create(app_context_, kBaseTitle, 1500, 1000)) { - if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) { + if ( +#ifdef XE_ARCH_AMD64 + cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) +#elif XE_ARCH_ARM64 + cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone_handle_) +#endif + != CS_ERR_OK) { assert_always("Failed to initialize capstone"); } cs_option(capstone_handle_, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); @@ -336,7 +342,7 @@ void DebugWindow::DrawSourcePane() { // copy button // address start - end // name text box (editable) - // combo for interleaved + [ppc, hir, opt hir, x64 + byte with sizes] + // combo for interleaved + [ppc, hir, opt hir, asm + byte with sizes] ImGui::AlignTextToFramePadding(); ImGui::Text("%s", function->module()->name().c_str()); ImGui::SameLine(); @@ -381,11 +387,11 @@ void DebugWindow::DrawSourcePane() { } ImGui::SameLine(); if (state_.source_display_mode > 0) { - // Only show x64 step button if we have x64 visible. + // Only show asm step button if we have asm visible. ImGui::Dummy(ImVec2(4, 0)); ImGui::SameLine(); ImGui::PushButtonRepeat(true); - if (ImGui::ButtonEx("Step x64", ImVec2(0, 0), + if (ImGui::ButtonEx("Step " XE_HOST_ARCH_NAME, ImVec2(0, 0), can_step ? 0 : ImGuiItemFlags_Disabled)) { // By enabling the button when stepping we allow repeat behavior. if (processor_->execution_state() != cpu::ExecutionState::kStepping) { @@ -394,8 +400,8 @@ void DebugWindow::DrawSourcePane() { } ImGui::PopButtonRepeat(); if (ImGui::IsItemHovered()) { - ImGui::SetTooltip( - "Step one x64 instruction on the current thread (hold for many)."); + ImGui::SetTooltip("Step one " XE_HOST_ARCH_NAME + " instruction on the current thread (hold for many)."); } ImGui::SameLine(); } @@ -410,9 +416,9 @@ void DebugWindow::DrawSourcePane() { if (function->is_guest()) { const char* kSourceDisplayModes[] = { "PPC", - "PPC+HIR+x64", - "PPC+HIR (opt)+x64", - "PPC+x64", + "PPC+HIR+" XE_HOST_ARCH_NAME, + "PPC+HIR (opt)+" XE_HOST_ARCH_NAME, + "PPC+" XE_HOST_ARCH_NAME, }; ImGui::PushItemWidth(90); ImGui::Combo("##display_mode", &state_.source_display_mode, @@ -457,7 +463,7 @@ void DebugWindow::DrawGuestFunctionSource() { // labels get their own line with duped addresses // show xrefs to labels? // hir greyed and offset (background color change?) - // x64 greyed and offset with native address + // asm greyed and offset with native address // hover on registers/etc for tooltip/highlight others // click register to go to location of last write // click code address to jump to code @@ -470,18 +476,18 @@ void DebugWindow::DrawGuestFunctionSource() { bool draw_hir = false; bool draw_hir_opt = false; - bool draw_x64 = false; + bool draw_asm = false; switch (state_.source_display_mode) { case 1: draw_hir = true; - draw_x64 = true; + draw_asm = true; break; case 2: draw_hir_opt = true; - draw_x64 = true; + draw_asm = true; break; case 3: - draw_x64 = true; + draw_asm = true; break; } @@ -496,8 +502,8 @@ void DebugWindow::DrawGuestFunctionSource() { if (draw_hir_opt) { // TODO(benvanik): get HIR and draw preamble. } - if (draw_x64) { - // x64 preamble. + if (draw_asm) { + // asm preamble. DrawMachineCodeSource(function->machine_code(), source_map[0].code_offset); } @@ -510,7 +516,7 @@ void DebugWindow::DrawGuestFunctionSource() { bool is_current_instr = address == guest_pc; if (is_current_instr) { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 1.0f, 0.0f, 1.0f)); - if (!draw_x64) { + if (!draw_asm) { ScrollToSourceIfPcChanged(); } } @@ -546,7 +552,7 @@ void DebugWindow::DrawGuestFunctionSource() { if (draw_hir_opt) { // TODO(benvanik): get HIR and draw for this PPC function. } - if (draw_x64) { + if (draw_asm) { const uint8_t* machine_code_start = function->machine_code() + source_map[source_map_index].code_offset; const size_t machine_code_length = @@ -849,10 +855,10 @@ void DebugWindow::DrawRegistersPane() { if (state_.register_group == RegisterGroup::kHostGeneral) { ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); - ImGui::Button("x64"); + ImGui::Button(XE_HOST_ARCH_NAME); ImGui::PopStyleColor(); } else { - if (ImGui::Button("x64")) { + if (ImGui::Button(XE_HOST_ARCH_NAME)) { state_.register_group = RegisterGroup::kHostGeneral; } } @@ -860,10 +866,10 @@ void DebugWindow::DrawRegistersPane() { if (state_.register_group == RegisterGroup::kHostVector) { ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); - ImGui::Button("XMM"); + ImGui::Button(XE_HOST_ARCH_NAME "-vec"); ImGui::PopStyleColor(); } else { - if (ImGui::Button("XMM")) { + if (ImGui::Button(XE_HOST_ARCH_NAME "-vec")) { state_.register_group = RegisterGroup::kHostVector; } } @@ -996,6 +1002,43 @@ void DebugWindow::DrawRegistersPane() { } #elif XE_ARCH_ARM64 // TODO(wunkolo): print ARM64 registers + for (int i = 0; i < 34; ++i) { + auto reg = static_cast(i); + ImGui::BeginGroup(); + ImGui::AlignTextToFramePadding(); + ImGui::Text("%3s", HostThreadContext::GetRegisterName(reg)); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(4, 0)); + ImGui::SameLine(); + if (reg == Arm64Register::kPc) { + dirty_guest_context |= + DrawRegisterTextBox(i, &thread_info->host_context.pc); + } else if (reg == Arm64Register::kPstate) { + dirty_guest_context = + DrawRegisterTextBox(i, &thread_info->host_context.cpsr); + } else { + dirty_guest_context |= + DrawRegisterTextBox(i, &thread_info->host_context.x[i]); + } + ImGui::EndGroup(); + } + ImGui::EndChild(); + } break; + case RegisterGroup::kHostVector: { + ImGui::BeginChild("##host_vector"); + for (int i = 0; i < 32; ++i) { + auto reg = static_cast( + static_cast(Arm64Register::kV0) + i); + ImGui::BeginGroup(); + ImGui::AlignTextToFramePadding(); + ImGui::Text("%5s", HostThreadContext::GetRegisterName(reg)); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(4, 0)); + ImGui::SameLine(); + dirty_host_context |= + DrawRegisterTextBoxes(i, thread_info->host_context.v[i].f32); + ImGui::EndGroup(); + } #endif ImGui::EndChild(); } @@ -1146,7 +1189,8 @@ void DebugWindow::DrawBreakpointsPane() { ImGui::OpenPopup("##add_code_breakpoint"); } if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Add a code breakpoint for either PPC or x64."); + ImGui::SetTooltip( + "Add a code breakpoint for either PPC or " XE_HOST_ARCH_NAME "."); } // TODO(benvanik): remove this set focus workaround when imgui is fixed: // https://github.com/ocornut/imgui/issues/343 @@ -1180,15 +1224,15 @@ void DebugWindow::DrawBreakpointsPane() { ImGui::Dummy(ImVec2(0, 2)); ImGui::AlignTextToFramePadding(); - ImGui::Text("x64"); + ImGui::Text(XE_HOST_ARCH_NAME); ImGui::SameLine(); ImGui::Dummy(ImVec2(2, 0)); ImGui::SameLine(); - static char x64_buffer[64] = {0}; + static char asm_buffer[64] = {0}; ImGui::PushItemWidth(100); - if (ImGui::InputText("##host_address", x64_buffer, 17, input_flags)) { - uint64_t address = string_util::from_string(x64_buffer, true); - x64_buffer[0] = 0; + if (ImGui::InputText("##host_address", asm_buffer, 17, input_flags)) { + uint64_t address = string_util::from_string(asm_buffer, true); + asm_buffer[0] = 0; CreateCodeBreakpoint(Breakpoint::AddressType::kHost, address); ImGui::CloseCurrentPopup(); }