From c804b3980d2fb67379c1f62e9de845b14588922a Mon Sep 17 00:00:00 2001 From: Merry Date: Thu, 29 Dec 2022 17:01:17 +0000 Subject: [PATCH] tests: Add FMAX/FMIN/FMAXNM/FMINNM tests --- tests/A64/a64.cpp | 8 +-- tests/A64/fp_min_max.cpp | 110 +++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + 3 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 tests/A64/fp_min_max.cpp diff --git a/tests/A64/a64.cpp b/tests/A64/a64.cpp index 5edc7730..dfed240b 100644 --- a/tests/A64/a64.cpp +++ b/tests/A64/a64.cpp @@ -614,7 +614,7 @@ TEST_CASE("A64: FABS", "[a64]") { REQUIRE(jit.GetVector(6) == Vector{0x7fffffffffffffff, 0x0000000000000000}); } -TEST_CASE("A64: FMIN", "[a64]") { +TEST_CASE("A64: FMIN (example)", "[a64]") { A64TestEnv env; A64::Jit jit{A64::UserConfig{&env}}; @@ -636,7 +636,7 @@ TEST_CASE("A64: FMIN", "[a64]") { REQUIRE(jit.GetVector(2) == Vector{0xbff0000000000000, 0x3ff0000000000000}); } -TEST_CASE("A64: FMAX", "[a64]") { +TEST_CASE("A64: FMAX (example)", "[a64]") { A64TestEnv env; A64::Jit jit{A64::UserConfig{&env}}; @@ -658,7 +658,7 @@ TEST_CASE("A64: FMAX", "[a64]") { REQUIRE(jit.GetVector(2) == Vector{0x7fc0000009503366, 0x6e4b0a41ffffffff}); } -TEST_CASE("A64: FMINNM", "[a64]") { +TEST_CASE("A64: FMINNM (example)", "[a64]") { A64TestEnv env; A64::Jit jit{A64::UserConfig{&env}}; @@ -680,7 +680,7 @@ TEST_CASE("A64: FMINNM", "[a64]") { REQUIRE(jit.GetVector(2) == Vector{0xfff0000000000000, 0x3ff0000000000000}); } -TEST_CASE("A64: FMAXNM", "[a64]") { +TEST_CASE("A64: FMAXNM (example)", "[a64]") { A64TestEnv env; A64::Jit jit{A64::UserConfig{&env}}; diff --git a/tests/A64/fp_min_max.cpp b/tests/A64/fp_min_max.cpp new file mode 100644 index 00000000..4dc65d9c --- /dev/null +++ b/tests/A64/fp_min_max.cpp @@ -0,0 +1,110 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2022 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include + +#include +#include + +#include "./testenv.h" + +using namespace Dynarmic; + +namespace { + +struct TestCase { + u32 a; + u32 b; + u32 fmax; + u32 fmaxnm; + u32 fmin; + u32 fminnm; +}; + +const std::vector test_cases{ + // a b fmax fmaxnm fmin fminnm + TestCase{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, // +0.0 + TestCase{0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, // -0.0 + TestCase{0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000}, // +1.0 + TestCase{0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000, 0xbf800000}, // -1.0 + TestCase{0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000}, // +Inf + TestCase{0xff800000, 0xff800000, 0xff800000, 0xff800000, 0xff800000, 0xff800000}, // -Inf + TestCase{0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // QNaN + TestCase{0x7f800042, 0x7f800042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // SNaN + TestCase{0x00000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000}, // (+0.0, -0.0) + TestCase{0x3f800000, 0xbf800000, 0x3f800000, 0x3f800000, 0xbf800000, 0xbf800000}, // (+1.0, -1.0) + TestCase{0x3f800000, 0x7f800000, 0x7f800000, 0x7f800000, 0x3f800000, 0x3f800000}, // (+1.0, +Inf) + TestCase{0x3f800000, 0xff800000, 0x3f800000, 0x3f800000, 0xff800000, 0xff800000}, // (+1.0, -Inf) + TestCase{0x3f800000, 0x7fc00042, 0x7fc00042, 0x3f800000, 0x7fc00042, 0x3f800000}, // (+1.0, QNaN) + TestCase{0x3f800000, 0x7f800042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // (+1.0, SNaN) +}; + +template +void run_test(u32 instruction, Fn fn) { + A64TestEnv env; + A64::Jit jit{A64::UserConfig{&env}}; + + for (const auto test_case : test_cases) { + env.code_mem.emplace_back(instruction); // FMAX S0, S1, S2 + env.code_mem.emplace_back(0x14000000); // B . + + INFO(test_case.a); + INFO(test_case.b); + + jit.SetVector(0, {42, 0}); + jit.SetVector(1, {test_case.a, 0}); + jit.SetVector(2, {test_case.b, 0}); + jit.SetPC(0); + + env.ticks_left = 2; + jit.Run(); + + REQUIRE(jit.GetVector(0)[0] == fn(test_case)); + + jit.SetVector(0, {42, 0}); + jit.SetVector(1, {test_case.b, 0}); + jit.SetVector(2, {test_case.a, 0}); + jit.SetPC(0); + + env.ticks_left = 2; + jit.Run(); + + REQUIRE(jit.GetVector(0)[0] == fn(test_case)); + } +} + +} // namespace + +TEST_CASE("A64: FMAX (scalar)", "[a64]") { + run_test(0x1e224820, [](const TestCase& test_case) { return test_case.fmax; }); +} + +TEST_CASE("A64: FMIN (scalar)", "[a64]") { + run_test(0x1e225820, [](const TestCase& test_case) { return test_case.fmin; }); +} + +TEST_CASE("A64: FMAXNM (scalar)", "[a64]") { + run_test(0x1e226820, [](const TestCase& test_case) { return test_case.fmaxnm; }); +} + +TEST_CASE("A64: FMINNM (scalar)", "[a64]") { + run_test(0x1e227820, [](const TestCase& test_case) { return test_case.fminnm; }); +} + +TEST_CASE("A64: FMAX (vector)", "[a64]") { + run_test(0x4e22f420, [](const TestCase& test_case) { return test_case.fmax; }); +} + +TEST_CASE("A64: FMIN (vector)", "[a64]") { + run_test(0x4ea2f420, [](const TestCase& test_case) { return test_case.fmin; }); +} + +TEST_CASE("A64: FMAXNM (vector)", "[a64]") { + run_test(0x4e22c420, [](const TestCase& test_case) { return test_case.fmaxnm; }); +} + +TEST_CASE("A64: FMINNM (vector)", "[a64]") { + run_test(0x4ea2c420, [](const TestCase& test_case) { return test_case.fminnm; }); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index efdfa014..849f8e18 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ endif() if ("A64" IN_LIST DYNARMIC_FRONTENDS) target_sources(dynarmic_tests PRIVATE A64/a64.cpp + A64/fp_min_max.cpp A64/misaligned_page_table.cpp A64/test_invalidation.cpp A64/testenv.h