CPU: Fix incorrect scratchpad masking

This commit is contained in:
Stenzek 2023-11-06 18:09:27 +10:00
parent c5cd55ffb1
commit 3dfc3bd2ba
No known key found for this signature in database
9 changed files with 56 additions and 54 deletions

View File

@ -711,7 +711,7 @@ std::optional<Bus::MemoryRegion> Bus::GetMemoryRegionForAddress(PhysicalMemoryAd
return static_cast<MemoryRegion>(static_cast<u32>(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<std::pair<PhysicalMemoryAddress, PhysicalMemoryAddre
{Bus::RAM_2MB_SIZE * 2, Bus::RAM_2MB_SIZE * 3},
{Bus::RAM_2MB_SIZE * 3, Bus::RAM_MIRROR_END},
{Bus::EXP1_BASE, Bus::EXP1_BASE + Bus::EXP1_SIZE},
{CPU::DCACHE_LOCATION, CPU::DCACHE_LOCATION + CPU::DCACHE_SIZE},
{CPU::SCRATCHPAD_ADDR, CPU::SCRATCHPAD_ADDR + CPU::SCRATCHPAD_SIZE},
{Bus::BIOS_BASE, Bus::BIOS_BASE + Bus::BIOS_SIZE},
}};
@ -761,7 +761,7 @@ u8* Bus::GetMemoryRegionPointer(MemoryRegion region)
return nullptr;
case MemoryRegion::Scratchpad:
return CPU::g_state.dcache.data();
return CPU::g_state.scratchpad.data();
case MemoryRegion::BIOS:
return g_bios;
@ -982,24 +982,24 @@ u32 Bus::BIOSReadHandler(VirtualMemoryAddress address)
template<MemoryAccessSize size>
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<size>(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<MemoryAccessSize size>
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<size>(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<MemoryAccessSize size>
@ -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);

View File

@ -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]

View File

@ -25,8 +25,8 @@ using KeyValuePairVector = std::vector<std::pair<std::string, std::string>>;
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<u16>(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value16);
DoMemoryWrite<u16>(CPU::SCRATCHPAD_ADDR | (inst.address & CPU::SCRATCHPAD_OFFSET_MASK), inst.value16);
index++;
}
break;
case InstructionCode::ExtScratchpadWrite32:
{
DoMemoryWrite<u32>(CPU::DCACHE_LOCATION | (inst.address & CPU::DCACHE_OFFSET_MASK), inst.value32);
DoMemoryWrite<u32>(CPU::SCRATCHPAD_ADDR | (inst.address & CPU::SCRATCHPAD_OFFSET_MASK), inst.value32);
index++;
}
break;

View File

@ -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;
}

View File

@ -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<u8, DCACHE_SIZE> dcache = {};
std::array<u32, ICACHE_LINES> icache_tags = {};
std::array<u8, ICACHE_SIZE> icache_data = {};
std::array<u8, SCRATCHPAD_SIZE> 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); }
};

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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<u32>(Bus::RAM_8MB_SIZE) + static_cast<u32>(CPU::DCACHE_SIZE)) / 4,
PGXP_MEM_SIZE = (static_cast<u32>(Bus::RAM_8MB_SIZE) + static_cast<u32>(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)

View File

@ -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
{