diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index c09088fd669..59cdc9e5812 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -6,9 +6,6 @@ Core implementation for the portable MIPS III/IV emulator. Written by Aaron Giles - Still not implemented: - * DMULT needs to be fixed properly - ***************************************************************************/ #include "emu.h" @@ -2617,17 +2614,33 @@ void mips3_device::handle_special(UINT32 op) break; case 0x1c: /* DMULT */ { - UINT64 temp64 = (INT64)RSVAL64 * (INT64)RTVAL64; - LOVAL64 = temp64; - HIVAL64 = (INT64)temp64 >> 63; + INT64 rshi = (INT32)(RSVAL64 >> 32); + INT64 rthi = (INT32)(RTVAL64 >> 32); + INT64 rslo = (UINT32)RSVAL64; + INT64 rtlo = (UINT32)RTVAL64; + INT64 mid_prods = (rshi * rtlo) + (rslo * rthi); + UINT64 lo_prod = (rslo * rtlo); + INT64 hi_prod = (rshi * rthi); + mid_prods += lo_prod >> 32; + + HIVAL64 = hi_prod + (mid_prods >> 32); + LOVAL64 = (UINT32)lo_prod + (mid_prods << 32); m_core->icount -= 7; break; } case 0x1d: /* DMULTU */ { - UINT64 temp64 = (UINT64)RSVAL64 * (UINT64)RTVAL64; - LOVAL64 = temp64; - HIVAL64 = 0; + UINT64 rshi = (INT32)(RSVAL64 >> 32); + UINT64 rthi = (INT32)(RTVAL64 >> 32); + UINT64 rslo = (UINT32)RSVAL64; + UINT64 rtlo = (UINT32)RTVAL64; + UINT64 mid_prods = (rshi * rtlo) + (rslo * rthi); + UINT64 lo_prod = (rslo * rtlo); + UINT64 hi_prod = (rshi * rthi); + mid_prods += lo_prod >> 32; + + HIVAL64 = hi_prod + (mid_prods >> 32); + LOVAL64 = (UINT32)lo_prod + (mid_prods << 32); m_core->icount -= 7; break; } diff --git a/src/devices/cpu/mips/mips3drc.cpp b/src/devices/cpu/mips/mips3drc.cpp index 9995cdb105f..d879bf7f26a 100644 --- a/src/devices/cpu/mips/mips3drc.cpp +++ b/src/devices/cpu/mips/mips3drc.cpp @@ -2062,11 +2062,77 @@ int mips3_device::generate_special(drcuml_block *block, compiler_state *compiler return TRUE; case 0x1c: /* DMULT - MIPS III */ - UML_DMULS(block, LO64, HI64, R64(RSREG), R64(RTREG)); // dmuls lo,hi,, + // I0: INT64 rshi = (INT32)(rs >> 32); + // I1: INT64 rthi = (INT32)(rt >> 32); + // I2: INT64 rslo = (UINT32)rs; + // I3: INT64 rtlo = (UINT32)rt; + + UML_DSHR(block, I0, R64(RSREG), 32); + UML_DSEXT(block, I0, I0, SIZE_DWORD); + UML_DSHR(block, I1, R64(RTREG), 32); + UML_DSEXT(block, I1, I1, SIZE_DWORD); + UML_DMOV(block, I2, R32(RSREG)); + UML_DMOV(block, I3, R32(RTREG)); + + // I4: INT64 mid_prods = (rshi * rtlo) + (rslo + rthi) + UML_DMULS(block, I4, I5, I0, I3); + UML_DMULS(block, I6, I7, I1, I2); + UML_DADD(block, I4, I4, I6); + + // I5: UINT64 lo_prod = rslo * rtlo; + UML_DMULU(block, I5, I6, I2, I3); + + // I6: INT64 hi_prod = rshi * rthi; + UML_DMULS(block, I6, I7, I0, I1); + + // mid_prods += lo_prod >> 32; + UML_DSHR(block, I7, I5, 32); + UML_DADD(block, I4, I4, I7); + + // hi = hi_prod + (mid_prods >> 32); + UML_DSHR(block, I7, I4, 32); + UML_DADD(block, HI64, I6, I7); + + // lo = (UINT32)lo_prod + (mid_prods << 32); + UML_DSHL(block, I4, I4, 32); + UML_DAND(block, I5, I5, 0x00000000ffffffffL); + UML_DADD(block, LO64, I4, I5); return TRUE; case 0x1d: /* DMULTU - MIPS III */ - UML_DMULU(block, LO64, HI64, R64(RSREG), R64(RTREG)); // dmulu lo,hi,, + // I0: UINT64 rshi = (INT32)(rs >> 32); + // I1: UINT64 rthi = (INT32)(rt >> 32); + // I2: UINT64 rslo = (UINT32)rs; + // I3: UINT64 rtlo = (UINT32)rt; + + UML_DSHR(block, I0, R64(RSREG), 32); + UML_DSHR(block, I1, R64(RTREG), 32); + UML_DMOV(block, I2, R32(RSREG)); + UML_DMOV(block, I3, R32(RTREG)); + + // I4: UINT64 mid_prods = (rshi * rtlo) + (rslo + rthi) + UML_DMULU(block, I4, I5, I0, I3); + UML_DMULU(block, I6, I7, I1, I2); + UML_DADD(block, I4, I4, I6); + + // I5: UINT64 lo_prod = rslo * rtlo; + UML_DMULU(block, I5, I6, I2, I3); + + // I6: UINT64 hi_prod = rshi * rthi; + UML_DMULU(block, I6, I7, I0, I1); + + // mid_prods += lo_prod >> 32; + UML_DSHR(block, I7, I5, 32); + UML_DADD(block, I4, I4, I7); + + // hi = hi_prod + (mid_prods >> 32); + UML_DSHR(block, I7, I4, 32); + UML_DADD(block, HI64, I6, I7); + + // lo = (UINT32)lo_prod + (mid_prods << 32); + UML_DSHL(block, I4, I4, 32); + UML_DAND(block, I5, I5, 0x00000000ffffffffL); + UML_DADD(block, LO64, I4, I5); return TRUE; case 0x1a: /* DIV - MIPS I */