2021-01-03 19:49:22 +00:00
|
|
|
// Copyright 2021 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
#include "Common/Arm64Emitter.h"
|
|
|
|
#include "Common/Assert.h"
|
|
|
|
#include "Common/BitUtils.h"
|
|
|
|
#include "Common/Random.h"
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
using namespace Arm64Gen;
|
|
|
|
|
|
|
|
class TestMovI2R : public ARM64CodeBlock
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TestMovI2R() { AllocCodeSpace(4096); }
|
|
|
|
|
|
|
|
void Check32(u32 value)
|
|
|
|
{
|
|
|
|
ResetCodePtr();
|
|
|
|
|
|
|
|
const u8* fn = GetCodePtr();
|
2021-06-19 17:05:35 +00:00
|
|
|
{
|
|
|
|
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
|
|
|
|
MOVI2R(ARM64Reg::W0, value);
|
|
|
|
RET();
|
|
|
|
}
|
2021-01-03 19:49:22 +00:00
|
|
|
|
|
|
|
FlushIcacheSection(const_cast<u8*>(fn), const_cast<u8*>(GetCodePtr()));
|
|
|
|
|
|
|
|
const u64 result = Common::BitCast<u64 (*)()>(fn)();
|
|
|
|
EXPECT_EQ(value, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Check64(u64 value)
|
|
|
|
{
|
|
|
|
ResetCodePtr();
|
|
|
|
|
|
|
|
const u8* fn = GetCodePtr();
|
2021-06-19 17:05:35 +00:00
|
|
|
{
|
|
|
|
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
|
|
|
|
MOVI2R(ARM64Reg::X0, value);
|
|
|
|
RET();
|
|
|
|
}
|
2021-01-03 19:49:22 +00:00
|
|
|
|
|
|
|
FlushIcacheSection(const_cast<u8*>(fn), const_cast<u8*>(GetCodePtr()));
|
|
|
|
|
|
|
|
const u64 result = Common::BitCast<u64 (*)()>(fn)();
|
|
|
|
EXPECT_EQ(value, result);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST(JitArm64, MovI2R_32BitValues)
|
|
|
|
{
|
2021-01-31 13:13:10 +00:00
|
|
|
Common::Random::PRNG rng{0};
|
2021-01-03 19:49:22 +00:00
|
|
|
TestMovI2R test;
|
2021-01-31 13:13:10 +00:00
|
|
|
for (u64 i = 0; i < 0x100000; i++)
|
2021-01-03 19:49:22 +00:00
|
|
|
{
|
2021-01-31 13:13:10 +00:00
|
|
|
const u32 value = rng.GenerateValue<u32>();
|
|
|
|
test.Check32(value);
|
|
|
|
test.Check64(value);
|
2021-01-03 19:49:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(JitArm64, MovI2R_Rand)
|
|
|
|
{
|
|
|
|
Common::Random::PRNG rng{0};
|
|
|
|
TestMovI2R test;
|
|
|
|
for (u64 i = 0; i < 0x100000; i++)
|
|
|
|
{
|
|
|
|
test.Check64(rng.GenerateValue<u64>());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(JitArm64, MovI2R_ADP)
|
|
|
|
{
|
|
|
|
TestMovI2R test;
|
|
|
|
const u64 base = Common::BitCast<u64>(test.GetCodePtr());
|
2021-02-13 10:54:46 +00:00
|
|
|
|
|
|
|
// Test offsets around 0
|
2021-01-03 19:49:22 +00:00
|
|
|
for (s64 i = -0x20000; i < 0x20000; i++)
|
|
|
|
{
|
|
|
|
const u64 offset = static_cast<u64>(i);
|
|
|
|
test.Check64(base + offset);
|
|
|
|
}
|
2021-02-13 10:54:46 +00:00
|
|
|
|
|
|
|
// Test offsets around the maximum
|
|
|
|
for (const s64 i : {-0x200000ll, 0x200000ll})
|
|
|
|
{
|
|
|
|
for (s64 j = -4; j < 4; j++)
|
|
|
|
{
|
|
|
|
const u64 offset = static_cast<u64>(i + j);
|
|
|
|
test.Check64(base + offset);
|
|
|
|
}
|
|
|
|
}
|
2021-01-03 19:49:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(JitArm64, MovI2R_ADRP)
|
|
|
|
{
|
|
|
|
TestMovI2R test;
|
|
|
|
const u64 base = Common::BitCast<u64>(test.GetCodePtr()) & ~0xFFF;
|
2021-02-13 10:54:46 +00:00
|
|
|
|
|
|
|
// Test offsets around 0
|
2021-01-03 19:49:22 +00:00
|
|
|
for (s64 i = -0x20000; i < 0x20000; i++)
|
|
|
|
{
|
|
|
|
const u64 offset = static_cast<u64>(i) << 12;
|
|
|
|
test.Check64(base + offset);
|
|
|
|
}
|
2021-02-13 10:54:46 +00:00
|
|
|
|
|
|
|
// Test offsets around the maximum
|
|
|
|
for (const s64 i : {-0x100000000ll, -0x80000000ll, 0x80000000ll, 0x100000000ll})
|
|
|
|
{
|
|
|
|
for (s64 j = -4; j < 4; j++)
|
|
|
|
{
|
|
|
|
const u64 offset = static_cast<u64>(i + (j << 12));
|
|
|
|
test.Check64(base + offset);
|
|
|
|
}
|
|
|
|
}
|
2021-01-03 19:49:22 +00:00
|
|
|
}
|