mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-10-18 07:17:53 +00:00
[dynarmic] jit fix branch v2 (#203)
Co-authored-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/203 Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
This commit is contained in:
parent
c9a3baab5d
commit
21cd44ec04
67 changed files with 1214 additions and 876 deletions
|
@ -357,7 +357,7 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit,
|
|||
uni.ClearPageCache();
|
||||
|
||||
jit_env.ticks_left = ticks_left;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
uni_env.ticks_left = instructions.size(); // Unicorn counts thumb instructions weirdly.
|
||||
uni.Run();
|
||||
|
@ -445,6 +445,9 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit,
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Why the difference? QEMU what are you doing???
|
||||
jit.Regs()[15] = uni.GetRegisters()[15];
|
||||
|
||||
REQUIRE(uni.GetRegisters() == jit.Regs());
|
||||
REQUIRE(uni.GetExtRegs() == jit.ExtRegs());
|
||||
REQUIRE((uni.GetCpsr() & 0xFFFFFDDF) == (jit.Cpsr() & 0xFFFFFDDF));
|
||||
|
|
|
@ -130,7 +130,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn<Th
|
|||
test_env.code_mem_modified_by_guest = false;
|
||||
test_env.modified_memory.clear();
|
||||
test_env.ticks_left = instructions_to_execute_count;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
const bool jit_code_memory_modified = test_env.code_mem_modified_by_guest;
|
||||
const auto jit_write_records = test_env.modified_memory;
|
||||
test_env.code_mem_modified_by_guest = false;
|
||||
|
|
|
@ -38,7 +38,7 @@ TEST_CASE("arm: Opt Failure: Const folding in MostSignificantWord", "[arm][A32]"
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 6;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
// If we don't trigger the GetCarryFromOp ASSERT, we're fine.
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ TEST_CASE("arm: Unintended modification in SetCFlag", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 6;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 0x00000af1);
|
||||
REQUIRE(jit.Regs()[1] == 0x267ea626);
|
||||
|
@ -123,7 +123,7 @@ TEST_CASE("arm: shsax (Edge-case)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 0x3a3b8b18);
|
||||
REQUIRE(jit.Regs()[1] == 0x96156555);
|
||||
|
@ -162,7 +162,7 @@ TEST_CASE("arm: uasx (Edge-case)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[4] == 0x8ed38f4c);
|
||||
REQUIRE(jit.Regs()[5] == 0x0000261d);
|
||||
|
@ -200,7 +200,7 @@ TEST_CASE("arm: smuad (Edge-case)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 0x80000000);
|
||||
REQUIRE(jit.Regs()[1] == 0x80008000);
|
||||
|
@ -222,7 +222,7 @@ TEST_CASE("arm: Test InvalidateCacheRange", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 5);
|
||||
REQUIRE(jit.Regs()[1] == 13);
|
||||
|
@ -238,8 +238,8 @@ TEST_CASE("arm: Test InvalidateCacheRange", "[arm][A32]") {
|
|||
jit.Regs()[15] = 0;
|
||||
|
||||
test_env.ticks_left = 4;
|
||||
jit.Run();
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 5);
|
||||
REQUIRE(jit.Regs()[1] == 7);
|
||||
|
@ -347,7 +347,7 @@ TEST_CASE("arm: Test stepping", "[arm]") {
|
|||
}
|
||||
|
||||
test_env.ticks_left = 20;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[15] == 80);
|
||||
REQUIRE(jit.Cpsr() == 0x000001d0);
|
||||
|
@ -397,7 +397,7 @@ TEST_CASE("arm: Test stepping 2", "[arm]") {
|
|||
}
|
||||
|
||||
test_env.ticks_left = 20;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[15] == 80);
|
||||
REQUIRE(jit.Cpsr() == 0x000001d0);
|
||||
|
@ -427,7 +427,7 @@ TEST_CASE("arm: Test stepping 3", "[arm]") {
|
|||
REQUIRE(jit.Cpsr() == 0x000001d0);
|
||||
|
||||
test_env.ticks_left = 20;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[15] == 20);
|
||||
REQUIRE(jit.Cpsr() == 0x000001d0);
|
||||
|
@ -466,7 +466,7 @@ TEST_CASE("arm: PackedAbsDiffSumS8", "[arm][A32]") {
|
|||
jit.SetCpsr(0xb0000010);
|
||||
|
||||
test_env.ticks_left = 3;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 0xea85297c);
|
||||
REQUIRE(jit.Regs()[1] == 0x417ad918);
|
||||
|
@ -501,7 +501,7 @@ TEST_CASE("arm: vclt.f32 with zero", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.ExtRegs()[6] == 0x00000000);
|
||||
REQUIRE(jit.ExtRegs()[7] == 0x00000000);
|
||||
|
@ -521,7 +521,7 @@ TEST_CASE("arm: vcvt.s16.f64", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.ExtRegs()[16] == 0xffff8000);
|
||||
REQUIRE(jit.ExtRegs()[17] == 0xffffffff);
|
||||
|
@ -558,7 +558,7 @@ TEST_CASE("arm: Memory access (fastmem)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
env.ticks_left = 3;
|
||||
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(strncmp(backing_memory + 0x100, backing_memory + 0x1F0, 4) == 0);
|
||||
}
|
||||
|
||||
|
@ -581,7 +581,7 @@ TEST_CASE("arm: vmsr, vcmp, vmrs", "[arm][A32]") {
|
|||
jit.SetCpsr(0x60000000); // User-mode
|
||||
|
||||
test_env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
}
|
||||
|
||||
TEST_CASE("arm: sdiv maximally", "[arm][A32]") {
|
||||
|
@ -598,7 +598,7 @@ TEST_CASE("arm: sdiv maximally", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[2] == 0x80000000);
|
||||
}
|
||||
|
@ -637,7 +637,7 @@ TEST_CASE("arm: tbl", "[arm][A32]") {
|
|||
jit.ExtRegs()[23 * 2 + 1] = 0x1F'1E'1D'1C;
|
||||
|
||||
test_env.ticks_left = 5;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.ExtRegs()[16 * 2 + 0] == 0x05'02'01'00);
|
||||
REQUIRE(jit.ExtRegs()[16 * 2 + 1] == 0x00'00'00'00);
|
||||
|
@ -689,7 +689,7 @@ TEST_CASE("arm: tbx", "[arm][A32]") {
|
|||
jit.ExtRegs()[23 * 2 + 1] = 0x1F'1E'1D'1C;
|
||||
|
||||
test_env.ticks_left = 5;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.ExtRegs()[16 * 2 + 0] == 0x05'02'01'00);
|
||||
REQUIRE(jit.ExtRegs()[16 * 2 + 1] == 0x20'1F'10'0F);
|
||||
|
|
|
@ -156,7 +156,7 @@ TEST_CASE("arm: Test coprocessor (Read TPIDRURO)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[1] == 0xf00d);
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ TEST_CASE("arm: Test coprocessor (Read TPIDRURW)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[1] == 0xcafe);
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ TEST_CASE("arm: Test coprocessor (Write TPIDRURW)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(cp15_state.cp15_thread_uprw == 0xaaaa);
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ TEST_CASE("arm: Test coprocessor (DMB)", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(cp15_state.cp15_data_memory_barrier == 1);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ TEST_CASE("arm: svc", "[arm][A32]") {
|
|||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
test_env.ticks_left = 3;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(test_env.svc_called == 0x1ee);
|
||||
REQUIRE(jit.Regs()[15] == 0x00000008);
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST_CASE("thumb: lsls r0, r1, #2", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 8);
|
||||
REQUIRE(jit.Regs()[1] == 2);
|
||||
|
@ -54,7 +54,7 @@ TEST_CASE("thumb: lsls r0, r1, #31", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 0x80000000);
|
||||
REQUIRE(jit.Regs()[1] == 0xffffffff);
|
||||
|
@ -75,7 +75,7 @@ TEST_CASE("thumb: revsh r4, r3", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[3] == 0x12345678);
|
||||
REQUIRE(jit.Regs()[4] == 0x00007856);
|
||||
|
@ -96,7 +96,7 @@ TEST_CASE("thumb: ldr r3, [r3, #28]", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[3] == 0x97969594); // Memory location 0x12345694
|
||||
REQUIRE(jit.Regs()[15] == 2);
|
||||
|
@ -115,7 +115,7 @@ TEST_CASE("thumb: blx +#67712", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[14] == (0x4 | 1));
|
||||
REQUIRE(jit.Regs()[15] == 0x10880);
|
||||
|
@ -134,7 +134,7 @@ TEST_CASE("thumb: bl +#234584", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[14] == (0x4 | 1));
|
||||
REQUIRE(jit.Regs()[15] == 0x39458);
|
||||
|
@ -153,7 +153,7 @@ TEST_CASE("thumb: bl -#42", "[thumb]") {
|
|||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 1;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[14] == (0x4 | 1));
|
||||
REQUIRE(jit.Regs()[15] == 0xFFFFFFD6);
|
||||
|
@ -208,7 +208,7 @@ TEST_CASE("thumb: Opt Failure: Get/Set Elimination for Flags", "[thumb]") {
|
|||
jit.SetCpsr(0x000001f0); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 7;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.Regs()[0] == 0x2154abb5);
|
||||
REQUIRE(jit.Regs()[1] == 0xdbaa6333);
|
||||
|
@ -248,7 +248,7 @@ TEST_CASE("thumb: Opt Failure: Get/Set Elimination for Flags 2", "[thumb]") {
|
|||
jit.SetCpsr(0x000001f0); // Thumb, User-mode
|
||||
|
||||
test_env.ticks_left = 7;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
const std::array<u32, 16> expected = {0x954d53b0, 0x4caaad40, 0xb0afaead, 0x0da0cdb6, 0x0f43507e, 0xb4b3b2b1, 0x00000066, 0x892a6888,
|
||||
0x3b9ffb23, 0x0a92ef93, 0x38dee619, 0xc0e95e81, 0x6a448690, 0xc2d4d6b9, 0xe93600b9, 0x0000000a};
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "dynarmic/interface/A32/a32.h"
|
||||
#include "../native/testenv.h"
|
||||
|
||||
template<typename InstructionType_, u32 infinite_loop_u32>
|
||||
class A32TestEnv : public Dynarmic::A32::UserCallbacks {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <array>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
@ -23,7 +23,7 @@ namespace {
|
|||
class MyEnvironment final : public A64::UserCallbacks {
|
||||
public:
|
||||
u64 ticks_left = 0;
|
||||
std::map<u64, u8> memory{};
|
||||
std::unordered_map<u64, u8> memory{};
|
||||
|
||||
u8 MemoryRead8(u64 vaddr) override {
|
||||
return memory[vaddr];
|
||||
|
|
|
@ -87,7 +87,7 @@ void run_test(u32 instruction, Fn fn) {
|
|||
jit.SetPC(0);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.GetVector(0)[0] == fn(test_case));
|
||||
|
||||
|
@ -97,7 +97,7 @@ void run_test(u32 instruction, Fn fn) {
|
|||
jit.SetPC(0);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.GetVector(0)[0] == fn(test_case));
|
||||
|
||||
|
@ -109,7 +109,7 @@ void run_test(u32 instruction, Fn fn) {
|
|||
jit.SetPC(0);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.GetVector(0)[0] == force_default_nan(fn(test_case)));
|
||||
|
||||
|
@ -119,7 +119,7 @@ void run_test(u32 instruction, Fn fn) {
|
|||
jit.SetPC(0);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.GetVector(0)[0] == force_default_nan(fn(test_case)));
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ void run_test(u32 instruction, Fn fn) {
|
|||
jit.SetPC(0);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.GetVector(0)[0] == fn(test_case));
|
||||
|
||||
|
@ -148,7 +148,7 @@ void run_test(u32 instruction, Fn fn) {
|
|||
jit.SetPC(0);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
REQUIRE(jit.GetVector(0)[0] == force_default_nan(fn(test_case)));
|
||||
}
|
||||
|
|
|
@ -91,6 +91,9 @@ static u32 GenRandomInst(u64 pc, bool is_last_inst) {
|
|||
"MSR_reg",
|
||||
"MSR_imm",
|
||||
"MRS",
|
||||
// Does not need test
|
||||
"SVC",
|
||||
"BRK"
|
||||
};
|
||||
|
||||
for (const auto& [fn, bitstring] : list) {
|
||||
|
@ -198,9 +201,9 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv
|
|||
uni.ClearPageCache();
|
||||
|
||||
jit_env.ticks_left = instructions.size();
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
uni_env.ticks_left = instructions.size();
|
||||
uni_env.ticks_left = instructions.size() * 4;
|
||||
uni.Run();
|
||||
|
||||
SCOPE_FAIL {
|
||||
|
@ -296,7 +299,7 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv
|
|||
return;
|
||||
}
|
||||
|
||||
REQUIRE(uni.GetPC() == jit.GetPC());
|
||||
REQUIRE(uni.GetPC() + 4 == jit.GetPC());
|
||||
REQUIRE(uni.GetRegisters() == jit.GetRegisters());
|
||||
REQUIRE(uni.GetVectors() == jit.GetVectors());
|
||||
REQUIRE(uni.GetSP() == jit.GetSP());
|
||||
|
@ -306,7 +309,7 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv
|
|||
REQUIRE(FP::FPSR{uni.GetFpsr()}.QC() == FP::FPSR{jit.GetFpsr()}.QC());
|
||||
}
|
||||
|
||||
TEST_CASE("A64: Single random instruction", "[a64]") {
|
||||
TEST_CASE("A64: Single random instruction", "[a64][unicorn]") {
|
||||
A64TestEnv jit_env{};
|
||||
A64TestEnv uni_env{};
|
||||
|
||||
|
@ -333,7 +336,7 @@ TEST_CASE("A64: Single random instruction", "[a64]") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("A64: Floating point instructions", "[a64]") {
|
||||
TEST_CASE("A64: Floating point instructions", "[a64][unicorn]") {
|
||||
A64TestEnv jit_env{};
|
||||
A64TestEnv uni_env{};
|
||||
|
||||
|
@ -458,7 +461,7 @@ TEST_CASE("A64: Floating point instructions", "[a64]") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("A64: Small random block", "[a64]") {
|
||||
TEST_CASE("A64: Small random block", "[a64][unicorn]") {
|
||||
A64TestEnv jit_env{};
|
||||
A64TestEnv uni_env{};
|
||||
|
||||
|
@ -493,7 +496,7 @@ TEST_CASE("A64: Small random block", "[a64]") {
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("A64: Large random block", "[a64]") {
|
||||
TEST_CASE("A64: Large random block", "[a64][unicorn]") {
|
||||
A64TestEnv jit_env{};
|
||||
A64TestEnv uni_env{};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_ac
|
|||
jit.SetRegister(0, 0x000000000b0afff8);
|
||||
|
||||
env.ticks_left = 2;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
// If we don't crash we're fine.
|
||||
}
|
||||
|
|
102
src/dynarmic/tests/A64/real_world.cpp
Normal file
102
src/dynarmic/tests/A64/real_world.cpp
Normal file
File diff suppressed because one or more lines are too long
|
@ -27,38 +27,38 @@ TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have
|
|||
|
||||
jit.SetPC(100);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
jit.SetPC(100);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
jit.InvalidateCacheRange(108, 4);
|
||||
|
||||
jit.SetPC(100);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
env.code_mem[2] = 0xd28008a0; // MOV X0, 69
|
||||
|
||||
jit.SetPC(100);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
jit.InvalidateCacheRange(108, 4);
|
||||
|
||||
jit.SetPC(100);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 69);
|
||||
|
||||
jit.SetPC(100);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 69);
|
||||
}
|
||||
|
||||
|
@ -77,37 +77,37 @@ TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have
|
|||
|
||||
jit.SetPC(0);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
jit.SetPC(0);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
jit.InvalidateCacheRange(8, 4);
|
||||
|
||||
jit.SetPC(0);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
env.code_mem[2] = 0xd28008a0; // MOV X0, 69
|
||||
|
||||
jit.SetPC(0);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 42);
|
||||
|
||||
jit.InvalidateCacheRange(8, 4);
|
||||
|
||||
jit.SetPC(0);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 69);
|
||||
|
||||
jit.SetPC(0);
|
||||
env.ticks_left = 4;
|
||||
jit.Run();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
REQUIRE(jit.GetRegister(0) == 69);
|
||||
}
|
||||
|
|
|
@ -8,13 +8,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include <unordered_map>
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/common/common_types.h"
|
||||
|
||||
#include "dynarmic/interface/A64/a64.h"
|
||||
#include "../native/testenv.h"
|
||||
|
||||
using Vector = Dynarmic::A64::Vector;
|
||||
|
||||
|
@ -26,7 +24,7 @@ public:
|
|||
u64 code_mem_start_address = 0;
|
||||
std::vector<u32> code_mem;
|
||||
|
||||
std::map<u64, u8> modified_memory;
|
||||
std::unordered_map<u64, u8> modified_memory;
|
||||
std::vector<std::string> interrupts;
|
||||
|
||||
bool IsInCodeMem(u64 vaddr) const {
|
||||
|
@ -133,9 +131,9 @@ class A64FastmemTestEnv final : public Dynarmic::A64::UserCallbacks {
|
|||
public:
|
||||
u64 ticks_left = 0;
|
||||
char* backing_memory = nullptr;
|
||||
bool ignore_invalid_insn = false;
|
||||
|
||||
explicit A64FastmemTestEnv(char* addr)
|
||||
: backing_memory(addr) {}
|
||||
explicit A64FastmemTestEnv(char* addr) : backing_memory(addr) {}
|
||||
|
||||
template<typename T>
|
||||
T read(u64 vaddr) {
|
||||
|
@ -205,7 +203,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(false, "InterpreterFallback({:016x}, {})", pc, num_instructions); }
|
||||
void InterpreterFallback(u64 pc, size_t num_instructions) override { ASSERT_MSG(ignore_invalid_insn, "InterpreterFallback({:016x}, {})", pc, num_instructions); }
|
||||
|
||||
void CallSVC(std::uint32_t swi) override { ASSERT_MSG(false, "CallSVC({})", swi); }
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
using namespace Dynarmic;
|
||||
|
||||
TEST_CASE("Unicorn: Sanity test", "[a64]") {
|
||||
TEST_CASE("Unicorn: Sanity test", "[a64][unicorn]") {
|
||||
A64TestEnv env;
|
||||
|
||||
env.code_mem.emplace_back(0x8b020020); // ADD X0, X1, X2
|
||||
|
@ -39,7 +39,7 @@ TEST_CASE("Unicorn: Sanity test", "[a64]") {
|
|||
REQUIRE(unicorn.GetPC() == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") {
|
||||
TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64][unicorn]") {
|
||||
A64TestEnv env;
|
||||
|
||||
env.code_mem.emplace_back(0x385fed99); // LDRB W25, [X12, #0xfffffffffffffffe]!
|
||||
|
@ -59,7 +59,7 @@ TEST_CASE("Unicorn: Ensure 0xFFFF'FFFF'FFFF'FFFF is readable", "[a64]") {
|
|||
REQUIRE(unicorn.GetPC() == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("Unicorn: Ensure is able to read across page boundaries", "[a64]") {
|
||||
TEST_CASE("Unicorn: Ensure is able to read across page boundaries", "[a64][unicorn]") {
|
||||
A64TestEnv env;
|
||||
|
||||
env.code_mem.emplace_back(0xb85f93d9); // LDUR W25, [X30, #0xfffffffffffffff9]
|
||||
|
|
|
@ -29,6 +29,7 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS)
|
|||
A64/fp_min_max.cpp
|
||||
A64/misaligned_page_table.cpp
|
||||
A64/test_invalidation.cpp
|
||||
A64/real_world.cpp
|
||||
A64/testenv.h
|
||||
)
|
||||
endif()
|
||||
|
@ -66,11 +67,14 @@ endif()
|
|||
|
||||
if ("x86_64" IN_LIST ARCHITECTURE)
|
||||
target_link_libraries(dynarmic_tests PRIVATE xbyak::xbyak)
|
||||
|
||||
target_architecture_specific_sources(dynarmic_tests "x86_64"
|
||||
x64_cpu_info.cpp
|
||||
)
|
||||
|
||||
target_architecture_specific_sources(dynarmic_tests "x86_64"
|
||||
native/preserve_xmm.cpp
|
||||
)
|
||||
|
||||
if (NOT MSVC AND NOT DYNARMIC_MULTIARCH_BUILD)
|
||||
target_sources(dynarmic_tests PRIVATE
|
||||
rsqrt_test.cpp
|
||||
|
@ -129,4 +133,6 @@ target_include_directories(dynarmic_tests PRIVATE . ../src)
|
|||
target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS})
|
||||
target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=1)
|
||||
|
||||
target_compile_options(dynarmic_tests PRIVATE -mavx2)
|
||||
|
||||
add_test(dynarmic_tests dynarmic_tests --durations yes)
|
||||
|
|
64
src/dynarmic/tests/native/preserve_xmm.cpp
Normal file
64
src/dynarmic/tests/native/preserve_xmm.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <oaknut/oaknut.hpp>
|
||||
#include <immintrin.h>
|
||||
|
||||
#include "../A64/testenv.h"
|
||||
#include "dynarmic/common/fp/fpsr.h"
|
||||
#include "dynarmic/interface/exclusive_monitor.h"
|
||||
|
||||
using namespace Dynarmic;
|
||||
using namespace oaknut::util;
|
||||
|
||||
TEST_CASE("X86: Preserve XMM regs", "[x86]") {
|
||||
A64TestEnv env;
|
||||
A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &env;
|
||||
A64::Jit jit{jit_user_config};
|
||||
|
||||
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
|
||||
code.SMINP(V2.S2(), V0.S2(), V1.S2());
|
||||
code.UMINP(V3.S2(), V0.S2(), V1.S2());
|
||||
code.SMINP(V4.S4(), V0.S4(), V1.S4());
|
||||
code.UMINP(V5.S4(), V0.S4(), V1.S4());
|
||||
code.SMAXP(V6.S2(), V0.S2(), V1.S2());
|
||||
code.UMAXP(V7.S2(), V0.S2(), V1.S2());
|
||||
code.SMAXP(V8.S4(), V0.S4(), V1.S4());
|
||||
code.UMAXP(V9.S4(), V0.S4(), V1.S4());
|
||||
|
||||
constexpr std::array<Vector, 12> vectors = {
|
||||
// initial input vectors [0-1]
|
||||
Vector{0x00000003'00000002, 0xF1234567'01234567},
|
||||
Vector{0x80000000'7FFFFFFF, 0x76543210'76543209},
|
||||
// expected output vectors [2-9]
|
||||
Vector{0x80000000'00000002, 0},
|
||||
Vector{0x7FFFFFFF'00000002, 0},
|
||||
Vector{0xF1234567'00000002, 0x76543209'80000000},
|
||||
Vector{0x01234567'00000002, 0x76543209'7FFFFFFF},
|
||||
Vector{0x7FFFFFFF'00000003, 0},
|
||||
Vector{0x80000000'00000003, 0},
|
||||
Vector{0x01234567'00000003, 0x76543210'7FFFFFFF},
|
||||
Vector{0xF1234567'00000003, 0x76543210'80000000},
|
||||
// input vectors with elements swapped pairwise [10-11]
|
||||
Vector{0x00000002'00000003, 0x01234567'F1234567},
|
||||
Vector{0x7FFFFFFF'80000000, 0x76543209'76543210},
|
||||
};
|
||||
|
||||
jit.SetPC(0);
|
||||
jit.SetVector(0, vectors[0]);
|
||||
jit.SetVector(1, vectors[1]);
|
||||
|
||||
env.ticks_left = env.code_mem.size();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
CHECK(jit.GetVector(2) == vectors[2]);
|
||||
CHECK(jit.GetVector(3) == vectors[3]);
|
||||
CHECK(jit.GetVector(4) == vectors[4]);
|
||||
CHECK(jit.GetVector(5) == vectors[5]);
|
||||
CHECK(jit.GetVector(6) == vectors[6]);
|
||||
CHECK(jit.GetVector(7) == vectors[7]);
|
||||
CHECK(jit.GetVector(8) == vectors[8]);
|
||||
CHECK(jit.GetVector(9) == vectors[9]);
|
||||
}
|
50
src/dynarmic/tests/native/testenv.h
Normal file
50
src/dynarmic/tests/native/testenv.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#ifdef __AVX__
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
template<typename F>
|
||||
void CheckedRun(F&& fn) {
|
||||
#ifdef __AVX__
|
||||
__m256i xmm0 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
__m256i xmm1 = _mm256_set_epi32(1, 1, 0, 0, 0, 0, 0, 1);
|
||||
__m256i xmm2 = _mm256_set_epi32(2, 2, 0, 0, 0, 0, 0, 2);
|
||||
__m256i xmm3 = _mm256_set_epi32(3, 3, 0, 0, 0, 0, 0, 3);
|
||||
__m256i xmm4 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 4);
|
||||
__m256i xmm5 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 5);
|
||||
__m256i xmm6 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 6);
|
||||
__m256i xmm7 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 7);
|
||||
__m256i xmm8 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 8);
|
||||
__m256i xmm9 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 9);
|
||||
__m256i xmm10 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 10);
|
||||
__m256i xmm11 = _mm256_set_epi32(4, 4, 0, 0, 0, 0, 0, 11);
|
||||
asm volatile(""
|
||||
: "+x"(xmm0), "+x"(xmm1), "+x"(xmm2), "+x"(xmm3)
|
||||
, "+x"(xmm4), "+x"(xmm5), "+x"(xmm6), "+x"(xmm7)
|
||||
, "+x"(xmm8), "+x"(xmm9), "+x"(xmm10), "+x"(xmm11)
|
||||
:
|
||||
);
|
||||
fn();
|
||||
asm volatile(""
|
||||
: "+x"(xmm0), "+x"(xmm1), "+x"(xmm2), "+x"(xmm3)
|
||||
, "+x"(xmm4), "+x"(xmm5), "+x"(xmm6), "+x"(xmm7)
|
||||
, "+x"(xmm8), "+x"(xmm9), "+x"(xmm10), "+x"(xmm11)
|
||||
:
|
||||
);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm0[0]) == 0);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm1[0]) == 1);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm2[0]) == 2);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm3[0]) == 3);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm4[0]) == 4);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm5[0]) == 5);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm6[0]) == 6);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm7[0]) == 7);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm8[0]) == 8);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm9[0]) == 9);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm10[0]) == 10);
|
||||
CHECK(std::bit_cast<std::uint64_t>(xmm11[0]) == 11);
|
||||
#else
|
||||
fn();
|
||||
#endif
|
||||
}
|
|
@ -173,7 +173,7 @@ void A64Unicorn::InterruptHook(uc_engine* uc, u32 int_number, void* user_data) {
|
|||
auto* this_ = static_cast<A64Unicorn*>(user_data);
|
||||
|
||||
u32 esr;
|
||||
CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR, &esr));
|
||||
//CHECKED(uc_reg_read(uc, UC_ARM64_REG_ESR_EL0, &esr));
|
||||
|
||||
auto ec = esr >> 26;
|
||||
auto iss = esr & 0xFFFFFF;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue