summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/r4000.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/r4000.cpp')
-rw-r--r--src/devices/cpu/mips/r4000.cpp32
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)