mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-02-26 16:39:38 +00:00
tests: Add verbose debugging output and test_reader
This commit is contained in:
@@ -24,10 +24,6 @@ add_library(dynarmic
|
||||
common/fp/op/FPMulAdd.cpp
|
||||
common/fp/op/FPMulAdd.h
|
||||
common/fp/op/FPNeg.h
|
||||
common/fp/op/FPRSqrtEstimate.cpp
|
||||
common/fp/op/FPRSqrtEstimate.h
|
||||
common/fp/op/FPRSqrtStepFused.cpp
|
||||
common/fp/op/FPRSqrtStepFused.h
|
||||
common/fp/op/FPRecipEstimate.cpp
|
||||
common/fp/op/FPRecipEstimate.h
|
||||
common/fp/op/FPRecipExponent.cpp
|
||||
@@ -36,6 +32,10 @@ add_library(dynarmic
|
||||
common/fp/op/FPRecipStepFused.h
|
||||
common/fp/op/FPRoundInt.cpp
|
||||
common/fp/op/FPRoundInt.h
|
||||
common/fp/op/FPRSqrtEstimate.cpp
|
||||
common/fp/op/FPRSqrtEstimate.h
|
||||
common/fp/op/FPRSqrtStepFused.cpp
|
||||
common/fp/op/FPRSqrtStepFused.h
|
||||
common/fp/op/FPToFixed.cpp
|
||||
common/fp/op/FPToFixed.h
|
||||
common/fp/process_exception.cpp
|
||||
@@ -98,6 +98,10 @@ add_library(dynarmic
|
||||
|
||||
if ("A32" IN_LIST DYNARMIC_FRONTENDS)
|
||||
target_sources(dynarmic PRIVATE
|
||||
frontend/A32/a32_ir_emitter.cpp
|
||||
frontend/A32/a32_ir_emitter.h
|
||||
frontend/A32/a32_location_descriptor.cpp
|
||||
frontend/A32/a32_location_descriptor.h
|
||||
frontend/A32/decoder/arm.h
|
||||
frontend/A32/decoder/arm.inc
|
||||
frontend/A32/decoder/asimd.h
|
||||
@@ -112,21 +116,17 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS)
|
||||
frontend/A32/disassembler/disassembler_arm.cpp
|
||||
frontend/A32/disassembler/disassembler_thumb.cpp
|
||||
frontend/A32/FPSCR.h
|
||||
frontend/A32/a32_ir_emitter.cpp
|
||||
frontend/A32/a32_ir_emitter.h
|
||||
frontend/A32/a32_location_descriptor.cpp
|
||||
frontend/A32/a32_location_descriptor.h
|
||||
frontend/A32/ITState.h
|
||||
frontend/A32/PSR.h
|
||||
frontend/A32/translate/a32_translate.cpp
|
||||
frontend/A32/translate/a32_translate.h
|
||||
frontend/A32/translate/conditional_state.cpp
|
||||
frontend/A32/translate/conditional_state.h
|
||||
frontend/A32/translate/impl/a32_branch.cpp
|
||||
frontend/A32/translate/impl/a32_crc32.cpp
|
||||
frontend/A32/translate/impl/a32_exception_generating.cpp
|
||||
frontend/A32/translate/impl/a32_translate_impl.cpp
|
||||
frontend/A32/translate/impl/a32_translate_impl.h
|
||||
frontend/A32/translate/conditional_state.cpp
|
||||
frontend/A32/translate/conditional_state.h
|
||||
frontend/A32/translate/impl/asimd_load_store_structures.cpp
|
||||
frontend/A32/translate/impl/asimd_misc.cpp
|
||||
frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp
|
||||
@@ -284,12 +284,12 @@ if ("x86_64" IN_LIST ARCHITECTURE)
|
||||
backend/x64/emit_x64_crc32.cpp
|
||||
backend/x64/emit_x64_data_processing.cpp
|
||||
backend/x64/emit_x64_floating_point.cpp
|
||||
backend/x64/emit_x64_memory.h
|
||||
backend/x64/emit_x64_memory.cpp.inc
|
||||
backend/x64/emit_x64_memory.h
|
||||
backend/x64/emit_x64_packed.cpp
|
||||
backend/x64/emit_x64_saturation.cpp
|
||||
backend/x64/emit_x64_sm4.cpp
|
||||
backend/x64/emit_x64_sha.cpp
|
||||
backend/x64/emit_x64_sm4.cpp
|
||||
backend/x64/emit_x64_vector.cpp
|
||||
backend/x64/emit_x64_vector_floating_point.cpp
|
||||
backend/x64/emit_x64_vector_saturation.cpp
|
||||
@@ -305,6 +305,8 @@ if ("x86_64" IN_LIST ARCHITECTURE)
|
||||
backend/x64/reg_alloc.cpp
|
||||
backend/x64/reg_alloc.h
|
||||
backend/x64/stack_layout.h
|
||||
backend/x64/verbose_debugging_output.cpp
|
||||
backend/x64/verbose_debugging_output.h
|
||||
common/spin_lock_x64.cpp
|
||||
common/spin_lock_x64.h
|
||||
common/x64_disassemble.cpp
|
||||
@@ -334,7 +336,7 @@ if ("x86_64" IN_LIST ARCHITECTURE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if("arm64" IN_LIST ARCHITECTURE)
|
||||
if ("arm64" IN_LIST ARCHITECTURE)
|
||||
target_link_libraries(dynarmic PRIVATE merry::oaknut)
|
||||
|
||||
target_architecture_specific_sources(dynarmic "arm64"
|
||||
@@ -433,7 +435,7 @@ elseif (APPLE)
|
||||
)
|
||||
endif()
|
||||
elseif (UNIX)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
target_link_libraries(dynarmic PRIVATE rt)
|
||||
endif()
|
||||
target_sources(dynarmic PRIVATE backend/exception_handler_posix.cpp)
|
||||
@@ -487,7 +489,7 @@ if (DYNARMIC_USE_PRECOMPILED_HEADERS)
|
||||
if ("x86_64" IN_LIST ARCHITECTURE)
|
||||
list(PREPEND PRECOMPILED_HEADERS "$<$<COMPILE_LANGUAGE:CXX>:<xbyak/xbyak.h$<ANGLE-R>>")
|
||||
endif()
|
||||
if("arm64" IN_LIST ARCHITECTURE)
|
||||
if ("arm64" IN_LIST ARCHITECTURE)
|
||||
list(PREPEND PRECOMPILED_HEADERS "$<$<COMPILE_LANGUAGE:CXX>:<oaknut/oaknut.hpp$<ANGLE-R>>")
|
||||
endif()
|
||||
target_precompile_headers(dynarmic PRIVATE ${PRECOMPILED_HEADERS})
|
||||
|
||||
@@ -94,6 +94,10 @@ A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_in
|
||||
A32EmitX64::~A32EmitX64() = default;
|
||||
|
||||
A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||
if (conf.very_verbose_debugging_output) {
|
||||
std::puts(IR::DumpBlock(block).c_str());
|
||||
}
|
||||
|
||||
code.EnableWriting();
|
||||
SCOPE_EXIT { code.DisableWriting(); };
|
||||
|
||||
@@ -142,6 +146,10 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
|
||||
}
|
||||
|
||||
reg_alloc.EndOfAllocScope();
|
||||
|
||||
if (conf.very_verbose_debugging_output) {
|
||||
EmitVerboseDebuggingOutput(reg_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
reg_alloc.AssertNoMoreUses();
|
||||
|
||||
@@ -65,6 +65,10 @@ A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_in
|
||||
A64EmitX64::~A64EmitX64() = default;
|
||||
|
||||
A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||
if (conf.very_verbose_debugging_output) {
|
||||
std::puts(IR::DumpBlock(block).c_str());
|
||||
}
|
||||
|
||||
code.EnableWriting();
|
||||
SCOPE_EXIT { code.DisableWriting(); };
|
||||
|
||||
@@ -113,6 +117,10 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||
}
|
||||
|
||||
ctx.reg_alloc.EndOfAllocScope();
|
||||
|
||||
if (conf.very_verbose_debugging_output) {
|
||||
EmitVerboseDebuggingOutput(reg_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
reg_alloc.AssertNoMoreUses();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "dynarmic/backend/x64/nzcv_util.h"
|
||||
#include "dynarmic/backend/x64/perf_map.h"
|
||||
#include "dynarmic/backend/x64/stack_layout.h"
|
||||
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
||||
#include "dynarmic/common/variant_util.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
@@ -102,6 +103,34 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I
|
||||
code.mov(dword[r15 + code.GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32());
|
||||
}
|
||||
|
||||
void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) {
|
||||
code.sub(rsp, sizeof(RegisterData));
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (rsp.getIdx() == i) {
|
||||
continue;
|
||||
}
|
||||
code.mov(qword[rsp + offsetof(RegisterData, gprs) + sizeof(u64) * i], Xbyak::Reg64{i});
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
code.movaps(xword[rsp + offsetof(RegisterData, xmms) + 2 * sizeof(u64) * i], Xbyak::Xmm{i});
|
||||
}
|
||||
code.lea(rax, ptr[rsp + sizeof(RegisterData) + offsetof(StackLayout, spill)]);
|
||||
code.mov(xword[rsp + offsetof(RegisterData, spill)], rax);
|
||||
|
||||
reg_alloc.EmitVerboseDebuggingOutput();
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (rsp.getIdx() == i) {
|
||||
continue;
|
||||
}
|
||||
code.mov(Xbyak::Reg64{i}, qword[rsp + offsetof(RegisterData, gprs) + sizeof(u64) * i]);
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
code.movaps(Xbyak::Xmm{i}, xword[rsp + offsetof(RegisterData, xmms) + 2 * sizeof(u64) * i]);
|
||||
}
|
||||
code.add(rsp, sizeof(RegisterData));
|
||||
}
|
||||
|
||||
void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
ASSERT(args[0].IsImmediate());
|
||||
|
||||
@@ -108,6 +108,8 @@ protected:
|
||||
BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size);
|
||||
void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target);
|
||||
|
||||
void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc);
|
||||
|
||||
// Terminal instruction emitters
|
||||
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||
virtual void EmitTerminalImpl(IR::Term::Interpret terminal, IR::LocationDescriptor initial_location, bool is_single_step) = 0;
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
|
||||
#include <fmt/ostream.h>
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/bit_cast.hpp>
|
||||
#include <xbyak/xbyak.h>
|
||||
|
||||
#include "dynarmic/backend/x64/abi.h"
|
||||
#include "dynarmic/backend/x64/stack_layout.h"
|
||||
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
@@ -85,6 +87,11 @@ bool HostLocInfo::IsLastUse() const {
|
||||
return is_being_used_count == 0 && current_references == 1 && accumulated_uses + 1 == total_uses;
|
||||
}
|
||||
|
||||
void HostLocInfo::SetLastUse() {
|
||||
ASSERT(IsLastUse());
|
||||
is_set_last_use = true;
|
||||
}
|
||||
|
||||
void HostLocInfo::ReadLock() {
|
||||
ASSERT(!is_scratch);
|
||||
is_being_used_count++;
|
||||
@@ -119,7 +126,7 @@ void HostLocInfo::ReleaseAll() {
|
||||
accumulated_uses += current_references;
|
||||
current_references = 0;
|
||||
|
||||
ASSERT(total_uses == std::accumulate(values.begin(), values.end(), size_t(0), [](size_t sum, IR::Inst* inst) { return sum + inst->UseCount(); }));
|
||||
is_set_last_use = false;
|
||||
|
||||
if (total_uses == accumulated_uses) {
|
||||
values.clear();
|
||||
@@ -141,11 +148,25 @@ size_t HostLocInfo::GetMaxBitWidth() const {
|
||||
}
|
||||
|
||||
void HostLocInfo::AddValue(IR::Inst* inst) {
|
||||
if (is_set_last_use) {
|
||||
is_set_last_use = false;
|
||||
values.clear();
|
||||
}
|
||||
values.push_back(inst);
|
||||
total_uses += inst->UseCount();
|
||||
max_bit_width = std::max(max_bit_width, GetBitWidth(inst->GetType()));
|
||||
}
|
||||
|
||||
void HostLocInfo::EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index) const {
|
||||
using namespace Xbyak::util;
|
||||
for (IR::Inst* value : values) {
|
||||
code.mov(code.ABI_PARAM1, rsp);
|
||||
code.mov(code.ABI_PARAM2, host_loc_index);
|
||||
code.mov(code.ABI_PARAM3, mcl::bit_cast<u64>(value));
|
||||
code.CallFunction(PrintVerboseDebuggingOutputLine);
|
||||
}
|
||||
}
|
||||
|
||||
IR::Type Argument::GetType() const {
|
||||
return value.GetType();
|
||||
}
|
||||
@@ -369,6 +390,8 @@ HostLoc RegAlloc::UseScratchImpl(IR::Value use_value, const std::vector<HostLoc>
|
||||
if (can_use_current_location && !LocInfo(current_location).IsLocked()) {
|
||||
if (!LocInfo(current_location).IsLastUse()) {
|
||||
MoveOutOfTheWay(current_location);
|
||||
} else {
|
||||
LocInfo(current_location).SetLastUse();
|
||||
}
|
||||
LocInfo(current_location).WriteLock();
|
||||
return current_location;
|
||||
@@ -471,6 +494,12 @@ void RegAlloc::AssertNoMoreUses() {
|
||||
ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i) { return i.IsEmpty(); }));
|
||||
}
|
||||
|
||||
void RegAlloc::EmitVerboseDebuggingOutput() {
|
||||
for (size_t i = 0; i < hostloc_info.size(); i++) {
|
||||
hostloc_info[i].EmitVerboseDebuggingOutput(code, i);
|
||||
}
|
||||
}
|
||||
|
||||
HostLoc RegAlloc::SelectARegister(const std::vector<HostLoc>& desired_locations) const {
|
||||
std::vector<HostLoc> candidates = desired_locations;
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
bool IsEmpty() const;
|
||||
bool IsLastUse() const;
|
||||
|
||||
void SetLastUse();
|
||||
|
||||
void ReadLock();
|
||||
void WriteLock();
|
||||
void AddArgReference();
|
||||
@@ -46,10 +48,13 @@ public:
|
||||
|
||||
void AddValue(IR::Inst* inst);
|
||||
|
||||
void EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index) const;
|
||||
|
||||
private:
|
||||
// Current instruction state
|
||||
size_t is_being_used_count = 0;
|
||||
bool is_scratch = false;
|
||||
bool is_set_last_use = false;
|
||||
|
||||
// Block state
|
||||
size_t current_references = 0;
|
||||
@@ -140,6 +145,8 @@ public:
|
||||
|
||||
void AssertNoMoreUses();
|
||||
|
||||
void EmitVerboseDebuggingOutput();
|
||||
|
||||
private:
|
||||
friend struct Argument;
|
||||
|
||||
|
||||
29
src/dynarmic/backend/x64/verbose_debugging_output.cpp
Normal file
29
src/dynarmic/backend/x64/verbose_debugging_output.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2023 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include "dynarmic/backend/x64/verbose_debugging_output.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "dynarmic/backend/x64/hostloc.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr) {
|
||||
if (HostLocIsGPR(hostloc)) {
|
||||
const u64 value = reg_data.gprs[HostLocToReg64(hostloc).getIdx()];
|
||||
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, 0, value);
|
||||
} else if (HostLocIsXMM(hostloc)) {
|
||||
const Vector value = reg_data.xmms[HostLocToXmm(hostloc).getIdx()];
|
||||
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]);
|
||||
} else if (HostLocIsSpill(hostloc)) {
|
||||
const Vector value = (*reg_data.spill)[static_cast<size_t>(hostloc) - static_cast<size_t>(HostLoc::FirstSpill)];
|
||||
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]);
|
||||
} else {
|
||||
fmt::print("dynarmic debug: Invalid hostloc\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
36
src/dynarmic/backend/x64/verbose_debugging_output.h
Normal file
36
src/dynarmic/backend/x64/verbose_debugging_output.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2023 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/backend/x64/stack_layout.h"
|
||||
|
||||
namespace Dynarmic::Backend::X64 {
|
||||
|
||||
enum class HostLoc;
|
||||
using Vector = std::array<u64, 2>;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4324) // Structure was padded due to alignment specifier
|
||||
#endif
|
||||
|
||||
struct alignas(16) RegisterData {
|
||||
std::array<u64, 16> gprs;
|
||||
std::array<Vector, 16> xmms;
|
||||
decltype(StackLayout::spill)* spill;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr);
|
||||
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
@@ -231,6 +231,9 @@ struct UserConfig {
|
||||
// Minimum size is about 8MiB. Maximum size is about 128MiB (arm64 host) or 2GiB (x64 host).
|
||||
// Maximum size is limited by the maximum length of a x86_64 / arm64 jump.
|
||||
size_t code_cache_size = 128 * 1024 * 1024; // bytes
|
||||
|
||||
/// Internal use only
|
||||
bool very_verbose_debugging_output = false;
|
||||
};
|
||||
|
||||
} // namespace A32
|
||||
|
||||
@@ -288,6 +288,9 @@ struct UserConfig {
|
||||
// Minimum size is about 8MiB. Maximum size is about 128MiB (arm64 host) or 2GiB (x64 host).
|
||||
// Maximum size is limited by the maximum length of a x86_64 / arm64 jump.
|
||||
size_t code_cache_size = 128 * 1024 * 1024; // bytes
|
||||
|
||||
/// Internal use only
|
||||
bool very_verbose_debugging_output = false;
|
||||
};
|
||||
|
||||
} // namespace A64
|
||||
|
||||
Reference in New Issue
Block a user