From 0869c26b4f4ebf7bf14e5b5a797cd3050e6d6767 Mon Sep 17 00:00:00 2001 From: Merry Date: Thu, 29 Dec 2022 17:16:06 +0000 Subject: [PATCH] tests/fp_min_max: Add a few more test cases --- tests/A64/a64.cpp | 18 +++++++++ tests/A64/fp_min_max.cpp | 83 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/tests/A64/a64.cpp b/tests/A64/a64.cpp index dfed240b..395482c2 100644 --- a/tests/A64/a64.cpp +++ b/tests/A64/a64.cpp @@ -702,6 +702,24 @@ TEST_CASE("A64: FMAXNM (example)", "[a64]") { REQUIRE(jit.GetVector(2) == Vector{0x7fc0000009503366, 0x3ff0000000000000}); } +TEST_CASE("A64: FMAXNM (example 2)", "[a64]") { + A64TestEnv env; + A64::Jit jit{A64::UserConfig{&env}}; + + env.code_mem.emplace_back(0x4e3bc6fd); // FMAXNM.4S V29, V23, V27 + env.code_mem.emplace_back(0x14000000); // B . + + jit.SetPC(0); + jit.SetFpcr(0x01400000); + jit.SetVector(23, {0xb485877c'42280000, 0x317285d3'b5c8e5d3}); + jit.SetVector(27, {0xbc48d091'c79b271e, 0xff800001'3304c3ef}); + + env.ticks_left = 2; + jit.Run(); + + REQUIRE(jit.GetVector(29) == Vector{0xb485877c'42280000, 0xffc00001'3304c3ef}); +} + TEST_CASE("A64: 128-bit exclusive read/write", "[a64]") { A64TestEnv env; ExclusiveMonitor monitor{1}; diff --git a/tests/A64/fp_min_max.cpp b/tests/A64/fp_min_max.cpp index 4dc65d9c..9e5e11b8 100644 --- a/tests/A64/fp_min_max.cpp +++ b/tests/A64/fp_min_max.cpp @@ -31,28 +31,50 @@ const std::vector test_cases{ 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{0x7fc00041, 0x7fc00041, 0x7fc00041, 0x7fc00041, 0x7fc00041, 0x7fc00041}, // 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{0x7f800000, 0xff800000, 0x7f800000, 0x7f800000, 0xff800000, 0xff800000}, // (+Inf, -Inf) + TestCase{0x3f800000, 0x7fc00041, 0x7fc00041, 0x3f800000, 0x7fc00041, 0x3f800000}, // (+1.0, QNaN) TestCase{0x3f800000, 0x7f800042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // (+1.0, SNaN) + TestCase{0x7f800000, 0x7fc00041, 0x7fc00041, 0x7f800000, 0x7fc00041, 0x7f800000}, // (+Inf, QNaN) + TestCase{0x7f800000, 0x7f800042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // (+Inf, SNaN) + TestCase{0x7fc00041, 0x7f800042, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // (QNaN, SNaN) + TestCase{0xffa57454, 0xe343a6b3, 0xffe57454, 0xffe57454, 0xffe57454, 0xffe57454}, }; +const std::vector unidirectional_test_cases{ + TestCase{0x7fc00041, 0x7fc00043, 0x7fc00041, 0x7fc00041, 0x7fc00041, 0x7fc00041}, // (QNaN, QNaN) + TestCase{0x7f800042, 0x7f800044, 0x7fc00042, 0x7fc00042, 0x7fc00042, 0x7fc00042}, // (SNaN, SNaN) +}; + +constexpr u32 default_nan = 0x7fc00000; + +bool is_nan(u32 value) { + return (value & 0x7f800000) == 0x7f800000 && (value & 0x007fffff) != 0; +} + +u32 force_default_nan(u32 value) { + return is_nan(value) ? default_nan : value; +} + 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 . + env.code_mem.emplace_back(instruction); // FMAX S0, S1, S2 + env.code_mem.emplace_back(0x14000000); // B . + for (const auto test_case : test_cases) { INFO(test_case.a); INFO(test_case.b); + jit.SetFpcr(0); + jit.SetVector(0, {42, 0}); jit.SetVector(1, {test_case.a, 0}); jit.SetVector(2, {test_case.b, 0}); @@ -72,6 +94,57 @@ void run_test(u32 instruction, Fn fn) { jit.Run(); REQUIRE(jit.GetVector(0)[0] == fn(test_case)); + + jit.SetFpcr(0x02000000); + + 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] == force_default_nan(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] == force_default_nan(fn(test_case))); + } + + for (const auto test_case : unidirectional_test_cases) { + INFO(test_case.a); + INFO(test_case.b); + + jit.SetFpcr(0); + + 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.SetFpcr(0x02000000); + + 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] == force_default_nan(fn(test_case))); } }