From ab3ad7671dbf106aeccf976e316eea372635d38e Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Tue, 8 Aug 2023 18:11:20 +0700 Subject: mips1: improved cache logic for partial word store --- src/devices/cpu/mips/mips1.cpp | 54 +++++++++++++++++++++++++++--------------- src/devices/cpu/mips/mips1.h | 5 ++-- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/devices/cpu/mips/mips1.cpp b/src/devices/cpu/mips/mips1.cpp index 8dd77b3a0bd..da2b9f666c6 100644 --- a/src/devices/cpu/mips/mips1.cpp +++ b/src/devices/cpu/mips/mips1.cpp @@ -215,7 +215,7 @@ DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 ALLOW_SAVE_TYPE(mips1core_device_base::branch_state); -mips1core_device_base::mips1core_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size) +mips1core_device_base::mips1core_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size, bool cache_pws) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config_be("program", ENDIANNESS_BIG, 32, 32) , m_program_config_le("program", ENDIANNESS_LITTLE, 32, 32) @@ -225,69 +225,70 @@ mips1core_device_base::mips1core_device_base(machine_config const &mconfig, devi , m_icache(icache_size) , m_dcache(dcache_size) , m_cache((icache_size && dcache_size) ? CACHED : UNCACHED) + , m_cache_pws(cache_pws) , m_in_brcond(*this, 0) { } -mips1_device_base::mips1_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size) - : mips1core_device_base(mconfig, type, tag, owner, clock, cpurev, icache_size, dcache_size) +mips1_device_base::mips1_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size, bool cache_pws) + : mips1core_device_base(mconfig, type, tag, owner, clock, cpurev, icache_size, dcache_size, cache_pws) , m_fcr0(0) { } r2000_device::r2000_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size) - : mips1_device_base(mconfig, R2000, tag, owner, clock, 0x0100, icache_size, dcache_size) + : mips1_device_base(mconfig, R2000, tag, owner, clock, 0x0100, icache_size, dcache_size, false) { } r2000a_device::r2000a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size) - : mips1_device_base(mconfig, R2000A, tag, owner, clock, 0x0210, icache_size, dcache_size) + : mips1_device_base(mconfig, R2000A, tag, owner, clock, 0x0210, icache_size, dcache_size, false) { } r3000_device::r3000_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size) - : mips1_device_base(mconfig, R3000, tag, owner, clock, 0x0220, icache_size, dcache_size) + : mips1_device_base(mconfig, R3000, tag, owner, clock, 0x0220, icache_size, dcache_size, false) { } r3000a_device::r3000a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size) - : mips1_device_base(mconfig, R3000A, tag, owner, clock, 0x0230, icache_size, dcache_size) + : mips1_device_base(mconfig, R3000A, tag, owner, clock, 0x0230, icache_size, dcache_size, false) { } r3041_device::r3041_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : mips1core_device_base(mconfig, R3041, tag, owner, clock, 0x0700, 2048, 512) + : mips1core_device_base(mconfig, R3041, tag, owner, clock, 0x0700, 2048, 512, true) { } r3051_device::r3051_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : mips1core_device_base(mconfig, R3051, tag, owner, clock, 0x0200, 4096, 2048) + : mips1core_device_base(mconfig, R3051, tag, owner, clock, 0x0200, 4096, 2048, true) { } r3052_device::r3052_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : mips1core_device_base(mconfig, R3052, tag, owner, clock, 0x0200, 8192, 2048) + : mips1core_device_base(mconfig, R3052, tag, owner, clock, 0x0200, 8192, 2048, true) { } r3052e_device::r3052e_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : mips1_device_base(mconfig, R3052E, tag, owner, clock, 0x0200, 8192, 2048) + : mips1_device_base(mconfig, R3052E, tag, owner, clock, 0x0200, 8192, 2048, true) { } r3071_device::r3071_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size) - : mips1_device_base(mconfig, R3071, tag, owner, clock, 0x0200, icache_size, dcache_size) + : mips1_device_base(mconfig, R3071, tag, owner, clock, 0x0200, icache_size, dcache_size, true) { } r3081_device::r3081_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size) - : mips1_device_base(mconfig, R3081, tag, owner, clock, 0x0200, icache_size, dcache_size) + : mips1_device_base(mconfig, R3081, tag, owner, clock, 0x0200, icache_size, dcache_size, true) { set_fpu(0x0300); } iop_device::iop_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : mips1core_device_base(mconfig, SONYPS2_IOP, tag, owner, clock, 0x001f, 4096, 1024) + : mips1core_device_base(mconfig, SONYPS2_IOP, tag, owner, clock, 0x001f, 4096, 1024, false) { m_endianness = ENDIANNESS_LITTLE; } @@ -1390,15 +1391,30 @@ template void mips1core_device_base::store(u32 addres { auto [l, miss] = cache_lookup(address, sizeof(T) == 4); - if (!miss) + // cached full word stores always update the cache + if constexpr (Aligned && sizeof(T) == 4) + l.update(data); + else if (!miss) { - unsigned const shift = shift_factor(address); + if (!m_cache_pws) + { + // reload the cache line from memory + u32 const data = space(AS_PROGRAM).read_dword(address); + if (m_bus_error) + { + m_bus_error = false; + generate_exception(EXCEPTION_BUSDATA); + return; + } + + l.update(data); + } + + // merge data into the cache + unsigned const shift = shift_factor(address); l.update(u32(data) << shift, u32(mem_mask) << shift); } - else if constexpr (Aligned && sizeof(T) == 4) - // only full word stores update the cache after a miss - l.update(data, mem_mask); } // uncached or write-through store diff --git a/src/devices/cpu/mips/mips1.h b/src/devices/cpu/mips/mips1.h index e5a38b060c5..c94629a7896 100644 --- a/src/devices/cpu/mips/mips1.h +++ b/src/devices/cpu/mips/mips1.h @@ -17,7 +17,7 @@ public: void berr_w(int state) { m_bus_error = bool(state); } protected: - mips1core_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size); + mips1core_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size, bool cache_pws); // device_t implementation virtual void device_start() override; @@ -136,6 +136,7 @@ protected: struct cache m_icache; struct cache m_dcache; translate_result const m_cache; + bool const m_cache_pws; // cache supports partial-word store // I/O devcb_read_line::array<4> m_in_brcond; @@ -160,7 +161,7 @@ public: void set_fpu(u32 revision, unsigned interrupt = 3) { m_fcr0 = revision; m_fpu_irq = interrupt; } protected: - mips1_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size); + mips1_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size, bool cache_pws); // device_t implementation virtual void device_start() override; -- cgit v1.2.3