aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/A64/a64.cpp8
-rw-r--r--tests/A64/fp_min_max.cpp110
-rw-r--r--tests/CMakeLists.txt1
3 files changed, 115 insertions, 4 deletions
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 <vector>
+
+#include <catch2/catch.hpp>
+#include <mcl/stdint.hpp>
+
+#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<typename Fn>
+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