From 1955f0b999762b2f6dec0372f6df1de9008d4fc9 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Thu, 5 Mar 2020 18:35:18 +0100 Subject: 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] --- src/devices/cpu/mips/r4000.cpp | 567 +++++++++++++++++++++++++++++++++++--- src/devices/cpu/mips/r4000.h | 8 +- src/mame/drivers/indy_indigo2.cpp | 2 +- 3 files changed, 543 insertions(+), 34 deletions(-) diff --git a/src/devices/cpu/mips/r4000.cpp b/src/devices/cpu/mips/r4000.cpp index dea5bbb9915..7b409dc0bab 100644 --- a/src/devices/cpu/mips/r4000.cpp +++ b/src/devices/cpu/mips/r4000.cpp @@ -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(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 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)) diff --git a/src/devices/cpu/mips/r4000.h b/src/devices/cpu/mips/r4000.h index ed4b5efa58b..2e4c0e177a7 100644 --- a/src/devices/cpu/mips/r4000.h +++ b/src/devices/cpu/mips/r4000.h @@ -356,9 +356,11 @@ protected: // cp1 implementation void cp1_unimplemented(); template 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 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 diff --git a/src/mame/drivers/indy_indigo2.cpp b/src/mame/drivers/indy_indigo2.cpp index 0cd4808684a..bf6da2eedac 100644 --- a/src/mame/drivers/indy_indigo2.cpp +++ b/src/mame/drivers/indy_indigo2.cpp @@ -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 ) -- cgit v1.2.3