mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
@ -2,8 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <unordered_set>
|
||||
#include <gtest/gtest.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/HW/MMIO.h"
|
||||
@ -12,120 +12,120 @@
|
||||
// number: that is, it is unique in the address ranges we care about.
|
||||
TEST(UniqueID, UniqueEnough)
|
||||
{
|
||||
std::unordered_set<u32> ids;
|
||||
for (u32 i = 0x0C000000; i < 0x0C010000; ++i)
|
||||
{
|
||||
u32 unique_id = MMIO::UniqueID(i);
|
||||
EXPECT_EQ(ids.end(), ids.find(unique_id));
|
||||
ids.insert(unique_id);
|
||||
}
|
||||
for (u32 i = 0x0D000000; i < 0x0D010000; ++i)
|
||||
{
|
||||
u32 unique_id = MMIO::UniqueID(i);
|
||||
EXPECT_EQ(ids.end(), ids.find(unique_id));
|
||||
ids.insert(unique_id);
|
||||
}
|
||||
std::unordered_set<u32> ids;
|
||||
for (u32 i = 0x0C000000; i < 0x0C010000; ++i)
|
||||
{
|
||||
u32 unique_id = MMIO::UniqueID(i);
|
||||
EXPECT_EQ(ids.end(), ids.find(unique_id));
|
||||
ids.insert(unique_id);
|
||||
}
|
||||
for (u32 i = 0x0D000000; i < 0x0D010000; ++i)
|
||||
{
|
||||
u32 unique_id = MMIO::UniqueID(i);
|
||||
EXPECT_EQ(ids.end(), ids.find(unique_id));
|
||||
ids.insert(unique_id);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(IsMMIOAddress, SpecialAddresses)
|
||||
{
|
||||
SConfig::Init();
|
||||
SConfig::GetInstance().bWii = true;
|
||||
SConfig::Init();
|
||||
SConfig::GetInstance().bWii = true;
|
||||
|
||||
// WG Pipe address, should not be handled by MMIO.
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0x0C008000));
|
||||
// WG Pipe address, should not be handled by MMIO.
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0x0C008000));
|
||||
|
||||
// Locked L1 cache allocation.
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0xE0000000));
|
||||
// Locked L1 cache allocation.
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0xE0000000));
|
||||
|
||||
// Uncached mirror of MEM1, shouldn't be handled by MMIO
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0xC0000000));
|
||||
// Uncached mirror of MEM1, shouldn't be handled by MMIO
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0xC0000000));
|
||||
|
||||
// Effective address of an MMIO register; MMIO only deals with physical
|
||||
// addresses.
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0xCC0000E0));
|
||||
// Effective address of an MMIO register; MMIO only deals with physical
|
||||
// addresses.
|
||||
EXPECT_FALSE(MMIO::IsMMIOAddress(0xCC0000E0));
|
||||
|
||||
// And lets check some valid addresses too
|
||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0C0000E0)); // Gamecube MMIOs
|
||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D00008C)); // Wii MMIOs
|
||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D800F10)); // Mirror of Wii MMIOs
|
||||
// And lets check some valid addresses too
|
||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0C0000E0)); // Gamecube MMIOs
|
||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D00008C)); // Wii MMIOs
|
||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D800F10)); // Mirror of Wii MMIOs
|
||||
|
||||
SConfig::Shutdown();
|
||||
SConfig::Shutdown();
|
||||
}
|
||||
|
||||
class MappingTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() override
|
||||
{
|
||||
m_mapping = new MMIO::Mapping();
|
||||
}
|
||||
|
||||
virtual void TearDown() override
|
||||
{
|
||||
delete m_mapping;
|
||||
}
|
||||
|
||||
MMIO::Mapping* m_mapping;
|
||||
virtual void SetUp() override { m_mapping = new MMIO::Mapping(); }
|
||||
virtual void TearDown() override { delete m_mapping; }
|
||||
MMIO::Mapping* m_mapping;
|
||||
};
|
||||
|
||||
TEST_F(MappingTest, ReadConstant)
|
||||
{
|
||||
m_mapping->Register(0x0C001234, MMIO::Constant<u8>(0x42), MMIO::Nop<u8>());
|
||||
m_mapping->Register(0x0C001234, MMIO::Constant<u16>(0x1234), MMIO::Nop<u16>());
|
||||
m_mapping->Register(0x0C001234, MMIO::Constant<u32>(0xdeadbeef), MMIO::Nop<u32>());
|
||||
m_mapping->Register(0x0C001234, MMIO::Constant<u8>(0x42), MMIO::Nop<u8>());
|
||||
m_mapping->Register(0x0C001234, MMIO::Constant<u16>(0x1234), MMIO::Nop<u16>());
|
||||
m_mapping->Register(0x0C001234, MMIO::Constant<u32>(0xdeadbeef), MMIO::Nop<u32>());
|
||||
|
||||
u8 val8 = m_mapping->Read<u8>(0x0C001234);
|
||||
u16 val16 = m_mapping->Read<u16>(0x0C001234);
|
||||
u32 val32 = m_mapping->Read<u32>(0x0C001234);
|
||||
u8 val8 = m_mapping->Read<u8>(0x0C001234);
|
||||
u16 val16 = m_mapping->Read<u16>(0x0C001234);
|
||||
u32 val32 = m_mapping->Read<u32>(0x0C001234);
|
||||
|
||||
EXPECT_EQ(0x42, val8);
|
||||
EXPECT_EQ(0x1234, val16);
|
||||
EXPECT_EQ(0xdeadbeef, val32);
|
||||
EXPECT_EQ(0x42, val8);
|
||||
EXPECT_EQ(0x1234, val16);
|
||||
EXPECT_EQ(0xdeadbeef, val32);
|
||||
}
|
||||
|
||||
TEST_F(MappingTest, ReadWriteDirect)
|
||||
{
|
||||
u8 target_8 = 0;
|
||||
u16 target_16 = 0;
|
||||
u32 target_32 = 0;
|
||||
u8 target_8 = 0;
|
||||
u16 target_16 = 0;
|
||||
u32 target_32 = 0;
|
||||
|
||||
m_mapping->Register(0x0C001234, MMIO::DirectRead<u8>(&target_8), MMIO::DirectWrite<u8>(&target_8));
|
||||
m_mapping->Register(0x0C001234, MMIO::DirectRead<u16>(&target_16), MMIO::DirectWrite<u16>(&target_16));
|
||||
m_mapping->Register(0x0C001234, MMIO::DirectRead<u32>(&target_32), MMIO::DirectWrite<u32>(&target_32));
|
||||
m_mapping->Register(0x0C001234, MMIO::DirectRead<u8>(&target_8),
|
||||
MMIO::DirectWrite<u8>(&target_8));
|
||||
m_mapping->Register(0x0C001234, MMIO::DirectRead<u16>(&target_16),
|
||||
MMIO::DirectWrite<u16>(&target_16));
|
||||
m_mapping->Register(0x0C001234, MMIO::DirectRead<u32>(&target_32),
|
||||
MMIO::DirectWrite<u32>(&target_32));
|
||||
|
||||
for (u32 i = 0; i < 100; ++i)
|
||||
{
|
||||
u8 val8 = m_mapping->Read<u8>(0x0C001234); EXPECT_EQ(i, val8);
|
||||
u16 val16 = m_mapping->Read<u16>(0x0C001234); EXPECT_EQ(i, val16);
|
||||
u32 val32 = m_mapping->Read<u32>(0x0C001234); EXPECT_EQ(i, val32);
|
||||
for (u32 i = 0; i < 100; ++i)
|
||||
{
|
||||
u8 val8 = m_mapping->Read<u8>(0x0C001234);
|
||||
EXPECT_EQ(i, val8);
|
||||
u16 val16 = m_mapping->Read<u16>(0x0C001234);
|
||||
EXPECT_EQ(i, val16);
|
||||
u32 val32 = m_mapping->Read<u32>(0x0C001234);
|
||||
EXPECT_EQ(i, val32);
|
||||
|
||||
val8 += 1; m_mapping->Write(0x0C001234, val8);
|
||||
val16 += 1; m_mapping->Write(0x0C001234, val16);
|
||||
val32 += 1; m_mapping->Write(0x0C001234, val32);
|
||||
}
|
||||
val8 += 1;
|
||||
m_mapping->Write(0x0C001234, val8);
|
||||
val16 += 1;
|
||||
m_mapping->Write(0x0C001234, val16);
|
||||
val32 += 1;
|
||||
m_mapping->Write(0x0C001234, val32);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MappingTest, ReadWriteComplex)
|
||||
{
|
||||
bool read_called = false, write_called = false;
|
||||
bool read_called = false, write_called = false;
|
||||
|
||||
m_mapping->Register(0x0C001234,
|
||||
MMIO::ComplexRead<u8>([&read_called](u32 addr) {
|
||||
EXPECT_EQ(0x0C001234u, addr);
|
||||
read_called = true;
|
||||
return 0x12;
|
||||
}),
|
||||
MMIO::ComplexWrite<u8>([&write_called](u32 addr, u8 val) {
|
||||
EXPECT_EQ(0x0C001234u, addr);
|
||||
EXPECT_EQ(0x34, val);
|
||||
write_called = true;
|
||||
})
|
||||
);
|
||||
m_mapping->Register(0x0C001234, MMIO::ComplexRead<u8>([&read_called](u32 addr) {
|
||||
EXPECT_EQ(0x0C001234u, addr);
|
||||
read_called = true;
|
||||
return 0x12;
|
||||
}),
|
||||
MMIO::ComplexWrite<u8>([&write_called](u32 addr, u8 val) {
|
||||
EXPECT_EQ(0x0C001234u, addr);
|
||||
EXPECT_EQ(0x34, val);
|
||||
write_called = true;
|
||||
}));
|
||||
|
||||
u8 val = m_mapping->Read<u8>(0x0C001234); EXPECT_EQ(0x12, val);
|
||||
m_mapping->Write(0x0C001234, (u8)0x34);
|
||||
u8 val = m_mapping->Read<u8>(0x0C001234);
|
||||
EXPECT_EQ(0x12, val);
|
||||
m_mapping->Write(0x0C001234, (u8)0x34);
|
||||
|
||||
EXPECT_TRUE(read_called);
|
||||
EXPECT_TRUE(write_called);
|
||||
EXPECT_TRUE(read_called);
|
||||
EXPECT_TRUE(write_called);
|
||||
}
|
||||
|
@ -10,70 +10,69 @@
|
||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||
|
||||
// include order is important
|
||||
#include <gtest/gtest.h> // NOLINT
|
||||
#include <gtest/gtest.h> // NOLINT
|
||||
|
||||
enum
|
||||
{
|
||||
#ifdef _WIN32
|
||||
PAGE_GRAN = 0x10000
|
||||
PAGE_GRAN = 0x10000
|
||||
#else
|
||||
PAGE_GRAN = 0x1000
|
||||
PAGE_GRAN = 0x1000
|
||||
#endif
|
||||
};
|
||||
|
||||
class PageFaultFakeJit : public JitBase
|
||||
{
|
||||
public:
|
||||
// CPUCoreBase methods
|
||||
void Init() override {}
|
||||
void Shutdown() override {}
|
||||
void ClearCache() override {}
|
||||
void Run() override {}
|
||||
void SingleStep() override {}
|
||||
const char *GetName() override { return nullptr; }
|
||||
// CPUCoreBase methods
|
||||
void Init() override {}
|
||||
void Shutdown() override {}
|
||||
void ClearCache() override {}
|
||||
void Run() override {}
|
||||
void SingleStep() override {}
|
||||
const char* GetName() override { return nullptr; }
|
||||
// JitBase methods
|
||||
JitBaseBlockCache* GetBlockCache() override { return nullptr; }
|
||||
void Jit(u32 em_address) override {}
|
||||
const CommonAsmRoutinesBase* GetAsmRoutines() override { return nullptr; }
|
||||
virtual bool HandleFault(uintptr_t access_address, SContext* ctx) override
|
||||
{
|
||||
m_pre_unprotect_time = std::chrono::high_resolution_clock::now();
|
||||
UnWriteProtectMemory(m_data, PAGE_GRAN, /*allowExecute*/ false);
|
||||
m_post_unprotect_time = std::chrono::high_resolution_clock::now();
|
||||
return true;
|
||||
}
|
||||
|
||||
// JitBase methods
|
||||
JitBaseBlockCache *GetBlockCache() override { return nullptr; }
|
||||
void Jit(u32 em_address) override {}
|
||||
const CommonAsmRoutinesBase *GetAsmRoutines() override { return nullptr; }
|
||||
|
||||
virtual bool HandleFault(uintptr_t access_address, SContext* ctx) override
|
||||
{
|
||||
m_pre_unprotect_time = std::chrono::high_resolution_clock::now();
|
||||
UnWriteProtectMemory(m_data, PAGE_GRAN, /*allowExecute*/ false);
|
||||
m_post_unprotect_time = std::chrono::high_resolution_clock::now();
|
||||
return true;
|
||||
}
|
||||
|
||||
void* m_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>
|
||||
m_pre_unprotect_time, m_post_unprotect_time;
|
||||
void* m_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> m_pre_unprotect_time,
|
||||
m_post_unprotect_time;
|
||||
};
|
||||
|
||||
|
||||
TEST(PageFault, PageFault)
|
||||
{
|
||||
EMM::InstallExceptionHandler();
|
||||
void* data = AllocateMemoryPages(PAGE_GRAN);
|
||||
EXPECT_NE(data, nullptr);
|
||||
WriteProtectMemory(data, PAGE_GRAN, false);
|
||||
EMM::InstallExceptionHandler();
|
||||
void* data = AllocateMemoryPages(PAGE_GRAN);
|
||||
EXPECT_NE(data, nullptr);
|
||||
WriteProtectMemory(data, PAGE_GRAN, false);
|
||||
|
||||
PageFaultFakeJit pfjit;
|
||||
jit = &pfjit;
|
||||
pfjit.m_data = data;
|
||||
PageFaultFakeJit pfjit;
|
||||
jit = &pfjit;
|
||||
pfjit.m_data = data;
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
*(volatile int*) data = 5;
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
*(volatile int*)data = 5;
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
#define AS_NS(diff) ((unsigned long long)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count())
|
||||
#define AS_NS(diff) \
|
||||
((unsigned long long)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count())
|
||||
|
||||
EMM::UninstallExceptionHandler();
|
||||
jit = nullptr;
|
||||
EMM::UninstallExceptionHandler();
|
||||
jit = nullptr;
|
||||
|
||||
printf("page fault timing:\n");
|
||||
printf("start->HandleFault %llu ns\n", AS_NS(pfjit.m_pre_unprotect_time - start));
|
||||
printf("UnWriteProtectMemory %llu ns\n", AS_NS(pfjit.m_post_unprotect_time - pfjit.m_pre_unprotect_time));
|
||||
printf("HandleFault->end %llu ns\n", AS_NS(end - pfjit.m_post_unprotect_time));
|
||||
printf("total %llu ns\n", AS_NS(end - start));
|
||||
printf("page fault timing:\n");
|
||||
printf("start->HandleFault %llu ns\n", AS_NS(pfjit.m_pre_unprotect_time - start));
|
||||
printf("UnWriteProtectMemory %llu ns\n",
|
||||
AS_NS(pfjit.m_post_unprotect_time - pfjit.m_pre_unprotect_time));
|
||||
printf("HandleFault->end %llu ns\n", AS_NS(end - pfjit.m_post_unprotect_time));
|
||||
printf("total %llu ns\n", AS_NS(end - start));
|
||||
}
|
||||
|
Reference in New Issue
Block a user