From 1f2ae2d47a01ff1c1aec0a3017973a608da83c9b Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Fri, 3 Feb 2023 14:23:49 +0700 Subject: m88000: add basic cmmu support --- src/devices/cpu/m88000/m88000.cpp | 222 ++++++++++++++++++++++++++------------ src/devices/cpu/m88000/m88000.h | 9 +- 2 files changed, 160 insertions(+), 71 deletions(-) diff --git a/src/devices/cpu/m88000/m88000.cpp b/src/devices/cpu/m88000/m88000.cpp index c0df2a80a24..657af493133 100644 --- a/src/devices/cpu/m88000/m88000.cpp +++ b/src/devices/cpu/m88000/m88000.cpp @@ -5,10 +5,6 @@ * Motorola M88000 Family of RISC microprocessors. * * TODO: - * - cache/mmu interface - * - misaligned access exceptions - * - floating point exceptions - * - user/supervisor space * - xip/fip/nip exception flag * - pipeline and cycles counts * - mc88110 @@ -131,9 +127,8 @@ mc88100_device::mc88100_device(const machine_config &mconfig, const char *tag, d : cpu_device(mconfig, MC88100, tag, owner, clock) , m_code_config("code", ENDIANNESS_BIG, 32, 32, 0) , m_data_config("data", ENDIANNESS_BIG, 32, 32, 0) - , m_xip(0) - , m_nip(0) - , m_fip(0) + , m_cmmu_d(*this, finder_base::DUMMY_TAG) + , m_cmmu_i(*this, finder_base::DUMMY_TAG) , m_sb(0) , m_r{ 0 } , m_cr{ 0 } @@ -161,7 +156,7 @@ device_memory_interface::space_config_vector mc88100_device::memory_space_config void mc88100_device::device_start() { - space(AS_PROGRAM).cache(m_inst_cache); + space(AS_PROGRAM).specific(m_inst_space); if (has_configured_map(AS_DATA)) space(AS_DATA).specific(m_data_space); @@ -191,7 +186,7 @@ void mc88100_device::device_start() state_add(36 + SR2, "sr2", m_cr[SR2]); state_add(36 + SR3, "sr3", m_cr[SR3]); - for (int i = 1; i < 32; i++) + for (int i = 0; i < 32; i++) state_add(i, string_format("r%d", i).c_str(), m_r[i]); save_item(NAME(m_xip)); @@ -246,20 +241,19 @@ void mc88100_device::execute_run() execute(m_xop); } - // fetch - if (m_fip & IP_V) - fetch(m_fip & IP_A, m_fop); - - // next becomes execute - m_xop = m_nop; - m_xip = m_nip; + if (fetch(m_fip & IP_A, m_fop)) + { + // next becomes execute + m_xop = m_nop; + m_xip = m_nip; - // fetch becomes next - m_nop = m_fop; - m_nip = m_fip; + // fetch becomes next + m_nop = m_fop; + m_nip = m_fip; - // increment fetch - m_fip += 4; + // increment fetch + m_fip += 4; + } m_icount--; } @@ -1433,9 +1427,22 @@ void mc88100_device::fset(unsigned const td, unsigned const d, float64_t const d bool mc88100_device::fetch(u32 address, u32 &inst) { - inst = m_inst_cache.read_dword(address); + if (m_cmmu_i) + { + std::optional data = m_cmmu_i->read(address, m_cr[PSR] & PSR_MODE); + if (data.has_value()) + inst = data.value(); + else + exception(E_INSTRUCTION); - return true; + return data.has_value(); + } + else + { + inst = m_inst_space.read_dword(address); + + return true; + } } template void mc88100_device::ld(u32 address, unsigned const reg) @@ -1453,35 +1460,64 @@ template void mc88100_device::ld(u32 address, unsigned const reg) address &= ~(sizeof(T) - 1); } - if constexpr (sizeof(T) == 1) + if (m_cmmu_d) { - u32 const data = std::is_signed() ? s32(T(m_data_space.read_byte(address))) : m_data_space.read_byte(address); + if constexpr (sizeof(T) < 8) + { + std::optional const data = m_cmmu_d->read::type>(address, m_cr[PSR] & PSR_MODE); - if (reg) - m_r[reg] = data; + if (data.has_value() && reg) + m_r[reg] = std::is_signed() ? s32(data.value()) : data.value(); + else if (!data.has_value()) + exception(E_DATA); + } + else + { + std::optional const lo = m_cmmu_d->read(address + 0, m_cr[PSR] & PSR_MODE); + std::optional const hi = m_cmmu_d->read(address + 4, m_cr[PSR] & PSR_MODE); + if (lo.has_value() && hi.has_value()) + { + if (reg != 0) + m_r[(reg + 0) & 31] = hi.value(); + if (reg != 31) + m_r[(reg + 1) & 31] = lo.value(); + } + else + exception(E_DATA); + } } - else if constexpr (sizeof(T) == 2) + else { - u32 const data = std::is_signed() ? s32(T(m_data_space.read_word(address))) : m_data_space.read_word(address); + if constexpr (sizeof(T) == 1) + { + u32 const data = std::is_signed() ? s32(T(m_data_space.read_byte(address))) : m_data_space.read_byte(address); - if (reg) - m_r[reg] = data; - } - else if constexpr (sizeof(T) == 4) - { - u32 const data = m_data_space.read_dword(address); + if (reg) + m_r[reg] = data; + } + else if constexpr (sizeof(T) == 2) + { + u32 const data = std::is_signed() ? s32(T(m_data_space.read_word(address))) : m_data_space.read_word(address); - if (reg) - m_r[reg] = data; - } - else if constexpr (sizeof(T) == 8) - { - u64 const data = m_data_space.read_qword(address); + if (reg) + m_r[reg] = data; + } + else if constexpr (sizeof(T) == 4) + { + u32 const data = m_data_space.read_dword(address); - if (reg != 0) - m_r[(reg + 0) & 31] = u32(data >> 32); - if (reg != 31) - m_r[(reg + 1) & 31] = u32(data >> 0); + if (reg) + m_r[reg] = data; + } + else if constexpr (sizeof(T) == 8) + { + u64 const data = m_data_space.read_qword(address); + + if (reg != 0) + m_r[(reg + 0) & 31] = u32(data >> 32); + if (reg != 31) + m_r[(reg + 1) & 31] = u32(data >> 0); + } } } @@ -1500,16 +1536,42 @@ template bool mc88100_device::st(u32 address, unsigned const reg) address &= ~(sizeof(T) - 1); } - if constexpr (sizeof(T) == 1) - m_data_space.write_byte(address, m_r[reg]); - else if constexpr (sizeof(T) == 2) - m_data_space.write_word(address, m_r[reg]); - else if constexpr (sizeof(T) == 4) - m_data_space.write_dword(address, m_r[reg]); - else if constexpr (sizeof(T) == 8) - m_data_space.write_qword(address, (u64(m_r[(reg + 0) & 31]) << 32) | m_r[(reg + 1) & 31]); + if (m_cmmu_d) + { + if constexpr (sizeof(T) < 8) + { + bool const result = m_cmmu_d->write(address, T(m_r[reg]), m_cr[PSR] & PSR_MODE); + + if (!result) + exception(E_DATA); + + return result; + } + else + { + bool result = true; + result &= m_cmmu_d->write(address + 0, m_r[(reg + 1) & 31], m_cr[PSR] & PSR_MODE); + result &= m_cmmu_d->write(address + 4, m_r[(reg + 0) & 31], m_cr[PSR] & PSR_MODE); + + if (!result) + exception(E_DATA); - return true; + return result; + } + } + else + { + if constexpr (sizeof(T) == 1) + m_data_space.write_byte(address, m_r[reg]); + else if constexpr (sizeof(T) == 2) + m_data_space.write_word(address, m_r[reg]); + else if constexpr (sizeof(T) == 4) + m_data_space.write_dword(address, m_r[reg]); + else if constexpr (sizeof(T) == 8) + m_data_space.write_qword(address, (u64(m_r[(reg + 0) & 31]) << 32) | m_r[(reg + 1) & 31]); + + return true; + } } template void mc88100_device::xmem(u32 address, unsigned const reg) @@ -1526,28 +1588,48 @@ template void mc88100_device::xmem(u32 address, unsigned const reg) // save source value T const src = m_r[reg]; - if constexpr (sizeof(T) == 1) + if (m_cmmu_d) { // read destination - T const dst = m_data_space.read_byte(address); - - // update register - if (reg) - m_r[reg] = dst; + std::optional const dst = m_cmmu_d->read(address, m_cr[PSR] & PSR_MODE); + if (dst.has_value()) + { + // update register + if (reg) + m_r[reg] = dst.value(); - // write destination - m_data_space.write_byte(address, src); + // write destination + if (!m_cmmu_d->write(address, src, m_cr[PSR] & PSR_MODE)) + exception(E_DATA); + } + else + exception(E_DATA); } - else if constexpr (sizeof(T) == 4) + else { - // read destination - T const dst = m_data_space.read_dword(address); + if constexpr (sizeof(T) == 1) + { + // read destination + T const dst = m_data_space.read_byte(address); - // update register - if (reg) - m_r[reg] = dst; + // update register + if (reg) + m_r[reg] = dst; - // write destination - m_data_space.write_dword(address, src); + // write destination + m_data_space.write_byte(address, src); + } + else if constexpr (sizeof(T) == 4) + { + // read destination + T const dst = m_data_space.read_dword(address); + + // update register + if (reg) + m_r[reg] = dst; + + // write destination + m_data_space.write_dword(address, src); + } } } diff --git a/src/devices/cpu/m88000/m88000.h b/src/devices/cpu/m88000/m88000.h index dc711d5a5b2..668d3fe5c62 100644 --- a/src/devices/cpu/m88000/m88000.h +++ b/src/devices/cpu/m88000/m88000.h @@ -11,6 +11,7 @@ #pragma once +#include "machine/mc88200.h" #include "softfloat3/source/include/softfloat.h" class mc88100_device : public cpu_device @@ -19,6 +20,9 @@ public: // construction/destruction mc88100_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + template void set_cmmu_d(T &&tag) { m_cmmu_d.set_tag(std::forward(tag)); } + template void set_cmmu_i(T &&tag) { m_cmmu_i.set_tag(std::forward(tag)); } + protected: // device-level overrides virtual void device_start() override; @@ -59,9 +63,12 @@ private: // address spaces address_space_config m_code_config; address_space_config m_data_config; - memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_inst_cache; + memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_inst_space; memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_data_space; + optional_device m_cmmu_d; + optional_device m_cmmu_i; + // register storage u32 m_xip; // execute instruction pointer u32 m_nip; // next instruction pointer -- cgit v1.2.3