summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips1.cpp')
-rw-r--r--src/devices/cpu/mips/mips1.cpp112
1 files changed, 80 insertions, 32 deletions
diff --git a/src/devices/cpu/mips/mips1.cpp b/src/devices/cpu/mips/mips1.cpp
index c2a34e47e73..26260b836b4 100644
--- a/src/devices/cpu/mips/mips1.cpp
+++ b/src/devices/cpu/mips/mips1.cpp
@@ -54,9 +54,9 @@ DEFINE_DEVICE_TYPE(R3071, r3071_device, "r3071", "IDT R3071")
DEFINE_DEVICE_TYPE(R3081, r3081_device, "r3081", "IDT R3081")
DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 IOP")
-ALLOW_SAVE_TYPE(mips1core_device_base::branch_state_t);
+ALLOW_SAVE_TYPE(mips1core_device_base::branch_state);
-mips1core_device_base::mips1core_device_base(const machine_config &mconfig, device_type type, const char *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)
: 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)
@@ -71,64 +71,64 @@ mips1core_device_base::mips1core_device_base(const machine_config &mconfig, devi
{
}
-mips1_device_base::mips1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t 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)
: mips1core_device_base(mconfig, type, tag, owner, clock, cpurev, icache_size, dcache_size)
, m_fcr0(0)
{
}
-r2000_device::r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+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)
{
}
-r2000a_device::r2000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+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)
{
}
-r3000_device::r3000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+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)
{
}
-r3000a_device::r3000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+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)
{
}
-r3041_device::r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+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)
{
}
-r3051_device::r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+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)
{
}
-r3052_device::r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+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)
{
}
-r3052e_device::r3052e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+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)
{
}
-r3071_device::r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+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)
{
}
-r3081_device::r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+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)
{
set_fpu(0x0300);
}
-iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+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)
{
m_endianness = ENDIANNESS_LITTLE;
@@ -184,6 +184,8 @@ void mips1core_device_base::device_start()
// initialise cpu id register
m_cop0[COP0_PRId] = m_cpurev;
+ m_cop0[COP0_Cause] = 0;
+
m_r[0] = 0;
}
@@ -197,6 +199,10 @@ void r3041_device::device_start()
state_add(MIPS1_COP0 + COP0_Count, "Count", m_cop0[COP0_Count]);
state_add(MIPS1_COP0 + COP0_PortSize, "PortSize", m_cop0[COP0_PortSize]);
state_add(MIPS1_COP0 + COP0_Compare, "Compare", m_cop0[COP0_Compare]);
+
+ m_cop0[COP0_BusCtrl] = 0x20130b00U;
+ m_cop0[COP0_Config] = 0x40000000U;
+ m_cop0[COP0_PortSize] = 0;
}
void mips1core_device_base::device_reset()
@@ -212,6 +218,14 @@ void mips1core_device_base::device_reset()
m_bus_error = false;
}
+void r3041_device::device_reset()
+{
+ mips1core_device_base::device_reset();
+
+ m_cop0[COP0_Count] = 0;
+ m_cop0[COP0_Compare] = 0x00ffffffU;
+}
+
void mips1core_device_base::execute_run()
{
// core execution loop
@@ -649,13 +663,8 @@ bool mips1core_device_base::memory_translate(int spacenum, int intention, offs_t
}
else if (SR & SR_KUc)
{
- if (!machine().side_effects_disabled())
- {
- // exception
- m_cop0[COP0_BadVAddr] = address;
+ address_error(intention, address);
- generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
- }
return false;
}
}
@@ -861,6 +870,21 @@ void mips1core_device_base::generate_exception(u32 exception, bool refill)
debugger_privilege_hook();
}
+void mips1core_device_base::address_error(int intention, u32 const address)
+{
+ if (!machine().side_effects_disabled() && !(intention & TRANSLATE_DEBUG_MASK))
+ {
+ logerror("address_error 0x%08x (%s)\n", address, machine().describe_context());
+
+ m_cop0[COP0_BadVAddr] = address;
+
+ generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
+
+ // address errors shouldn't typically occur, so a breakpoint is handy
+ machine().debug_break();
+ }
+}
+
void mips1core_device_base::handle_cop0(u32 const op)
{
switch (RSREG)
@@ -1032,7 +1056,7 @@ void mips1core_device_base::handle_cop3(u32 const op)
void mips1core_device_base::lwl(u32 const op)
{
offs_t const offset = SIMMVAL + m_r[RSREG];
- load<u32>(offset & ~3, [this, op, offset](u32 temp)
+ load<u32, false>(offset, [this, op, offset](u32 temp)
{
unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
@@ -1043,7 +1067,7 @@ void mips1core_device_base::lwl(u32 const op)
void mips1core_device_base::lwr(u32 const op)
{
offs_t const offset = SIMMVAL + m_r[RSREG];
- load<u32>(offset & ~3, [this, op, offset](u32 temp)
+ load<u32, false>(offset, [this, op, offset](u32 temp)
{
unsigned const shift = ((offset & 0x3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
@@ -1056,7 +1080,7 @@ void mips1core_device_base::swl(u32 const op)
offs_t const offset = SIMMVAL + m_r[RSREG];
unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
- store<u32>(offset & ~3, m_r[RTREG] >> shift, 0xffffffffU >> shift);
+ store<u32, false>(offset, m_r[RTREG] >> shift, 0xffffffffU >> shift);
}
void mips1core_device_base::swr(u32 const op)
@@ -1064,13 +1088,24 @@ void mips1core_device_base::swr(u32 const op)
offs_t const offset = SIMMVAL + m_r[RSREG];
unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
- store<u32>(offset & ~3, m_r[RTREG] << shift, 0xffffffffU << shift);
+ store<u32, false>(offset, m_r[RTREG] << shift, 0xffffffffU << shift);
}
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> mips1core_device_base::load(u32 address, U &&apply)
+template <typename T, bool Aligned, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> mips1core_device_base::load(u32 address, U &&apply)
{
+ // alignment error
+ if (Aligned && (address & (sizeof(T) - 1)))
+ {
+ address_error(TRANSLATE_READ, address);
+ return;
+ }
+
if (memory_translate(m_data_spacenum, TRANSLATE_READ, address))
{
+ // align address for ld[lr] instructions
+ if (!Aligned)
+ address &= ~(sizeof(T) - 1);
+
T const data
= (sizeof(T) == 1) ? space(m_data_spacenum).read_byte(address)
: (sizeof(T) == 2) ? space(m_data_spacenum).read_word(address)
@@ -1086,10 +1121,21 @@ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::f
}
}
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> mips1core_device_base::store(u32 address, U data, T mem_mask)
+template <typename T, bool Aligned, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> mips1core_device_base::store(u32 address, U data, T mem_mask)
{
+ // alignment error
+ if (Aligned && (address & (sizeof(T) - 1)))
+ {
+ address_error(TRANSLATE_WRITE, address);
+ return;
+ }
+
if (memory_translate(m_data_spacenum, TRANSLATE_WRITE, address))
{
+ // align address for sd[lr] instructions
+ if (!Aligned)
+ address &= ~(sizeof(T) - 1);
+
switch (sizeof(T))
{
case 1: space(m_data_spacenum).write_byte(address, T(data)); break;
@@ -1101,6 +1147,13 @@ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::va
bool mips1core_device_base::fetch(u32 address, std::function<void(u32)> &&apply)
{
+ // alignment error
+ if (address & 3)
+ {
+ address_error(TRANSLATE_FETCH, address);
+ return false;
+ }
+
if (memory_translate(0, TRANSLATE_FETCH, address))
{
u32 const data = space(0).read_dword(address);
@@ -1913,13 +1966,8 @@ bool mips1_device_base::memory_translate(int spacenum, int intention, offs_t &ad
}
else if (SR & SR_KUc)
{
- if (!machine().side_effects_disabled())
- {
- // exception
- m_cop0[COP0_BadVAddr] = address;
+ address_error(intention, address);
- generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
- }
return false;
}
}