From 3dfc3bd2bae77c97862985f4463ac8e1eb805d0b Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 6 Nov 2023 18:09:27 +1000 Subject: [PATCH] CPU: Fix incorrect scratchpad masking --- src/core/bus.cpp | 34 +++++++++++----------- src/core/bus.h | 1 + src/core/cheats.cpp | 8 ++--- src/core/cpu_core.cpp | 29 +++++++++--------- src/core/cpu_core.h | 12 ++++---- src/core/cpu_newrec_compiler.cpp | 8 ++--- src/core/cpu_recompiler_code_generator.cpp | 8 ++--- src/core/pgxp.cpp | 6 ++-- src/duckstation-qt/cheatmanagerdialog.cpp | 4 +-- 9 files changed, 56 insertions(+), 54 deletions(-) diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 319c1b652..6527df1e4 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -711,7 +711,7 @@ std::optional Bus::GetMemoryRegionForAddress(PhysicalMemoryAd return static_cast(static_cast(MemoryRegion::RAM) + (address / RAM_2MB_SIZE)); else if (address >= EXP1_BASE && address < (EXP1_BASE + EXP1_SIZE)) return MemoryRegion::EXP1; - else if (address >= CPU::DCACHE_LOCATION && address < (CPU::DCACHE_LOCATION + CPU::DCACHE_SIZE)) + else if (address >= CPU::SCRATCHPAD_ADDR && address < (CPU::SCRATCHPAD_ADDR + CPU::SCRATCHPAD_SIZE)) return MemoryRegion::Scratchpad; else if (address >= BIOS_BASE && address < (BIOS_BASE + BIOS_SIZE)) return MemoryRegion::BIOS; @@ -727,7 +727,7 @@ static constexpr std::array u32 Bus::ScratchpadReadHandler(VirtualMemoryAddress address) { - const PhysicalMemoryAddress cache_offset = address - CPU::DCACHE_LOCATION; - if (cache_offset >= CPU::DCACHE_SIZE) [[unlikely]] + const PhysicalMemoryAddress cache_offset = address & MEMORY_LUT_PAGE_MASK; + if (cache_offset >= CPU::SCRATCHPAD_SIZE) [[unlikely]] return UnknownReadHandler(address); if constexpr (size == MemoryAccessSize::Byte) { - return ZeroExtend32(CPU::g_state.dcache[cache_offset]); + return ZeroExtend32(CPU::g_state.scratchpad[cache_offset]); } else if constexpr (size == MemoryAccessSize::HalfWord) { u16 temp; - std::memcpy(&temp, &CPU::g_state.dcache[cache_offset], sizeof(temp)); + std::memcpy(&temp, &CPU::g_state.scratchpad[cache_offset], sizeof(temp)); return ZeroExtend32(temp); } else { u32 value; - std::memcpy(&value, &CPU::g_state.dcache[cache_offset], sizeof(value)); + std::memcpy(&value, &CPU::g_state.scratchpad[cache_offset], sizeof(value)); return value; } } @@ -1007,19 +1007,19 @@ u32 Bus::ScratchpadReadHandler(VirtualMemoryAddress address) template void Bus::ScratchpadWriteHandler(VirtualMemoryAddress address, u32 value) { - const PhysicalMemoryAddress cache_offset = address - CPU::DCACHE_LOCATION; - if (cache_offset >= CPU::DCACHE_SIZE) [[unlikely]] + const PhysicalMemoryAddress cache_offset = address & MEMORY_LUT_PAGE_MASK; + if (cache_offset >= CPU::SCRATCHPAD_SIZE) [[unlikely]] { UnknownWriteHandler(address, value); return; } if constexpr (size == MemoryAccessSize::Byte) - CPU::g_state.dcache[cache_offset] = Truncate8(value); + CPU::g_state.scratchpad[cache_offset] = Truncate8(value); else if constexpr (size == MemoryAccessSize::HalfWord) - std::memcpy(&CPU::g_state.dcache[cache_offset], &value, sizeof(u16)); + std::memcpy(&CPU::g_state.scratchpad[cache_offset], &value, sizeof(u16)); else if constexpr (size == MemoryAccessSize::Word) - std::memcpy(&CPU::g_state.dcache[cache_offset], &value, sizeof(u32)); + std::memcpy(&CPU::g_state.scratchpad[cache_offset], &value, sizeof(u32)); } template @@ -1640,7 +1640,7 @@ void Bus::SetHandlers() // KUSEG - Cached SET(g_memory_handlers, KUSEG | RAM_BASE, RAM_MIRROR_SIZE, RAMReadHandler, RAMWriteHandler); - SET(g_memory_handlers, KUSEG | CPU::DCACHE_LOCATION, 0x1000, ScratchpadReadHandler, ScratchpadWriteHandler); + SET(g_memory_handlers, KUSEG | CPU::SCRATCHPAD_ADDR, 0x1000, ScratchpadReadHandler, ScratchpadWriteHandler); SET(g_memory_handlers, KUSEG | BIOS_BASE, BIOS_SIZE, BIOSReadHandler, IgnoreWriteHandler); SET(g_memory_handlers, KUSEG | EXP1_BASE, EXP1_SIZE, EXP1ReadHandler, EXP1WriteHandler); SET(g_memory_handlers, KUSEG | HW_BASE, HW_SIZE, HardwareReadHandler, HardwareWriteHandler); @@ -1649,7 +1649,7 @@ void Bus::SetHandlers() // KSEG0 - Cached SET(g_memory_handlers, KSEG0 | RAM_BASE, RAM_MIRROR_SIZE, RAMReadHandler, RAMWriteHandler); - SET(g_memory_handlers, KSEG0 | CPU::DCACHE_LOCATION, 0x1000, ScratchpadReadHandler, ScratchpadWriteHandler); + SET(g_memory_handlers, KSEG0 | CPU::SCRATCHPAD_ADDR, 0x1000, ScratchpadReadHandler, ScratchpadWriteHandler); SET(g_memory_handlers, KSEG0 | BIOS_BASE, BIOS_SIZE, BIOSReadHandler, IgnoreWriteHandler); SET(g_memory_handlers, KSEG0 | EXP1_BASE, EXP1_SIZE, EXP1ReadHandler, EXP1WriteHandler); SET(g_memory_handlers, KSEG0 | HW_BASE, HW_SIZE, HardwareReadHandler, HardwareWriteHandler); @@ -1669,14 +1669,14 @@ void Bus::SetHandlers() // When cache isolated, only allow writes to cache? Or should we still allow KSEG1? SET(g_memory_handlers_isc, KUSEG | RAM_BASE, RAM_MIRROR_SIZE, RAMReadHandler, ICacheWriteHandler); - SET(g_memory_handlers_isc, KUSEG | CPU::DCACHE_LOCATION, 0x1000, ScratchpadReadHandler, ICacheWriteHandler); + SET(g_memory_handlers_isc, KUSEG | CPU::SCRATCHPAD_ADDR, 0x1000, ScratchpadReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KUSEG | BIOS_BASE, BIOS_SIZE, BIOSReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KUSEG | EXP1_BASE, EXP1_SIZE, EXP1ReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KUSEG | HW_BASE, HW_SIZE, HardwareReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KUSEG | EXP2_BASE, EXP2_SIZE, EXP2ReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KUSEG | EXP3_BASE, EXP3_SIZE, EXP3ReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KSEG0 | RAM_BASE, RAM_MIRROR_SIZE, RAMReadHandler, ICacheWriteHandler); - SET(g_memory_handlers_isc, KSEG0 | CPU::DCACHE_LOCATION, 0x1000, ScratchpadReadHandler, ICacheWriteHandler); + SET(g_memory_handlers_isc, KSEG0 | CPU::SCRATCHPAD_ADDR, 0x1000, ScratchpadReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KSEG0 | BIOS_BASE, BIOS_SIZE, BIOSReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KSEG0 | EXP1_BASE, EXP1_SIZE, EXP1ReadHandler, ICacheWriteHandler); SET(g_memory_handlers_isc, KSEG0 | HW_BASE, HW_SIZE, HardwareReadHandler, ICacheWriteHandler); diff --git a/src/core/bus.h b/src/core/bus.h index 1d87eb53e..9ec5d12b8 100644 --- a/src/core/bus.h +++ b/src/core/bus.h @@ -90,6 +90,7 @@ enum : u32 MEMORY_LUT_PAGE_SIZE = 4096, MEMORY_LUT_PAGE_SHIFT = 12, + MEMORY_LUT_PAGE_MASK = MEMORY_LUT_PAGE_SIZE - 1, MEMORY_LUT_SIZE = 0x100000, // 0x100000000 >> 12 MEMORY_LUT_SLOTS = MEMORY_LUT_SIZE * 3 * 2, // [size][read_write] diff --git a/src/core/cheats.cpp b/src/core/cheats.cpp index 0874a10cd..10a554535 100644 --- a/src/core/cheats.cpp +++ b/src/core/cheats.cpp @@ -25,8 +25,8 @@ using KeyValuePairVector = std::vector>; static bool IsValidScanAddress(PhysicalMemoryAddress address) { - if ((address & CPU::DCACHE_LOCATION_MASK) == CPU::DCACHE_LOCATION && - (address & CPU::DCACHE_OFFSET_MASK) < CPU::DCACHE_SIZE) + if ((address & CPU::SCRATCHPAD_ADDR_MASK) == CPU::SCRATCHPAD_ADDR && + (address & CPU::SCRATCHPAD_OFFSET_MASK) < CPU::SCRATCHPAD_SIZE) { return true; } @@ -1076,14 +1076,14 @@ void CheatCode::Apply() const case InstructionCode::ScratchpadWrite16: { - DoMemoryWrite(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value16); + DoMemoryWrite(CPU::SCRATCHPAD_ADDR | (inst.address & CPU::SCRATCHPAD_OFFSET_MASK), inst.value16); index++; } break; case InstructionCode::ExtScratchpadWrite32: { - DoMemoryWrite(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value32); + DoMemoryWrite(CPU::SCRATCHPAD_ADDR | (inst.address & CPU::SCRATCHPAD_OFFSET_MASK), inst.value32); index++; } break; diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index cedabfde0..c3500143c 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -241,7 +241,7 @@ bool CPU::DoState(StateWrapper& sw) } sw.Do(&g_state.cache_control.bits); - sw.DoBytes(g_state.dcache.data(), g_state.dcache.size()); + sw.DoBytes(g_state.scratchpad.data(), g_state.scratchpad.size()); if (!GTE::DoState(sw)) return false; @@ -2674,46 +2674,47 @@ ALWAYS_INLINE bool CPU::DoSafeMemoryAccess(VirtualMemoryAddress address, u32& va case 0x00: // KUSEG 0M-512M case 0x04: // KSEG0 - physical memory cached { - address &= PHYSICAL_MEMORY_ADDRESS_MASK; - if ((address & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) + if ((address & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR) { - const u32 offset = address & DCACHE_OFFSET_MASK; + const u32 offset = address & SCRATCHPAD_OFFSET_MASK; if constexpr (type == MemoryAccessType::Read) { if constexpr (size == MemoryAccessSize::Byte) { - value = CPU::g_state.dcache[offset]; + value = CPU::g_state.scratchpad[offset]; } else if constexpr (size == MemoryAccessSize::HalfWord) { u16 temp; - std::memcpy(&temp, &CPU::g_state.dcache[offset], sizeof(u16)); + std::memcpy(&temp, &CPU::g_state.scratchpad[offset], sizeof(u16)); value = ZeroExtend32(temp); } else if constexpr (size == MemoryAccessSize::Word) { - std::memcpy(&value, &CPU::g_state.dcache[offset], sizeof(u32)); + std::memcpy(&value, &CPU::g_state.scratchpad[offset], sizeof(u32)); } } else { if constexpr (size == MemoryAccessSize::Byte) { - CPU::g_state.dcache[offset] = Truncate8(value); + CPU::g_state.scratchpad[offset] = Truncate8(value); } else if constexpr (size == MemoryAccessSize::HalfWord) { - std::memcpy(&CPU::g_state.dcache[offset], &value, sizeof(u16)); + std::memcpy(&CPU::g_state.scratchpad[offset], &value, sizeof(u16)); } else if constexpr (size == MemoryAccessSize::Word) { - std::memcpy(&CPU::g_state.dcache[offset], &value, sizeof(u32)); + std::memcpy(&CPU::g_state.scratchpad[offset], &value, sizeof(u32)); } } return true; } + + address &= PHYSICAL_MEMORY_ADDRESS_MASK; } break; @@ -2927,12 +2928,12 @@ void* CPU::GetDirectReadMemoryPointer(VirtualMemoryAddress address, MemoryAccess return &g_ram[paddr & g_ram_mask]; } - if ((paddr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) + if ((paddr & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR) { if (read_ticks) *read_ticks = 0; - return &g_state.dcache[paddr & DCACHE_OFFSET_MASK]; + return &g_state.scratchpad[paddr & SCRATCHPAD_OFFSET_MASK]; } if (paddr >= BIOS_BASE && paddr < (BIOS_BASE + BIOS_SIZE)) @@ -2959,8 +2960,8 @@ void* CPU::GetDirectWriteMemoryPointer(VirtualMemoryAddress address, MemoryAcces if (paddr < RAM_MIRROR_END) return &g_ram[paddr & g_ram_mask]; - if ((paddr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) - return &g_state.dcache[paddr & DCACHE_OFFSET_MASK]; + if ((paddr & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR) + return &g_state.scratchpad[paddr & SCRATCHPAD_OFFSET_MASK]; return nullptr; } diff --git a/src/core/cpu_core.h b/src/core/cpu_core.h index b74fb69f6..87fda6ec9 100644 --- a/src/core/cpu_core.h +++ b/src/core/cpu_core.h @@ -21,10 +21,10 @@ enum : VirtualMemoryAddress }; enum : PhysicalMemoryAddress { - DCACHE_LOCATION = UINT32_C(0x1F800000), - DCACHE_LOCATION_MASK = UINT32_C(0xFFFFFC00), - DCACHE_OFFSET_MASK = UINT32_C(0x000003FF), - DCACHE_SIZE = UINT32_C(0x00000400), + SCRATCHPAD_ADDR = UINT32_C(0x1F800000), + SCRATCHPAD_ADDR_MASK = UINT32_C(0x7FFFFC00), + SCRATCHPAD_OFFSET_MASK = UINT32_C(0x000003FF), + SCRATCHPAD_SIZE = UINT32_C(0x00000400), ICACHE_SIZE = UINT32_C(0x00001000), ICACHE_SLOTS = ICACHE_SIZE / sizeof(u32), ICACHE_LINE_SIZE = 16, @@ -88,11 +88,11 @@ struct State void* fastmem_base = nullptr; void** memory_handlers = nullptr; - // data cache (used as scratchpad) - std::array dcache = {}; std::array icache_tags = {}; std::array icache_data = {}; + std::array scratchpad = {}; + static constexpr u32 GPRRegisterOffset(u32 index) { return offsetof(State, regs.r) + (sizeof(u32) * index); } static constexpr u32 GTERegisterOffset(u32 index) { return offsetof(State, gte_regs.r32) + (sizeof(u32) * index); } }; diff --git a/src/core/cpu_newrec_compiler.cpp b/src/core/cpu_newrec_compiler.cpp index ae2acddeb..26a413de0 100644 --- a/src/core/cpu_newrec_compiler.cpp +++ b/src/core/cpu_newrec_compiler.cpp @@ -2350,10 +2350,10 @@ CPU::NewRec::Compiler::SpecValue CPU::NewRec::Compiler::SpecReadMem(VirtualMemor return it->second; u32 value; - if ((address & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) + if ((address & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR) { - u32 scratchpad_offset = address & DCACHE_OFFSET_MASK; - std::memcpy(&value, &CPU::g_state.dcache[scratchpad_offset], sizeof(value)); + u32 scratchpad_offset = address & SCRATCHPAD_OFFSET_MASK; + std::memcpy(&value, &CPU::g_state.scratchpad[scratchpad_offset], sizeof(value)); return value; } @@ -2378,7 +2378,7 @@ void CPU::NewRec::Compiler::SpecWriteMem(u32 address, SpecValue value) } const PhysicalMemoryAddress phys_addr = address & PHYSICAL_MEMORY_ADDRESS_MASK; - if ((address & DCACHE_LOCATION_MASK) == DCACHE_LOCATION || Bus::IsRAMAddress(phys_addr)) + if ((address & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR || Bus::IsRAMAddress(phys_addr)) m_speculative_constants.memory.emplace(address, value); } diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index 880e47318..ef7438176 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -3088,10 +3088,10 @@ CodeGenerator::SpeculativeValue CodeGenerator::SpeculativeReadMemory(VirtualMemo return it->second; u32 value; - if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION) + if ((phys_addr & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR) { - u32 scratchpad_offset = phys_addr & DCACHE_OFFSET_MASK; - std::memcpy(&value, &CPU::g_state.dcache[scratchpad_offset], sizeof(value)); + u32 scratchpad_offset = phys_addr & SCRATCHPAD_OFFSET_MASK; + std::memcpy(&value, &CPU::g_state.scratchpad[scratchpad_offset], sizeof(value)); return value; } @@ -3116,7 +3116,7 @@ void CodeGenerator::SpeculativeWriteMemory(u32 address, SpeculativeValue value) return; } - if ((phys_addr & DCACHE_LOCATION_MASK) == DCACHE_LOCATION || Bus::IsRAMAddress(phys_addr)) + if ((phys_addr & SCRATCHPAD_ADDR_MASK) == SCRATCHPAD_ADDR || Bus::IsRAMAddress(phys_addr)) m_speculative_constants.memory.emplace(address, value); } diff --git a/src/core/pgxp.cpp b/src/core/pgxp.cpp index 29fce1065..c6e611a06 100644 --- a/src/core/pgxp.cpp +++ b/src/core/pgxp.cpp @@ -20,7 +20,7 @@ enum : u32 VERTEX_CACHE_WIDTH = 0x800 * 2, VERTEX_CACHE_HEIGHT = 0x800 * 2, VERTEX_CACHE_SIZE = VERTEX_CACHE_WIDTH * VERTEX_CACHE_HEIGHT, - PGXP_MEM_SIZE = (static_cast(Bus::RAM_8MB_SIZE) + static_cast(CPU::DCACHE_SIZE)) / 4, + PGXP_MEM_SIZE = (static_cast(Bus::RAM_8MB_SIZE) + static_cast(CPU::SCRATCHPAD_SIZE)) / 4, PGXP_MEM_SCRATCH_OFFSET = Bus::RAM_8MB_SIZE / 4 }; @@ -142,8 +142,8 @@ ALWAYS_INLINE_RELEASE double f16Overflow(double in) ALWAYS_INLINE_RELEASE PGXP_value* GetPtr(u32 addr) { - if ((addr & CPU::DCACHE_LOCATION_MASK) == CPU::DCACHE_LOCATION) - return &Mem[PGXP_MEM_SCRATCH_OFFSET + ((addr & CPU::DCACHE_OFFSET_MASK) >> 2)]; + if ((addr & CPU::SCRATCHPAD_ADDR_MASK) == CPU::SCRATCHPAD_ADDR) + return &Mem[PGXP_MEM_SCRATCH_OFFSET + ((addr & CPU::SCRATCHPAD_OFFSET_MASK) >> 2)]; const u32 paddr = (addr & CPU::PHYSICAL_MEMORY_ADDRESS_MASK); if (paddr < Bus::RAM_MIRROR_END) diff --git a/src/duckstation-qt/cheatmanagerdialog.cpp b/src/duckstation-qt/cheatmanagerdialog.cpp index 61c2abc56..366f73e0c 100644 --- a/src/duckstation-qt/cheatmanagerdialog.cpp +++ b/src/duckstation-qt/cheatmanagerdialog.cpp @@ -162,8 +162,8 @@ void CheatManagerDialog::connectUi() } else if (index == 1) { - m_ui.scanStartAddress->setText(formatHexValue(CPU::DCACHE_LOCATION, 8)); - m_ui.scanEndAddress->setText(formatHexValue(CPU::DCACHE_LOCATION + CPU::DCACHE_SIZE, 8)); + m_ui.scanStartAddress->setText(formatHexValue(CPU::SCRATCHPAD_ADDR, 8)); + m_ui.scanEndAddress->setText(formatHexValue(CPU::SCRATCHPAD_ADDR + CPU::SCRATCHPAD_SIZE, 8)); } else {