diff options
| author | Admiral H. Curtiss <pikachu025@gmail.com> | 2023-11-25 17:30:42 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-25 17:30:42 +0100 |
| commit | 76d605639bfdeba30cddbc6483c4014979f43055 (patch) | |
| tree | db4305bcc2066e6781c43b70a59d1f772809cd7c /Source/UnitTests/Common | |
| parent | d89a0423d191931b31cafd8c2256a5258778dcb4 (diff) | |
| parent | c248a6926817dc2523c35d1c2fbb36c2af0c9a44 (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.cpp | 178 | ||||
| -rw-r--r-- | Source/UnitTests/Common/CMakeLists.txt | 2 |
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() |
