aboutsummaryrefslogtreecommitdiff
path: root/src/tests/video_core
diff options
context:
space:
mode:
authorxtam <jj.tobola2@gmail.com>2026-10-30 21:49:15 +0100
committerxtam <jj.tobola2@gmail.com>2026-10-30 21:49:15 +0100
commita4a746b47b1d1ee02ddf1fe528c7db05800eec2c (patch)
tree320fd13bf6ceb1e8e88b0164ed0e1c5d9a714a3f /src/tests/video_core
parent3e950dd677b6d7dca04541855ad5751d057371ea (diff)
fix: restore Mario Kart World text by accepting R0 shader returns
Do not treat the reserved destination field of Ampere RET as a write to the return-link register. Keep return linkage validation and rejection of actual link-register writes. Add three regression tests covering R0 and R55 links, copied links, and overwritten links. Validation: 10 assertions pass; user confirmed the compiled patch restores text in Mario Kart World. AI-assisted implementation and commit message using OpenAI Codex.
Diffstat (limited to 'src/tests/video_core')
-rw-r--r--src/tests/video_core/ampere_returns.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/tests/video_core/ampere_returns.cpp b/src/tests/video_core/ampere_returns.cpp
new file mode 100644
index 0000000000..56b8b374da
--- /dev/null
+++ b/src/tests/video_core/ampere_returns.cpp
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include <array>
+#include <catch2/catch_test_macros.hpp>
+
+#include "shader_recompiler/frontend/ampere/lower_to_maxwell.h"
+
+namespace {
+using Shader::Ampere::Instruction;
+using Shader::Ampere::LowerToMaxwell;
+
+TEST_CASE("Ampere returns do not write the link register", "[video_core][ampere]") {
+ for (const u32 link : {0U, 55U}) {
+ const std::array<Instruction, 4> code{{
+ {{0x00007802U | (link << 16), 0x20, 0x00000f00, 0}},
+ {{0x00007944, 0x10, 0x03c00000, 0}},
+ {{0x0000794d, 0, 0x03800000, 0}},
+ {{0x00007950U | (link << 24), 0xffffffc0, 0x03c3ffff, 0}},
+ }};
+ const auto lowered = LowerToMaxwell(code);
+ REQUIRE(static_cast<bool>(lowered));
+ REQUIRE(lowered.source_size == sizeof(code));
+ REQUIRE(lowered.instructions.back() == 0xe32000000007000fULL);
+ }
+}
+
+TEST_CASE("Ampere returns can read a copy of the R0 link", "[video_core][ampere]") {
+ const std::array<Instruction, 5> code{{
+ {{0x00007802, 0x20, 0x00000f00, 0}},
+ {{0x00007944, 0x10, 0x03c00000, 0}},
+ {{0x0000794d, 0, 0x03800000, 0}},
+ {{0x00017202, 0, 0x00000f00, 0}},
+ {{0x01007950, 0xffffffb0, 0x03c3ffff, 0}},
+ }};
+ REQUIRE(static_cast<bool>(LowerToMaxwell(code)));
+}
+
+TEST_CASE("Ampere callees still reject writes to the link", "[video_core][ampere]") {
+ const std::array<Instruction, 5> code{{
+ {{0x00007802, 0x20, 0x00000f00, 0}},
+ {{0x00007944, 0x10, 0x03c00000, 0}},
+ {{0x0000794d, 0, 0x03800000, 0}},
+ {{0x00007802, 0, 0x00000f00, 0}},
+ {{0x00007950, 0xffffffb0, 0x03c3ffff, 0}},
+ }};
+ const auto lowered = LowerToMaxwell(code);
+ REQUIRE(!static_cast<bool>(lowered));
+ REQUIRE(lowered.error == "native callee overwrites link register");
+ REQUIRE(lowered.error_offset == 0x30);
+}
+} // namespace