// Copyright 2021 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include #include "Common/Arm64Emitter.h" #include "Common/BitUtils.h" #include "Common/CommonTypes.h" #include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" #include "Core/PowerPC/JitArm64/Jit.h" #include "Core/PowerPC/PowerPC.h" #include "Core/System.h" #include "../TestValues.h" #include namespace { using namespace Arm64Gen; class TestFPRF : public JitArm64 { public: explicit TestFPRF(Core::System& system) : JitArm64(system) { const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes; AllocCodeSpace(4096); const u8* raw_fprf_single = GetCodePtr(); GenerateFPRF(true); const u8* raw_fprf_double = GetCodePtr(); GenerateFPRF(false); fprf_single = Common::BitCast(GetCodePtr()); MOV(ARM64Reg::X15, ARM64Reg::X30); MOV(ARM64Reg::X14, PPC_REG); MOVP2R(PPC_REG, &PowerPC::ppcState); BL(raw_fprf_single); MOV(ARM64Reg::X30, ARM64Reg::X15); MOV(PPC_REG, ARM64Reg::X14); RET(); fprf_double = Common::BitCast(GetCodePtr()); MOV(ARM64Reg::X15, ARM64Reg::X30); MOV(ARM64Reg::X14, PPC_REG); MOVP2R(PPC_REG, &PowerPC::ppcState); BL(raw_fprf_double); MOV(ARM64Reg::X30, ARM64Reg::X15); MOV(PPC_REG, ARM64Reg::X14); RET(); } std::function fprf_single; std::function fprf_double; }; } // namespace static u32 RunUpdateFPRF(const std::function& f) { PowerPC::ppcState.fpscr.Hex = 0x12345678; f(); return PowerPC::ppcState.fpscr.Hex; } TEST(JitArm64, FPRF) { TestFPRF test(Core::System::GetInstance()); for (const u64 double_input : double_test_values) { const u32 expected_double = RunUpdateFPRF( [&] { PowerPC::ppcState.UpdateFPRFDouble(Common::BitCast(double_input)); }); const u32 actual_double = RunUpdateFPRF([&] { test.fprf_double(double_input); }); EXPECT_EQ(expected_double, actual_double); const u32 single_input = ConvertToSingle(double_input); const u32 expected_single = RunUpdateFPRF( [&] { PowerPC::ppcState.UpdateFPRFSingle(Common::BitCast(single_input)); }); const u32 actual_single = RunUpdateFPRF([&] { test.fprf_single(single_input); }); EXPECT_EQ(expected_single, actual_single); } }