diff options
author | 2023-02-03 14:23:49 +0700 | |
---|---|---|
committer | 2023-02-03 14:23:49 +0700 | |
commit | 1f2ae2d47a01ff1c1aec0a3017973a608da83c9b (patch) | |
tree | 7d0e46f007b4d9395cbdefb32c1f8918a69d25b3 /src/devices/cpu/m88000/m88000.cpp | |
parent | bc802bb8ac56259b1e305672f63a537c9c6dc87f (diff) |
m88000: add basic cmmu support
Diffstat (limited to 'src/devices/cpu/m88000/m88000.cpp')
-rw-r--r-- | src/devices/cpu/m88000/m88000.cpp | 222 |
1 files changed, 152 insertions, 70 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<u32> data = m_cmmu_i->read<u32>(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 <typename T> void mc88100_device::ld(u32 address, unsigned const reg) @@ -1453,35 +1460,64 @@ template <typename T> 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<T>() ? s32(T(m_data_space.read_byte(address))) : m_data_space.read_byte(address); + if constexpr (sizeof(T) < 8) + { + std::optional<T> const data = m_cmmu_d->read<typename std::make_unsigned<T>::type>(address, m_cr[PSR] & PSR_MODE); - if (reg) - m_r[reg] = data; + if (data.has_value() && reg) + m_r[reg] = std::is_signed<T>() ? s32(data.value()) : data.value(); + else if (!data.has_value()) + exception(E_DATA); + } + else + { + std::optional<u32> const lo = m_cmmu_d->read<u32>(address + 0, m_cr[PSR] & PSR_MODE); + std::optional<u32> const hi = m_cmmu_d->read<u32>(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<T>() ? 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<T>() ? 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<T>() ? 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 <typename T> 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 <typename T> void mc88100_device::xmem(u32 address, unsigned const reg) @@ -1526,28 +1588,48 @@ template <typename T> 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<T> const dst = m_cmmu_d->read<T>(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); + } } } |