diff options
Diffstat (limited to 'src/devices/cpu/mips/r4000.cpp')
-rw-r--r-- | src/devices/cpu/mips/r4000.cpp | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/src/devices/cpu/mips/r4000.cpp b/src/devices/cpu/mips/r4000.cpp index ca95b107c65..28adcda0e15 100644 --- a/src/devices/cpu/mips/r4000.cpp +++ b/src/devices/cpu/mips/r4000.cpp @@ -1642,7 +1642,7 @@ void r4000_base_device::cp1_execute(u32 const op) break; case 0x04: // MTC1 if (SR & SR_FR) - m_f[RDREG] = u32(m_r[RTREG]); + m_f[RDREG] = (m_f[RDREG] & ~0xffffffffULL) | u32(m_r[RTREG]); else if (RDREG & 1) // load the high half of the even floating point register @@ -1761,12 +1761,27 @@ void r4000_base_device::cp1_execute(u32 const op) if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ 0 })) cp1_set(FDREG, f32_mul(float32_t{ u32(m_f[FSREG]) }, i32_to_f32(-1)).v); else - cp1_set(FDREG, m_f[FSREG]); + cp1_set(FDREG, u32(m_f[FSREG])); } break; case 0x06: // MOV.S - if ((SR & SR_FR) || !(op & ODD_REGS)) - m_f[FDREG] = m_f[FSREG]; + if (SR & SR_FR) + m_f[FDREG] = (m_f[FDREG] & ~0xffffffffULL) | u32(m_f[FSREG]); + else + if (FDREG & 1) + if (FSREG & 1) + // move high half to high half + m_f[FDREG & ~1] = (m_f[FSREG & ~1] & ~0xffffffffULL) | u32(m_f[FDREG & ~1]); + else + // move low half to high half + m_f[FDREG & ~1] = (m_f[FSREG & ~1] << 32) | u32(m_f[FDREG & ~1]); + else + if (FSREG & 1) + // move high half to low half + m_f[FDREG & ~1] = (m_f[FDREG & ~1] & ~0xffffffffULL) | (m_f[FSREG & ~1] >> 32); + else + // move low half to low half + m_f[FDREG & ~1] = (m_f[FDREG & ~1] & ~0xffffffffULL) | u32(m_f[FSREG & ~1]); break; case 0x07: // NEG.S if ((SR & SR_FR) || !(op & ODD_REGS)) @@ -2358,7 +2373,7 @@ void r4000_base_device::cp1_execute(u32 const op) [this, op](u32 data) { if (SR & SR_FR) - m_f[RTREG] = data; + m_f[RTREG] = (m_f[RTREG] & ~0xffffffffULL) | data; else if (RTREG & 1) // load the high half of the even floating point register @@ -2397,7 +2412,7 @@ void r4000_base_device::cp1_execute(u32 const op) } } -void r4000_base_device::cp1_set(unsigned const reg, u64 const data) +template <typename T> void r4000_base_device::cp1_set(unsigned const reg, T const data) { // translate softfloat exception flags to cause register if (softfloat_exceptionFlags) @@ -2424,7 +2439,10 @@ void r4000_base_device::cp1_set(unsigned const reg, u64 const data) m_fcr31 |= ((m_fcr31 & FCR31_CM) >> 10); } - m_f[reg] = data; + if (sizeof(T) == 4) + m_f[reg] = (m_f[reg] & ~0xffffffffULL) | data; + else + m_f[reg] = data; } void r4000_base_device::cp2_execute(u32 const op) |