-mips3: Fixed DMULT and DMULTU in both interpreter and DRC modes. [marathonman]

This commit is contained in:
therealmogminer@gmail.com 2016-04-12 19:13:55 +02:00
parent 6b9c7a920a
commit 207abac3ed
2 changed files with 90 additions and 11 deletions

View File

@ -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;
}

View File

@ -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,<rsreg>,<rtreg>
// 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,<rsreg>,<rtreg>
// 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 */