mips1: improved cache logic for partial word store

This commit is contained in:
Patrick Mackinlay 2023-08-08 18:11:20 +07:00
parent f3845348ba
commit ab3ad7671d
2 changed files with 38 additions and 21 deletions

View File

@ -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 <typename T, bool Aligned> 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<T>(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<T>(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

View File

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