summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips3.cpp')
-rw-r--r--src/devices/cpu/mips/mips3.cpp74
1 files changed, 47 insertions, 27 deletions
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp
index 178d81fadbd..8c8816b8e23 100644
--- a/src/devices/cpu/mips/mips3.cpp
+++ b/src/devices/cpu/mips/mips3.cpp
@@ -16,10 +16,9 @@
#include "ps2vu.h"
#include <cmath>
-#define ENABLE_OVERFLOWS (0)
-#define ENABLE_EE_ELF_LOADER (0)
-#define ENABLE_EE_DECI2 (0)
-#define DELAY_SLOT_EXCEPTION_HACK (0)
+#define ENABLE_OVERFLOWS (0)
+#define ENABLE_EE_ELF_LOADER (0)
+#define ENABLE_EE_DECI2 (0)
/***************************************************************************
HELPER MACROS
@@ -161,15 +160,13 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons
, m_pfnmask(flavor == MIPS3_TYPE_VR4300 ? 0x000fffff : 0x00ffffff)
, m_tlbentries(flavor == MIPS3_TYPE_VR4300 ? 32 : MIPS3_MAX_TLB_ENTRIES)
, m_bigendian(endianness == ENDIANNESS_BIG)
- , m_byte_xor(data_bits == 64 ? (m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)) : (m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)))
- , m_word_xor(data_bits == 64 ? (m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)) : (m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)))
- , m_dword_xor(data_bits == 64 ? (m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)) : 0)
+ , m_byte_xor(m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0))
+ , m_word_xor(m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0))
, c_icache_size(0)
, c_dcache_size(0)
- , c_secondary_cache_line_size(0)
, m_fastram_select(0)
, m_debugger_temp(0)
- , m_drc_cache(DRC_CACHE_SIZE + sizeof(internal_mips3_state) + 0x800000)
+ , m_drc_cache(DRC_CACHE_SIZE + sizeof(internal_mips3_state) + 0x80000)
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
@@ -316,11 +313,7 @@ void mips3_device::generate_exception(int exception, int backup)
if (!(SR & SR_EXL))
{
/* if we were in a branch delay slot, adjust */
-#if DELAY_SLOT_EXCEPTION_HACK
- if (((m_nextpc != ~0) || (m_delayslot)) && (m_ppc == m_core->pc - 4))
-#else
if ((m_nextpc != ~0) || (m_delayslot))
-#endif
{
m_delayslot = false;
m_nextpc = ~0;
@@ -343,7 +336,6 @@ void mips3_device::generate_exception(int exception, int backup)
if ((CAUSE & 0x7f) == 0)
logerror("Took interrupt -- Cause = %08X, PC = %08X\n", (uint32_t)CAUSE, m_core->pc);
*/
- debugger_exception_hook(exception);
}
@@ -1241,7 +1233,7 @@ inline bool mips3_device::RWORD(offs_t address, uint32_t *result, bool insn)
{
continue;
}
- *result = m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2];
+ *result = m_fastram[ramnum].offset_base32[tlbaddress >> 2];
return true;
}
*result = (*m_memory.read_dword)(*m_program, tlbaddress);
@@ -1411,7 +1403,7 @@ inline void mips3_device::WWORD(offs_t address, uint32_t data)
{
continue;
}
- m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2] = data;
+ m_fastram[ramnum].offset_base32[tlbaddress >> 2] = data;
return;
}
(*m_memory.write_dword)(*m_program, tlbaddress, data);
@@ -1780,7 +1772,7 @@ inline void mips3_device::set_cop0_creg(int idx, uint64_t val)
void mips3_device::handle_cop0(uint32_t op)
{
- if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0) && !(SR & (SR_EXL | SR_ERL)))
+ if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
{
m_badcop_value = 0;
generate_exception(EXCEPTION_BADCOP, 1);
@@ -1840,13 +1832,7 @@ void mips3_device::handle_cop0(uint32_t op)
break;
case 0x10: /* RFE */ invalid_instruction(op); break;
- case 0x18: /* ERET */
- m_core->pc = m_core->cpr[0][COP0_EPC];
- SR &= ~SR_EXL;
- check_irqs();
- m_lld_value ^= 0xffffffff;
- m_ll_value ^= 0xffffffff;
- break;
+ case 0x18: /* ERET */ m_core->pc = m_core->cpr[0][COP0_EPC]; SR &= ~SR_EXL; check_irqs(); m_lld_value ^= 0xffffffff; m_ll_value ^= 0xffffffff; break;
case 0x20: /* WAIT */ break;
default: handle_extra_cop0(op); break;
}
@@ -3530,13 +3516,47 @@ void mips3_device::handle_special(uint32_t op)
m_core->icount -= 35;
break;
case 0x1c: /* DMULT */
- LOVAL64 = mul_64x64(RSVAL64, RTVAL64, reinterpret_cast<s64 *>(&HIVAL64));
+ {
+ uint64_t a_hi = (uint32_t)(RSVAL64 >> 32);
+ uint64_t b_hi = (uint32_t)(RTVAL64 >> 32);
+ uint64_t a_lo = (uint32_t)RSVAL64;
+ uint64_t b_lo = (uint32_t)RTVAL64;
+ uint64_t p1 = a_lo * b_lo;
+ uint64_t p2 = a_hi * b_lo;
+ uint64_t p3 = a_lo * b_hi;
+ uint64_t p4 = a_hi * b_hi;
+ uint64_t carry = (uint32_t)(((p1 >> 32) + (uint32_t)p2 + (uint32_t)p3) >> 32);
+
+ LOVAL64 = p1 + (p2 << 32) + (p3 << 32);
+ HIVAL64 = p4 + (p2 >> 32) + (p3 >> 32) + carry;
+
+ // Adjust for sign
+ if (RSVAL64 < 0)
+ HIVAL64 -= RTVAL64;
+ if (RTVAL64 < 0)
+ HIVAL64 -= RSVAL64;
+
m_core->icount -= 7;
break;
+ }
case 0x1d: /* DMULTU */
- LOVAL64 = mulu_64x64(RSVAL64, RTVAL64, &HIVAL64);
+ {
+ uint64_t a_hi = (uint32_t)(RSVAL64 >> 32);
+ uint64_t b_hi = (uint32_t)(RTVAL64 >> 32);
+ uint64_t a_lo = (uint32_t)RSVAL64;
+ uint64_t b_lo = (uint32_t)RTVAL64;
+ uint64_t p1 = a_lo * b_lo;
+ uint64_t p2 = a_hi * b_lo;
+ uint64_t p3 = a_lo * b_hi;
+ uint64_t p4 = a_hi * b_hi;
+ uint64_t carry = (uint32_t)(((p1 >> 32) + (uint32_t)p2 + (uint32_t)p3) >> 32);
+
+ LOVAL64 = p1 + (p2 << 32) + (p3 << 32);
+ HIVAL64 = p4 + (p2 >> 32) + (p3 >> 32) + carry;
+
m_core->icount -= 7;
break;
+ }
case 0x1e: /* DDIV */
if (RTVAL64)
{
@@ -5480,7 +5500,7 @@ void mips3_device::load_elf()
void r5000be_device::handle_cache(uint32_t op)
{
- if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0) && !(SR & (SR_EXL | SR_ERL)))
+ if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
{
m_badcop_value = 0;
generate_exception(EXCEPTION_BADCOP, 1);