mirror of
https://github.com/holub/mame
synced 2025-04-21 16:01:56 +03:00
m88000: add basic cmmu support
This commit is contained in:
parent
bc802bb8ac
commit
1f2ae2d47a
@ -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);
|
||||
if (fetch(m_fip & IP_A, m_fop))
|
||||
{
|
||||
// next becomes execute
|
||||
m_xop = m_nop;
|
||||
m_xip = m_nip;
|
||||
|
||||
// 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);
|
||||
|
||||
return true;
|
||||
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 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);
|
||||
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();
|
||||
|
||||
// update register
|
||||
if (reg)
|
||||
m_r[reg] = dst;
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 <typename T> void set_cmmu_d(T &&tag) { m_cmmu_d.set_tag(std::forward<T>(tag)); }
|
||||
template <typename T> void set_cmmu_i(T &&tag) { m_cmmu_i.set_tag(std::forward<T>(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<mc88200_device> m_cmmu_d;
|
||||
optional_device<mc88200_device> m_cmmu_i;
|
||||
|
||||
// register storage
|
||||
u32 m_xip; // execute instruction pointer
|
||||
u32 m_nip; // next instruction pointer
|
||||
|
Loading…
Reference in New Issue
Block a user