[UI] Implement Arm64 host register info

This commit is contained in:
Wunkolo 2024-05-10 15:36:36 -07:00
parent f5e14d6a40
commit 737f2b582b
2 changed files with 80 additions and 28 deletions

View File

@ -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.

View File

@ -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<Arm64Register>(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<Arm64Register>(
static_cast<int>(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<uint64_t>(x64_buffer, true);
x64_buffer[0] = 0;
if (ImGui::InputText("##host_address", asm_buffer, 17, input_flags)) {
uint64_t address = string_util::from_string<uint64_t>(asm_buffer, true);
asm_buffer[0] = 0;
CreateCodeBreakpoint(Breakpoint::AddressType::kHost, address);
ImGui::CloseCurrentPopup();
}