diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 89fe6e9d3..ddb3f7920 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -1476,10 +1476,10 @@ template u32 Bus::ICacheReadHandler(VirtualMemoryAddress address) { const u32 line = CPU::GetICacheLine(address); - const u8* line_data = &CPU::g_state.icache_data[line * CPU::ICACHE_LINE_SIZE]; + const u32* line_data = &CPU::g_state.icache_data[line * CPU::ICACHE_WORDS_PER_LINE]; const u32 offset = CPU::GetICacheLineOffset(address); u32 result; - std::memcpy(&result, &line_data[offset], sizeof(result)); + std::memcpy(&result, reinterpret_cast(line_data) + offset, sizeof(result)); return result; } @@ -1487,14 +1487,15 @@ template void Bus::ICacheWriteHandler(VirtualMemoryAddress address, u32 value) { const u32 line = CPU::GetICacheLine(address); + u32* line_data = &CPU::g_state.icache_data[line * CPU::ICACHE_WORDS_PER_LINE]; const u32 offset = CPU::GetICacheLineOffset(address); CPU::g_state.icache_tags[line] = CPU::GetICacheTagForAddress(address) | CPU::ICACHE_INVALID_BITS; if constexpr (size == MemoryAccessSize::Byte) - std::memcpy(&CPU::g_state.icache_data[line * CPU::ICACHE_LINE_SIZE + offset], &value, sizeof(u8)); + std::memcpy(reinterpret_cast(line_data) + offset, &value, sizeof(u8)); else if constexpr (size == MemoryAccessSize::HalfWord) - std::memcpy(&CPU::g_state.icache_data[line * CPU::ICACHE_LINE_SIZE + offset], &value, sizeof(u16)); + std::memcpy(reinterpret_cast(line_data) + offset, &value, sizeof(u16)); else - std::memcpy(&CPU::g_state.icache_data[line * CPU::ICACHE_LINE_SIZE + offset], &value, sizeof(u32)); + std::memcpy(reinterpret_cast(line_data) + offset, &value, sizeof(u32)); } template diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index 34720981f..db6be82dd 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -85,7 +85,7 @@ template static bool FetchInstruction(); static bool FetchInstructionForInterpreterFallback(); template -static bool DoInstructionRead(PhysicalMemoryAddress address, void* data); +static bool DoInstructionRead(PhysicalMemoryAddress address, u32* data); template static bool DoSafeMemoryAccess(VirtualMemoryAddress address, u32& value); template @@ -2671,7 +2671,7 @@ void CPU::UpdateMemoryPointers() } template -ALWAYS_INLINE_RELEASE bool CPU::DoInstructionRead(PhysicalMemoryAddress address, void* data) +ALWAYS_INLINE_RELEASE bool CPU::DoInstructionRead(PhysicalMemoryAddress address, u32* data) { using namespace Bus; @@ -2766,34 +2766,33 @@ void CPU::CheckAndUpdateICacheTags(u32 line_count) u32 CPU::FillICache(VirtualMemoryAddress address) { const u32 line = GetICacheLine(address); - u8* line_data = &g_state.icache_data[line * ICACHE_LINE_SIZE]; + const u32 line_word_offset = GetICacheLineWordOffset(address); + u32* const line_data = g_state.icache_data.data() + (line * ICACHE_WORDS_PER_LINE); + u32* const offset_line_data = line_data + line_word_offset; u32 line_tag; - switch ((address >> 2) & 0x03u) + switch (line_word_offset) { case 0: - DoInstructionRead(address & ~(ICACHE_LINE_SIZE - 1u), line_data); + DoInstructionRead(address & ~(ICACHE_LINE_SIZE - 1u), offset_line_data); line_tag = GetICacheTagForAddress(address); break; case 1: - DoInstructionRead(address & (~(ICACHE_LINE_SIZE - 1u) | 0x4), line_data + 0x4); + DoInstructionRead(address & (~(ICACHE_LINE_SIZE - 1u) | 0x4), offset_line_data); line_tag = GetICacheTagForAddress(address) | 0x1; break; case 2: - DoInstructionRead(address & (~(ICACHE_LINE_SIZE - 1u) | 0x8), line_data + 0x8); + DoInstructionRead(address & (~(ICACHE_LINE_SIZE - 1u) | 0x8), offset_line_data); line_tag = GetICacheTagForAddress(address) | 0x3; break; case 3: default: - DoInstructionRead(address & (~(ICACHE_LINE_SIZE - 1u) | 0xC), line_data + 0xC); + DoInstructionRead(address & (~(ICACHE_LINE_SIZE - 1u) | 0xC), offset_line_data); line_tag = GetICacheTagForAddress(address) | 0x7; break; } - g_state.icache_tags[line] = line_tag; - const u32 offset = GetICacheLineOffset(address); - u32 result; - std::memcpy(&result, &line_data[offset], sizeof(result)); - return result; + g_state.icache_tags[line] = line_tag; + return offset_line_data[0]; } void CPU::ClearICache() @@ -2806,11 +2805,9 @@ namespace CPU { ALWAYS_INLINE_RELEASE static u32 ReadICache(VirtualMemoryAddress address) { const u32 line = GetICacheLine(address); - const u8* line_data = &g_state.icache_data[line * ICACHE_LINE_SIZE]; - const u32 offset = GetICacheLineOffset(address); - u32 result; - std::memcpy(&result, &line_data[offset], sizeof(result)); - return result; + const u32 line_word_offset = GetICacheLineWordOffset(address); + const u32* const line_data = g_state.icache_data.data() + (line * ICACHE_WORDS_PER_LINE); + return line_data[line_word_offset]; } } // namespace CPU diff --git a/src/core/cpu_core.h b/src/core/cpu_core.h index 04abbc048..0bdb75238 100644 --- a/src/core/cpu_core.h +++ b/src/core/cpu_core.h @@ -32,7 +32,7 @@ enum : PhysicalMemoryAddress ICACHE_SLOTS = ICACHE_SIZE / sizeof(u32), ICACHE_LINE_SIZE = 16, ICACHE_LINES = ICACHE_SIZE / ICACHE_LINE_SIZE, - ICACHE_SLOTS_PER_LINE = ICACHE_SLOTS / ICACHE_LINES, + ICACHE_WORDS_PER_LINE = ICACHE_SLOTS / ICACHE_LINES, ICACHE_TAG_ADDRESS_MASK = 0xFFFFFFF0u, ICACHE_INVALID_BITS = 0x0Fu, }; @@ -117,7 +117,7 @@ struct State PGXPValue pgxp_gte[64] = {}; std::array icache_tags = {}; - std::array icache_data = {}; + std::array icache_data = {}; std::array scratchpad = {}; diff --git a/src/core/cpu_core_private.h b/src/core/cpu_core_private.h index 921aa0cfd..479c2f58f 100644 --- a/src/core/cpu_core_private.h +++ b/src/core/cpu_core_private.h @@ -48,6 +48,10 @@ ALWAYS_INLINE static u32 GetICacheLineOffset(VirtualMemoryAddress address) { return (address & (ICACHE_LINE_SIZE - 1)); } +ALWAYS_INLINE static u32 GetICacheLineWordOffset(VirtualMemoryAddress address) +{ + return (address >> 2) & 0x03u; +} ALWAYS_INLINE static u32 GetICacheTagForAddress(VirtualMemoryAddress address) { return (address & ICACHE_TAG_ADDRESS_MASK);