File: MMIOTest.cpp

package info (click to toggle)
dolphin-emu 2512%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 76,328 kB
  • sloc: cpp: 499,023; ansic: 119,674; python: 6,547; sh: 2,338; makefile: 1,093; asm: 726; pascal: 257; javascript: 183; perl: 97; objc: 75; xml: 30
file content (141 lines) | stat: -rw-r--r-- 4,217 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2014 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <gtest/gtest.h>

#include <memory>
#include <unordered_set>

#include "Common/CommonTypes.h"
#include "Core/HW/GPFifo.h"
#include "Core/HW/MMIO.h"
#include "Core/System.h"

// Tests that the UniqueID function returns a "unique enough" identifier
// 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_FALSE(ids.contains(unique_id));
    ids.insert(unique_id);
  }
  for (u32 i = 0x0D000000; i < 0x0D010000; ++i)
  {
    u32 unique_id = MMIO::UniqueID(i);
    EXPECT_FALSE(ids.contains(unique_id));
    ids.insert(unique_id);
  }
}

TEST(IsMMIOAddress, SpecialAddresses)
{
  constexpr bool is_wii = true;

  // WG Pipe address, should not be handled by MMIO.
  EXPECT_FALSE(MMIO::IsMMIOAddress(GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS, is_wii));

  // Locked L1 cache allocation.
  EXPECT_FALSE(MMIO::IsMMIOAddress(0xE0000000, is_wii));

  // Uncached mirror of MEM1, shouldn't be handled by MMIO
  EXPECT_FALSE(MMIO::IsMMIOAddress(0xC0000000, is_wii));

  // Effective address of an MMIO register; MMIO only deals with physical
  // addresses.
  EXPECT_FALSE(MMIO::IsMMIOAddress(0xCC0000E0, is_wii));

  // And let's check some valid addresses too
  EXPECT_TRUE(MMIO::IsMMIOAddress(0x0C0000E0, is_wii));  // GameCube MMIOs
  EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D00008C, is_wii));  // Wii MMIOs
  EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D800F10, is_wii));  // Mirror of Wii MMIOs
}

class MappingTest : public testing::Test
{
protected:
  void SetUp() override
  {
    m_system = &Core::System::GetInstance();
    m_mapping = std::make_unique<MMIO::Mapping>();
  }
  void TearDown() override
  {
    m_system = nullptr;
    m_mapping.reset();
  }
  Core::System* m_system = nullptr;
  std::unique_ptr<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>());

  u8 val8 = m_mapping->Read<u8>(*m_system, 0x0C001234);
  u16 val16 = m_mapping->Read<u16>(*m_system, 0x0C001234);
  u32 val32 = m_mapping->Read<u32>(*m_system, 0x0C001234);

  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;

  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>(*m_system, 0x0C001234);
    EXPECT_EQ(i, val8);
    u16 val16 = m_mapping->Read<u16>(*m_system, 0x0C001234);
    EXPECT_EQ(i, val16);
    u32 val32 = m_mapping->Read<u32>(*m_system, 0x0C001234);
    EXPECT_EQ(i, val32);

    val8 += 1;
    m_mapping->Write(*m_system, 0x0C001234, val8);
    val16 += 1;
    m_mapping->Write(*m_system, 0x0C001234, val16);
    val32 += 1;
    m_mapping->Write(*m_system, 0x0C001234, val32);
  }
}

TEST_F(MappingTest, ReadWriteComplex)
{
  bool read_called = false, write_called = false;

  m_mapping->Register(
      0x0C001234, MMIO::ComplexRead<u8>([&read_called](Core::System&, const u32 addr) {
        EXPECT_EQ(0x0C001234u, addr);
        read_called = true;
        return 0x12;
      }),
      MMIO::ComplexWrite<u8>([&write_called](Core::System&, const u32 addr, const u8 val) {
        EXPECT_EQ(0x0C001234u, addr);
        EXPECT_EQ(0x34, val);
        write_called = true;
      }));

  u8 val = m_mapping->Read<u8>(*m_system, 0x0C001234);
  EXPECT_EQ(0x12, val);
  m_mapping->Write(*m_system, 0x0C001234, (u8)0x34);

  EXPECT_TRUE(read_called);
  EXPECT_TRUE(write_called);
}