mirror of
https://github.com/holub/mame
synced 2025-04-21 16:01:56 +03:00
New working machines
-------------------- Indy (R5000, 150MHz) [Ryan Holtz] -r4000: Improved R5000 support; FCR31 now supports 8 condition flags, added MOVF/MOVT support, fixed MOVZ/MOVN ops. [Ryan Holtz]
This commit is contained in:
parent
b42e446ac5
commit
1955f0b999
@ -86,6 +86,9 @@ DEFINE_DEVICE_TYPE(R4400, r4400_device, "r4400", "MIPS R4400")
|
||||
DEFINE_DEVICE_TYPE(R4600, r4600_device, "r4600", "QED R4600")
|
||||
DEFINE_DEVICE_TYPE(R5000, r5000_device, "r5000", "MIPS R5000")
|
||||
|
||||
u32 const r5000_device::s_fcc_masks[8] = { (1U << 23), (1U << 25), (1U << 26), (1U << 27), (1U << 28), (1U << 29), (1U << 30), (1U << 31) };
|
||||
u32 const r5000_device::s_fcc_shifts[8] = { 23, 25, 26, 27, 28, 29, 30, 31 };
|
||||
|
||||
r4000_base_device::r4000_base_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 prid, u32 fcr, cache_size icache_size, cache_size dcache_size)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_program_config_le("program", ENDIANNESS_LITTLE, 64, 32)
|
||||
@ -732,7 +735,7 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
// * Operation codes marked with an asterisk cause reserved
|
||||
// instruction exceptions in all current implementations and are
|
||||
// reserved for future versions of the architecture.
|
||||
cpu_exception(EXCEPTION_RI);
|
||||
handle_reserved_instruction(op);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -1044,7 +1047,6 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
case 0x32: // LWC2
|
||||
cp2_execute(op);
|
||||
break;
|
||||
// case 0x33: *
|
||||
case 0x34: // LLD
|
||||
load_linked<u64>(ADDR(m_r[RSREG], s16(op)),
|
||||
[this, op](u64 address, u64 data)
|
||||
@ -1114,14 +1116,14 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
// * Operation codes marked with an asterisk cause reserved instruction
|
||||
// exceptions in all current implementations and are reserved for future
|
||||
// versions of the architecture.
|
||||
cpu_exception(EXCEPTION_RI);
|
||||
handle_reserved_instruction(op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void r4000_base_device::handle_reserved_instruction(u32 const op)
|
||||
{
|
||||
// Unahdnled operation codes cause reserved instruction
|
||||
// Unhandled operation codes cause reserved instruction
|
||||
// exceptions in all current implementations and are
|
||||
// reserved for future versions of the architecture.
|
||||
cpu_exception(EXCEPTION_RI);
|
||||
@ -1129,21 +1131,33 @@ void r4000_base_device::handle_reserved_instruction(u32 const op)
|
||||
|
||||
void r5000_device::handle_reserved_instruction(u32 const op)
|
||||
{
|
||||
switch (op & 0x3f)
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 0x33: // PREF (effective no-op)
|
||||
break;
|
||||
default:
|
||||
switch (op >> 26)
|
||||
case 0x00: // SPECIAL
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
case 0x0a: // MOVN
|
||||
case 0x01: // MOVT / MOVF
|
||||
if (((m_fcr31 >> s_fcc_shifts[(op >> 18) & 7]) & 1) == ((op >> 16) & 1))
|
||||
{
|
||||
if (RDREG)
|
||||
{
|
||||
m_r[RDREG] = m_r[RSREG];
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x0a: // MOVZ
|
||||
if (m_r[RTREG] == 0) { if (RDREG) m_r[RDREG] = m_r[RSREG]; }
|
||||
break;
|
||||
case 0x0b: // MOVZ
|
||||
return;
|
||||
case 0x0b: // MOVN
|
||||
if (m_r[RTREG] != 0) { if (RDREG) m_r[RDREG] = m_r[RSREG]; }
|
||||
break;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x33: // PREF (effective no-op)
|
||||
return;
|
||||
}
|
||||
|
||||
r4000_base_device::handle_reserved_instruction(op);
|
||||
}
|
||||
|
||||
void r4000_base_device::cpu_exception(u32 exception, u16 const vector)
|
||||
@ -1631,6 +1645,485 @@ template <> bool r4000_base_device::cp1_op<float64_t>(float64_t op)
|
||||
return true;
|
||||
}
|
||||
|
||||
void r5000_device::cp1_execute(u32 const op)
|
||||
{
|
||||
if (!(SR & SR_CU1))
|
||||
{
|
||||
cpu_exception(EXCEPTION_CP1);
|
||||
return;
|
||||
}
|
||||
|
||||
softfloat_exceptionFlags = 0;
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 0x11: // COP1
|
||||
switch ((op >> 21) & 0x1f)
|
||||
{
|
||||
case 0x10: // S
|
||||
{
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
case 0x11: // MOVF.S / MOVT.S
|
||||
if (((m_fcr31 >> s_fcc_shifts[(op >> 18) & 7]) & 1) == ((op >> 16) & 1))
|
||||
cp1_mov_s(op);
|
||||
return;
|
||||
case 0x12: // MOVZ.S
|
||||
if (m_r[RTREG] == 0)
|
||||
cp1_mov_s(op);
|
||||
return;
|
||||
case 0x13: // MOVN.S
|
||||
if (m_r[RTREG] != 0)
|
||||
cp1_mov_s(op);
|
||||
return;
|
||||
case 0x15: // RECIP.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float32_t const fs = float32_t{ u32(m_f[FSREG]) };
|
||||
|
||||
if (cp1_op(fs))
|
||||
{
|
||||
cp1_set(FDREG, f32_div(i32_to_f32(1), fs).v);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x16: // RSQRT.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float32_t const fs = float32_t{ u32(m_f[FSREG]) };
|
||||
|
||||
if (cp1_op(fs))
|
||||
{
|
||||
cp1_set(FDREG, f32_div(i32_to_f32(1), f32_sqrt(fs)).v);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x30: // C.F.S (false)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
return;
|
||||
case 0x31: // C.UN.S (unordered)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
// detect unordered
|
||||
f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) });
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x32: // C.EQ.S (equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x33: // C.UEQ.S (unordered equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x34: // C.OLT.S (less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x35: // C.ULT.S (unordered less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x36: // C.OLE.S (less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x37: // C.ULE.S (unordered less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x38: // C.SF.S (signalling false)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
// detect unordered
|
||||
f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) });
|
||||
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x39: // C.NGLE.S (not greater, less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
// detect unordered
|
||||
f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) });
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7] | FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x3a: // C.SEQ.S (signalling equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3b: // C.NGL.S (not greater or less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3c: // C.LT.S (less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3d: // C.NGE.S (not greater or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3e: // C.LE.S (less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3f: // C.NGT.S (not greater than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
case 0x11: // D
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
case 0x11: // MOVF.D / MOVT.D
|
||||
if (((m_fcr31 >> s_fcc_shifts[(op >> 18) & 7]) & 1) == ((op >> 16) & 1))
|
||||
cp1_mov_d(op);
|
||||
return;
|
||||
case 0x12: // MOVZ.D
|
||||
if (m_r[RTREG] == 0)
|
||||
cp1_mov_d(op);
|
||||
return;
|
||||
case 0x13: // MOVN.D
|
||||
if (m_r[RTREG] != 0)
|
||||
cp1_mov_d(op);
|
||||
return;
|
||||
case 0x15: // RECIP.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float64_t const fs = float64_t{ m_f[FSREG] };
|
||||
|
||||
if (cp1_op(fs))
|
||||
{
|
||||
cp1_set(FDREG, f64_div(i32_to_f64(1), fs).v);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x16: // RSQRT.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float64_t const fs = float64_t{ m_f[FSREG] };
|
||||
|
||||
if (cp1_op(fs))
|
||||
{
|
||||
cp1_set(FDREG, f64_div(i32_to_f64(1), f64_sqrt(fs)).v);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x30: // C.F.D (false)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
return;
|
||||
case 0x31: // C.UN.D (unordered)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
// detect unordered
|
||||
f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] });
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x32: // C.EQ.D (equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x33: // C.UEQ.D (unordered equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x34: // C.OLT.D (less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x35: // C.ULT.D (unordered less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x36: // C.OLE.D (less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x37: // C.ULE.D (unordered less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x38: // C.SF.D (signalling false)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
// detect unordered
|
||||
f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] });
|
||||
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x39: // C.NGLE.D (not greater, less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
// detect unordered
|
||||
f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] });
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7] | FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
}
|
||||
return;
|
||||
case 0x3a: // C.SEQ.D (signalling equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3b: // C.NGL.D (not greater or less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3c: // C.LT.D (less than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3d: // C.NGE.D (not greater or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3e: // C.LE.D (less than or equal)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case 0x3f: // C.NGT.D (not greater than)
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
|
||||
m_fcr31 |= s_fcc_masks[(op >> 18) & 7];
|
||||
else
|
||||
m_fcr31 &= ~s_fcc_masks[(op >> 18) & 7];
|
||||
|
||||
if (softfloat_exceptionFlags & softfloat_flag_invalid)
|
||||
{
|
||||
m_fcr31 |= FCR31_CV;
|
||||
cpu_exception(EXCEPTION_FPE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
r4000_base_device::cp1_execute(op);
|
||||
}
|
||||
|
||||
void r4000_base_device::cp1_execute(u32 const op)
|
||||
{
|
||||
if (!(SR & SR_CU1))
|
||||
@ -1832,23 +2325,7 @@ void r4000_base_device::cp1_execute(u32 const op)
|
||||
}
|
||||
break;
|
||||
case 0x06: // MOV.S
|
||||
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]);
|
||||
cp1_mov_s(op);
|
||||
break;
|
||||
case 0x07: // NEG.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
@ -2228,8 +2705,7 @@ void r4000_base_device::cp1_execute(u32 const op)
|
||||
}
|
||||
break;
|
||||
case 0x06: // MOV.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
m_f[FDREG] = m_f[FSREG];
|
||||
cp1_mov_d(op);
|
||||
break;
|
||||
case 0x07: // NEG.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
@ -2628,6 +3104,33 @@ void r4000_base_device::cp1_execute(u32 const op)
|
||||
}
|
||||
}
|
||||
|
||||
void r4000_base_device::cp1_mov_s(u32 const op)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
|
||||
void r4000_base_device::cp1_mov_d(u32 const op)
|
||||
{
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
m_f[FDREG] = m_f[FSREG];
|
||||
}
|
||||
|
||||
void r4000_base_device::cp1x_execute(u32 const op)
|
||||
{
|
||||
if (!(SR & SR_CU1))
|
||||
|
@ -356,9 +356,11 @@ protected:
|
||||
// cp1 implementation
|
||||
void cp1_unimplemented();
|
||||
template <typename T> bool cp1_op(T op);
|
||||
void cp1_execute(u32 const op);
|
||||
virtual void cp1_execute(u32 const op);
|
||||
virtual void cp1x_execute(u32 const op);
|
||||
template <typename T> void cp1_set(unsigned const reg, T const data);
|
||||
void cp1_mov_s(u32 const op);
|
||||
void cp1_mov_d(u32 const op);
|
||||
|
||||
// cp2 implementation
|
||||
void cp2_execute(u32 const op);
|
||||
@ -486,6 +488,10 @@ public:
|
||||
|
||||
private:
|
||||
virtual void handle_reserved_instruction(u32 const op) override;
|
||||
virtual void cp1_execute(u32 const op) override;
|
||||
virtual void cp1x_execute(u32 const op) override;
|
||||
|
||||
static u32 const s_fcc_masks[8];
|
||||
static u32 const s_fcc_shifts[8];
|
||||
};
|
||||
#endif // MAME_CPU_MIPS_R4000_H
|
||||
|
@ -539,5 +539,5 @@ ROM_END
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1993, indy_4610, 0, 0, indy_4610, ip24, ip24_state, empty_init, "Silicon Graphics Inc", "Indy (R4600, 100MHz)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NODEVICE_LAN | MACHINE_NODEVICE_MICROPHONE )
|
||||
COMP( 1993, indy_4613, indy_4610, 0, indy_4613, ip24, ip24_state, empty_init, "Silicon Graphics Inc", "Indy (R4600, 133MHz)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NODEVICE_LAN | MACHINE_NODEVICE_MICROPHONE )
|
||||
COMP( 1996, indy_5015, indy_4610, 0, indy_5015, ip24, ip24_state, empty_init, "Silicon Graphics Inc", "Indy (R5000, 150MHz)", MACHINE_NOT_WORKING )
|
||||
COMP( 1996, indy_5015, indy_4610, 0, indy_5015, ip24, ip24_state, empty_init, "Silicon Graphics Inc", "Indy (R5000, 150MHz)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NODEVICE_LAN | MACHINE_NODEVICE_MICROPHONE )
|
||||
COMP( 1993, indigo2_4415, 0, 0, indigo2_4415, ip24, ip22_state, empty_init, "Silicon Graphics Inc", "Indigo2 (R4400, 150MHz)", MACHINE_NOT_WORKING )
|
||||
|
Loading…
Reference in New Issue
Block a user