summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2019-07-25 18:48:08 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2019-07-25 18:48:08 +0700
commite31685d6b1a1e44e9cf081672a27669ff240f066 (patch)
tree3a97362cbe27af9e609de0e4eeb2c3a95e46e2c8
parent4c34a13da1aae9625b18d922078108a793486586 (diff)
mips1: diagnostic fixes (nw)
Some fixes identified by MIPS Rx3230 diagnostics: * assert/clear irq based on fpu exception state * mask entryhi/lo reserved bits
-rw-r--r--src/devices/cpu/mips/mips1.cpp73
-rw-r--r--src/devices/cpu/mips/mips1.h5
2 files changed, 53 insertions, 25 deletions
diff --git a/src/devices/cpu/mips/mips1.cpp b/src/devices/cpu/mips/mips1.cpp
index eb379a225d0..21f49301e26 100644
--- a/src/devices/cpu/mips/mips1.cpp
+++ b/src/devices/cpu/mips/mips1.cpp
@@ -912,32 +912,31 @@ void mips1core_device_base::set_cop0_reg(unsigned const reg, u32 const data)
{
switch (reg)
{
- case COP0_Context:
- m_cop0[COP0_Context] = (m_cop0[COP0_Context] & ~PTE_BASE) | (data & PTE_BASE);
- break;
case COP0_Status:
- {
- u32 const delta = SR ^ data;
+ {
+ u32 const delta = SR ^ data;
- m_cop0[COP0_Status] = data;
+ m_cop0[COP0_Status] = data;
- // handle cache isolation and swap
- m_data_spacenum = (data & SR_IsC) ? ((data & SR_SwC) ? 1 : 2) : 0;
+ // handle cache isolation and swap
+ m_data_spacenum = (data & SR_IsC) ? ((data & SR_SwC) ? 1 : 2) : 0;
- // update interrupts
- if (delta & (SR_IEc | SR_IM))
- check_irqs();
+ // update interrupts
+ if (delta & (SR_IEc | SR_IM))
+ check_irqs();
+
+ if ((delta & SR_KUc) && (m_branch_state != EXCEPTION))
+ debugger_privilege_hook();
+ }
+ break;
- if ((delta & SR_KUc) && (m_branch_state != EXCEPTION))
- debugger_privilege_hook();
- }
- break;
case COP0_Cause:
CAUSE = (CAUSE & CAUSE_IPEX) | (data & ~CAUSE_IPEX);
// update interrupts -- software ints can occur this way
check_irqs();
break;
+
case COP0_PRId:
// read-only register
break;
@@ -1193,7 +1192,7 @@ void mips1_device_base::device_start()
{
state_add(MIPS1_FCR31, "FCSR", m_fcr31);
for (unsigned i = 0; i < ARRAY_LENGTH(m_f); i++)
- state_add(MIPS1_F0 + i, util::string_format("F%d", i).c_str(), m_f[i]);
+ state_add(MIPS1_F0 + i, util::string_format("F%d", i * 2).c_str(), m_f[i]);
}
save_item(NAME(m_reset_time));
@@ -1303,6 +1302,28 @@ u32 mips1_device_base::get_cop0_reg(unsigned const reg)
return m_cop0[reg];
}
+void mips1_device_base::set_cop0_reg(unsigned const reg, u32 const data)
+{
+ switch (reg)
+ {
+ case COP0_EntryHi:
+ m_cop0[COP0_EntryHi] = data & EH_WM;
+ break;
+
+ case COP0_EntryLo:
+ m_cop0[COP0_EntryLo] = data & EL_WM;
+ break;
+
+ case COP0_Context:
+ m_cop0[COP0_Context] = (m_cop0[COP0_Context] & ~PTE_BASE) | (data & PTE_BASE);
+ break;
+
+ default:
+ mips1core_device_base::set_cop0_reg(reg, data);
+ break;
+ }
+}
+
void mips1_device_base::handle_cop1(u32 const op)
{
if (!(SR & SR_COP1))
@@ -1371,8 +1392,10 @@ void mips1_device_base::handle_cop1(u32 const op)
}
// exception check
- if ((m_fcr31 & FCR31_CE) || ((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM))
- execute_set_input(m_fpu_irq, ASSERT_LINE);
+ {
+ bool const exception = (m_fcr31 & FCR31_CE) || (((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM));
+ execute_set_input(m_fpu_irq, exception ? ASSERT_LINE : CLEAR_LINE);
+ }
break;
default:
@@ -1847,15 +1870,15 @@ template <typename T> void mips1_device_base::set_cop1_reg(unsigned const reg, T
if (softfloat_exceptionFlags & softfloat_flag_invalid)
m_fcr31 |= FCR31_CV;
- // check if exception is enabled
- if (((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM))
- {
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- return;
- }
-
// set flags
m_fcr31 |= ((m_fcr31 & FCR31_CM) >> 10);
+
+ // update exception state
+ bool const exception = (m_fcr31 & FCR31_CE) || ((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM);
+ execute_set_input(m_fpu_irq, exception ? ASSERT_LINE : CLEAR_LINE);
+
+ if (exception)
+ return;
}
if (sizeof(T) == 4)
diff --git a/src/devices/cpu/mips/mips1.h b/src/devices/cpu/mips/mips1.h
index 1e56394ede6..a7cde9cdfd7 100644
--- a/src/devices/cpu/mips/mips1.h
+++ b/src/devices/cpu/mips/mips1.h
@@ -131,6 +131,8 @@ protected:
{
EH_VPN = 0xfffff000, // virtual page number
EH_ASID = 0x00000fc0, // address space identifier
+
+ EH_WM = 0xffffffc0, // write mask
};
enum entrylo_mask : u32
{
@@ -139,6 +141,8 @@ protected:
EL_D = 0x00000400, // dirty
EL_V = 0x00000200, // valid
EL_G = 0x00000100, // global
+
+ EL_WM = 0xffffff00, // write mask
};
enum context_mask : u32
{
@@ -298,6 +302,7 @@ protected:
virtual void handle_cop0(u32 const op) override;
virtual u32 get_cop0_reg(unsigned const reg) override;
+ virtual void set_cop0_reg(unsigned const reg, u32 const data) override;
virtual void handle_cop1(u32 const op) override;
template <typename T> void set_cop1_reg(unsigned const reg, T const data);