diff options
author | Merry <[email protected]> | 2023-01-16 00:25:41 +0000 |
---|---|---|
committer | Merry <[email protected]> | 2023-01-16 00:42:18 +0000 |
commit | ffc3dce9b122c82c68dc337f280fa2ab1522c317 (patch) | |
tree | a2aef2df451a056b56412e9de9f97bf5b2fdef6e /tests | |
parent | f865bbbad2a9d596f832cdc69b7e2ec4f87abb6a (diff) | |
download | dynarmic-ffc3dce9b122c82c68dc337f280fa2ab1522c317.tar.gz dynarmic-ffc3dce9b122c82c68dc337f280fa2ab1522c317.zip |
tests: Add verbose debugging output and test_reader
Diffstat (limited to 'tests')
-rw-r--r-- | tests/CMakeLists.txt | 13 | ||||
-rw-r--r-- | tests/test_generator.cpp | 6 | ||||
-rw-r--r-- | tests/test_reader.cpp | 208 |
3 files changed, 221 insertions, 6 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e52f4da4..7277bc94 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -102,6 +102,19 @@ if (("A32" IN_LIST DYNARMIC_FRONTENDS) AND ("A64" IN_LIST DYNARMIC_FRONTENDS)) target_compile_definitions(dynarmic_test_generator PRIVATE FMT_USE_USER_DEFINED_LITERALS=1) endif() +if (("A32" IN_LIST DYNARMIC_FRONTENDS) AND ("A64" IN_LIST DYNARMIC_FRONTENDS)) + add_executable(dynarmic_test_reader + test_reader.cpp + ) + + create_target_directory_groups(dynarmic_test_reader) + + target_link_libraries(dynarmic_test_reader PRIVATE dynarmic Boost::boost fmt::fmt merry::mcl) + target_include_directories(dynarmic_test_reader PRIVATE . ../src) + target_compile_options(dynarmic_test_reader PRIVATE ${DYNARMIC_CXX_FLAGS}) + target_compile_definitions(dynarmic_test_reader PRIVATE FMT_USE_USER_DEFINED_LITERALS=1) +endif() + create_target_directory_groups(dynarmic_tests) target_link_libraries(dynarmic_tests PRIVATE dynarmic Boost::boost Catch2::Catch2WithMain fmt::fmt merry::mcl) diff --git a/tests/test_generator.cpp b/tests/test_generator.cpp index 938aff4d..00bfd73c 100644 --- a/tests/test_generator.cpp +++ b/tests/test_generator.cpp @@ -40,12 +40,6 @@ #include <fmt/format.h> #include <fmt/ostream.h> -#if defined(__APPLE__) && defined(MCL_ARCHITECTURE_ARM64) -# include <mach/mach_init.h> -# include <mach/mach_port.h> -# include <mach/task.h> -#endif - constexpr bool mask_fpsr_cum_bits = true; namespace { diff --git a/tests/test_reader.cpp b/tests/test_reader.cpp new file mode 100644 index 00000000..c0ddac28 --- /dev/null +++ b/tests/test_reader.cpp @@ -0,0 +1,208 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2023 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include <array> +#include <iostream> +#include <string> +#include <string_view> +#include <vector> + +#include <fmt/format.h> +#include <mcl/stdint.hpp> + +#include "./A64/testenv.h" +#include "dynarmic/common/fp/fpsr.h" +#include "dynarmic/interface/A64/a64.h" + +using namespace Dynarmic; + +A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env) { + A64::UserConfig jit_user_config{&jit_env}; + jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch; + // The below corresponds to the settings for qemu's aarch64_max_initfn + jit_user_config.dczid_el0 = 7; + jit_user_config.ctr_el0 = 0x80038003; + jit_user_config.very_verbose_debugging_output = true; + return jit_user_config; +} + +template<size_t num_jit_reruns = 1> +void RunTestInstance(A64::Jit& jit, + A64TestEnv& jit_env, + const std::array<u64, 31>& regs, + const std::array<std::array<u64, 2>, 32>& vecs, + const std::vector<u32>& instructions, + const u32 pstate, + const u32 fpcr, + const u64 initial_sp, + const u64 start_address, + const size_t ticks_left) { + jit.ClearCache(); + + for (size_t jit_rerun_count = 0; jit_rerun_count < num_jit_reruns; ++jit_rerun_count) { + jit_env.code_mem = instructions; + jit_env.code_mem.emplace_back(0x14000000); // B . + jit_env.code_mem_start_address = start_address; + jit_env.modified_memory.clear(); + jit_env.interrupts.clear(); + + jit.SetRegisters(regs); + jit.SetVectors(vecs); + jit.SetPC(start_address); + jit.SetSP(initial_sp); + jit.SetFpcr(fpcr); + jit.SetFpsr(0); + jit.SetPstate(pstate); + jit.ClearCache(); + + jit_env.ticks_left = ticks_left; + jit.Run(); + } + + fmt::print("instructions:"); + for (u32 instruction : instructions) { + fmt::print(" {:08x}", instruction); + } + fmt::print("\n"); + + fmt::print("initial_regs:"); + for (u64 i : regs) { + fmt::print(" {:016x}", i); + } + fmt::print("\n"); + fmt::print("initial_vecs:"); + for (auto i : vecs) { + fmt::print(" {:016x}:{:016x}", i[0], i[1]); + } + fmt::print("\n"); + fmt::print("initial_sp: {:016x}\n", initial_sp); + fmt::print("initial_pstate: {:08x}\n", pstate); + fmt::print("initial_fpcr: {:08x}\n", fpcr); + + fmt::print("final_regs:"); + for (u64 i : jit.GetRegisters()) { + fmt::print(" {:016x}", i); + } + fmt::print("\n"); + fmt::print("final_vecs:"); + for (auto i : jit.GetVectors()) { + fmt::print(" {:016x}:{:016x}", i[0], i[1]); + } + fmt::print("\n"); + fmt::print("final_sp: {:016x}\n", jit.GetSP()); + fmt::print("final_pc: {:016x}\n", jit.GetPC()); + fmt::print("final_pstate: {:08x}\n", jit.GetPstate()); + fmt::print("final_fpcr: {:08x}\n", jit.GetFpcr()); + fmt::print("final_qc : {}\n", FP::FPSR{jit.GetFpsr()}.QC()); + + fmt::print("mod_mem:"); + for (auto [addr, value] : jit_env.modified_memory) { + fmt::print(" {:08x}:{:02x}", addr, value); + } + fmt::print("\n"); + + fmt::print("interrupts:\n"); + for (const auto& i : jit_env.interrupts) { + std::puts(i.c_str()); + } + + fmt::print("===\n"); +} + +int main() { + std::array<u64, 31> initial_regs{}; + std::array<std::array<u64, 2>, 32> initial_vecs{}; + std::vector<u32> instructions{}; + u32 initial_pstate = 0; + u32 initial_fpcr = 0; + u64 initial_sp = 0; + u64 start_address = 100; + + std::string line; + while (std::getline(std::cin, line)) { + std::string_view sv{line}; + + const auto skip_ws = [&] { + auto nextpos{sv.find_first_not_of(' ')}; + if (nextpos != std::string::npos) { + sv.remove_prefix(nextpos); + } + }; + const auto skip_header = [&] { + sv.remove_prefix(sv.find_first_of(':') + 1); + skip_ws(); + }; + const auto next_token = [&] { + auto nextpos{sv.find_first_of(' ')}; + auto tok{sv.substr(0, nextpos)}; + sv.remove_prefix(nextpos == std::string::npos ? sv.size() : nextpos); + skip_ws(); + return tok; + }; + const auto parse_hex = [&](std::string_view hex) { + u64 result = 0; + while (!hex.empty()) { + result <<= 4; + if (hex.front() >= '0' && hex.front() <= '9') { + result += hex.front() - '0'; + } else if (hex.front() >= 'a' && hex.front() <= 'f') { + result += hex.front() - 'a' + 0xA; + } else if (hex.front() >= 'A' && hex.front() <= 'F') { + result += hex.front() - 'A' + 0xA; + } else if (hex.front() == ':') { + return result; + } else { + fmt::print("Character {} is not a valid hex character\n", hex.front()); + } + hex.remove_prefix(1); + } + return result; + }; + + if (sv.starts_with("instructions:")) { + skip_header(); + while (!sv.empty()) { + instructions.emplace_back((u32)parse_hex(next_token())); + } + } else if (sv.starts_with("initial_regs:")) { + skip_header(); + for (size_t i = 0; i < initial_regs.size(); ++i) { + initial_regs[i] = parse_hex(next_token()); + } + } else if (sv.starts_with("initial_vecs:")) { + skip_header(); + for (size_t i = 0; i < initial_vecs.size(); ++i) { + auto tok{next_token()}; + initial_vecs[i][0] = parse_hex(tok); + tok.remove_prefix(tok.find_first_of(':') + 1); + initial_vecs[i][1] = parse_hex(tok); + } + } else if (sv.starts_with("initial_sp:")) { + skip_header(); + initial_sp = parse_hex(next_token()); + } else if (sv.starts_with("initial_pstate:")) { + skip_header(); + initial_pstate = (u32)parse_hex(next_token()); + } else if (sv.starts_with("initial_fpcr:")) { + skip_header(); + initial_fpcr = (u32)parse_hex(next_token()); + } + } + + A64TestEnv jit_env{}; + A64::Jit jit{GetA64UserConfig(jit_env)}; + RunTestInstance(jit, + jit_env, + initial_regs, + initial_vecs, + instructions, + initial_pstate, + initial_fpcr, + initial_sp, + start_address, + instructions.size()); + + return 0; +} |