summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m88000/m88000.cpp
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2023-02-03 14:23:49 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2023-02-03 14:23:49 +0700
commit1f2ae2d47a01ff1c1aec0a3017973a608da83c9b (patch)
tree7d0e46f007b4d9395cbdefb32c1f8918a69d25b3 /src/devices/cpu/m88000/m88000.cpp
parentbc802bb8ac56259b1e305672f63a537c9c6dc87f (diff)
m88000: add basic cmmu support
Diffstat (limited to 'src/devices/cpu/m88000/m88000.cpp')
-rw-r--r--src/devices/cpu/m88000/m88000.cpp222
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);
+ }
}
}