summaryrefslogtreecommitdiff
path: root/Source/UnitTests/Common
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2023-11-25 17:30:42 +0100
committerGitHub <noreply@github.com>2023-11-25 17:30:42 +0100
commit76d605639bfdeba30cddbc6483c4014979f43055 (patch)
treedb4305bcc2066e6781c43b70a59d1f772809cd7c /Source/UnitTests/Common
parentd89a0423d191931b31cafd8c2256a5258778dcb4 (diff)
parentc248a6926817dc2523c35d1c2fbb36c2af0c9a44 (diff)
Merge pull request #11881 from JosJuice/aarch64-function-call
JitArm64: Add utility for calling a function with arguments
Diffstat (limited to 'Source/UnitTests/Common')
-rw-r--r--Source/UnitTests/Common/Arm64EmitterTest.cpp178
-rw-r--r--Source/UnitTests/Common/CMakeLists.txt2
2 files changed, 180 insertions, 0 deletions
diff --git a/Source/UnitTests/Common/Arm64EmitterTest.cpp b/Source/UnitTests/Common/Arm64EmitterTest.cpp
new file mode 100644
index 0000000000..61be07fef6
--- /dev/null
+++ b/Source/UnitTests/Common/Arm64EmitterTest.cpp
@@ -0,0 +1,178 @@
+// Copyright 2023 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "Common/Arm64Emitter.h"
+#include "Common/BitSet.h"
+#include "Common/BitUtils.h"
+
+#include <gtest/gtest.h>
+
+using namespace Arm64Gen;
+
+namespace
+{
+u32 ZeroParameterFunction()
+{
+ return 123;
+}
+
+u32 OneParameterFunction(u64 a)
+{
+ return a + 23;
+}
+
+u32 TwoParameterFunction(u64 a, u64 b)
+{
+ return a * 10 + b + 3;
+}
+
+u32 ThreeParameterFunction(u64 a, u64 b, u64 c)
+{
+ return a * 10 + b + c / 10;
+}
+
+u32 EightParameterFunction(u64 a, u64 b, u64 c, u64 d, u64 e, u64 f, u64 g, u64 h)
+{
+ return a / 20 + b / 8 + c / 10 + d / 2 + e / 5 - f + g + h / 3;
+}
+
+class TestCallFunction : public ARM64CodeBlock
+{
+public:
+ TestCallFunction() { AllocCodeSpace(4096); }
+
+ template <typename F>
+ void Emit(F f)
+ {
+ ResetCodePtr();
+
+ m_code_pointer = GetCodePtr();
+ {
+ const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
+
+ constexpr BitSet32 link_register{DecodeReg(ARM64Reg::X30)};
+ ABI_PushRegisters(link_register);
+ f();
+ ABI_PopRegisters(link_register);
+ RET();
+ }
+
+ FlushIcacheSection(const_cast<u8*>(m_code_pointer), const_cast<u8*>(GetCodePtr()));
+ }
+
+ void Run()
+ {
+ const u64 actual = Common::BitCast<u64 (*)()>(m_code_pointer)();
+ constexpr u64 expected = 123;
+ EXPECT_EQ(expected, actual);
+ }
+
+private:
+ const u8* m_code_pointer = nullptr;
+};
+
+} // namespace
+
+TEST(Arm64Emitter, CallFunction_ZeroParameters)
+{
+ TestCallFunction test;
+ test.Emit([&] { test.ABI_CallFunction(&ZeroParameterFunction); });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_OneConstantParameter)
+{
+ TestCallFunction test;
+ test.Emit([&] { test.ABI_CallFunction(&OneParameterFunction, 100); });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_OneRegisterParameterNoMov)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X0, 100);
+ test.ABI_CallFunction(&OneParameterFunction, ARM64Reg::X0);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_OneRegisterParameterMov)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X8, 100);
+ test.ABI_CallFunction(&OneParameterFunction, ARM64Reg::X8);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_TwoRegistersMixed)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X0, 20);
+ test.ABI_CallFunction(&TwoParameterFunction, 10, ARM64Reg::X0);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_TwoRegistersCycle)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X0, 20);
+ test.MOVI2R(ARM64Reg::X1, 10);
+ test.ABI_CallFunction(&TwoParameterFunction, ARM64Reg::X1, ARM64Reg::X0);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_ThreeRegistersMixed)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X1, 10);
+ test.MOVI2R(ARM64Reg::X2, 20);
+ test.ABI_CallFunction(&ThreeParameterFunction, ARM64Reg::X1, ARM64Reg::X2, 30);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_ThreeRegistersCycle1)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X0, 30);
+ test.MOVI2R(ARM64Reg::X1, 10);
+ test.MOVI2R(ARM64Reg::X2, 20);
+ test.ABI_CallFunction(&ThreeParameterFunction, ARM64Reg::X1, ARM64Reg::X2, ARM64Reg::X0);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_ThreeRegistersCycle2)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X0, 20);
+ test.MOVI2R(ARM64Reg::X1, 30);
+ test.MOVI2R(ARM64Reg::X2, 10);
+ test.ABI_CallFunction(&ThreeParameterFunction, ARM64Reg::X2, ARM64Reg::X0, ARM64Reg::X1);
+ });
+ test.Run();
+}
+
+TEST(Arm64Emitter, CallFunction_EightRegistersMixed)
+{
+ TestCallFunction test;
+ test.Emit([&] {
+ test.MOVI2R(ARM64Reg::X3, 12);
+ test.MOVI2R(ARM64Reg::X4, 23);
+ test.MOVI2R(ARM64Reg::X5, 24);
+ test.MOVI2R(ARM64Reg::X30, 2000);
+ test.ABI_CallFunction(&EightParameterFunction, ARM64Reg::X30, 40, ARM64Reg::X4, ARM64Reg::X5,
+ ARM64Reg::X4, ARM64Reg::X3, 5, ARM64Reg::X4);
+ });
+ test.Run();
+}
diff --git a/Source/UnitTests/Common/CMakeLists.txt b/Source/UnitTests/Common/CMakeLists.txt
index bbea892fdf..a4c9a67ade 100644
--- a/Source/UnitTests/Common/CMakeLists.txt
+++ b/Source/UnitTests/Common/CMakeLists.txt
@@ -21,4 +21,6 @@ add_dolphin_test(SwapTest SwapTest.cpp)
if (_M_X86)
add_dolphin_test(x64EmitterTest x64EmitterTest.cpp)
target_link_libraries(x64EmitterTest PRIVATE bdisasm)
+elseif (_M_ARM_64)
+ add_dolphin_test(Arm64EmitterTest Arm64EmitterTest.cpp)
endif()