Merge pull request #784 from Happy-yappH/master

mips3: Fix behavior for 32/64 bit mode floating point register aliasing.
This commit is contained in:
R. Belmont 2016-04-05 21:43:19 -04:00
commit d38702c846

View File

@ -31,19 +31,26 @@
#define RTVAL64 (m_core->r[RTREG])
#define RDVAL64 (m_core->r[RDREG])
#define FRVALS_FR0 (((float *)&m_core->cpr[1][0])[FRREG])
#define FTVALS_FR0 (((float *)&m_core->cpr[1][0])[FTREG])
#define FSVALS_FR0 (((float *)&m_core->cpr[1][0])[FSREG])
#define FDVALS_FR0 (((float *)&m_core->cpr[1][0])[FDREG])
#define FSVALW_FR0 (((UINT32 *)&m_core->cpr[1][0])[FSREG])
#define FDVALW_FR0 (((UINT32 *)&m_core->cpr[1][0])[FDREG])
#define FRVALS_FR0 (((float *)&m_core->cpr[1][FRREG])[BYTE_XOR_LE(0)])
#define FTVALS_FR0 (((float *)&m_core->cpr[1][FTREG])[BYTE_XOR_LE(0)])
#define FSVALS_FR0 (((float *)&m_core->cpr[1][FSREG])[BYTE_XOR_LE(0)])
#define FDVALS_FR0 (((float *)&m_core->cpr[1][FDREG])[BYTE_XOR_LE(0)])
#define FSVALW_FR0 (((UINT32 *)&m_core->cpr[1][FSREG])[BYTE_XOR_LE(0)])
#define FDVALW_FR0 (((UINT32 *)&m_core->cpr[1][FDREG])[BYTE_XOR_LE(0)])
#define FRVALD_FR0 (*(double *)&m_core->cpr[1][FRREG/2])
#define FTVALD_FR0 (*(double *)&m_core->cpr[1][FTREG/2])
#define FSVALD_FR0 (*(double *)&m_core->cpr[1][FSREG/2])
#define FDVALD_FR0 (*(double *)&m_core->cpr[1][FDREG/2])
#define FSVALL_FR0 (((UINT64 *)&m_core->cpr[1][0])[FSREG/2])
#define FDVALL_FR0 (((UINT64 *)&m_core->cpr[1][0])[FDREG/2])
#define LFRVALD_FR0 (u2d(get_cop1_reg64(FRREG)))
#define LFTVALD_FR0 (u2d(get_cop1_reg64(FTREG)))
#define LFSVALD_FR0 (u2d(get_cop1_reg64(FSREG)))
#define LFDVALD_FR0 (u2d(get_cop1_reg64(FDREG)))
#define LFSVALL_FR0 (get_cop1_reg64(FSREG))
#define LFDVALL_FR0 (get_cop1_reg64(FDREG))
#define SFRVALD_FR0(x) (set_cop1_reg64(FRREG,d2u((x))))
#define SFTVALD_FR0(x) (set_cop1_reg64(FTREG,d2u((x))))
#define SFSVALD_FR0(x) (set_cop1_reg64(FSREG,d2u((x))))
#define SFDVALD_FR0(x) (set_cop1_reg64(FDREG,d2u((x))))
#define SFSVALL_FR0(x) (set_cop1_reg64(FSREG,(x)))
#define SFDVALL_FR0(x) (set_cop1_reg64(FDREG,(x)))
#define FRVALS_FR1 (((float *)&m_core->cpr[1][FRREG])[BYTE_XOR_LE(0)])
#define FTVALS_FR1 (((float *)&m_core->cpr[1][FTREG])[BYTE_XOR_LE(0)])
@ -1513,36 +1520,39 @@ void mips3_device::handle_cop0(UINT32 op)
inline UINT32 mips3_device::get_cop1_reg32(int idx)
{
if (IS_FR0)
return ((UINT32 *)&m_core->cpr[1][0])[idx];
else
//if (IS_FR0)
// return ((UINT32 *)&m_core->cpr[1][0])[idx];
//else
return m_core->cpr[1][idx];
}
inline UINT64 mips3_device::get_cop1_reg64(int idx)
{
if (IS_FR0)
return ((UINT64 *)&m_core->cpr[1][0])[idx/2];
return (UINT64(((UINT32 *)&m_core->cpr[1][(idx&0x1E) + 1])[BYTE_XOR_LE(0)])) << 32
| (UINT64(((UINT32 *)&m_core->cpr[1][idx&0x1E])[BYTE_XOR_LE(0)]));
else
return m_core->cpr[1][idx];
}
inline void mips3_device::set_cop1_reg32(int idx, UINT32 val)
{
if (IS_FR0)
((UINT32 *)&m_core->cpr[1][0])[idx] = val;
else
//if (IS_FR0)
// ((UINT32 *)&m_core->cpr[1][0])[idx] = val;
//else
m_core->cpr[1][idx] = val;
}
inline void mips3_device::set_cop1_reg64(int idx, UINT64 val)
{
if (IS_FR0)
((UINT64 *)&m_core->cpr[1][0])[idx/2] = val;
{
((UINT32 *)&m_core->cpr[1][idx&0x1E])[BYTE_XOR_LE(0)] = val & 0xFFFFFFFF;
((UINT32 *)&m_core->cpr[1][(idx&0x1E) + 1])[BYTE_XOR_LE(0)] = val >> 32;
}
else
m_core->cpr[1][idx] = val;
}
inline UINT64 mips3_device::get_cop1_creg(int idx)
{
if (idx == 31)
@ -1606,56 +1616,56 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* ADD.S */
FDVALS_FR0 = FSVALS_FR0 + FTVALS_FR0;
else /* ADD.D */
FDVALD_FR0 = FSVALD_FR0 + FTVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0 + LFTVALD_FR0);
break;
case 0x01:
if (IS_SINGLE(op)) /* SUB.S */
FDVALS_FR0 = FSVALS_FR0 - FTVALS_FR0;
else /* SUB.D */
FDVALD_FR0 = FSVALD_FR0 - FTVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0 - LFTVALD_FR0);
break;
case 0x02:
if (IS_SINGLE(op)) /* MUL.S */
FDVALS_FR0 = FSVALS_FR0 * FTVALS_FR0;
else /* MUL.D */
FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0 * LFTVALD_FR0);
break;
case 0x03:
if (IS_SINGLE(op)) /* DIV.S */
FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0;
else /* DIV.D */
FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0 / LFTVALD_FR0);
break;
case 0x04:
if (IS_SINGLE(op)) /* SQRT.S */
FDVALS_FR0 = sqrt(FSVALS_FR0);
else /* SQRT.D */
FDVALD_FR0 = sqrt(FSVALD_FR0);
SFDVALD_FR0(sqrt(LFSVALD_FR0));
break;
case 0x05:
if (IS_SINGLE(op)) /* ABS.S */
FDVALS_FR0 = fabs(FSVALS_FR0);
else /* ABS.D */
FDVALD_FR0 = fabs(FSVALD_FR0);
SFDVALD_FR0(fabs(LFSVALD_FR0));
break;
case 0x06:
if (IS_SINGLE(op)) /* MOV.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOV.D */
FDVALD_FR0 = FSVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0);
break;
case 0x07:
if (IS_SINGLE(op)) /* NEG.S */
FDVALS_FR0 = -FSVALS_FR0;
else /* NEG.D */
FDVALD_FR0 = -FSVALD_FR0;
SFDVALD_FR0(-LFSVALD_FR0);
break;
case 0x08:
@ -1666,16 +1676,16 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
temp = ceil(temp - 0.5);
else
temp = floor(temp + 0.5);
FDVALL_FR0 = (INT64)temp;
SFDVALL_FR0((INT64)temp);
}
else /* ROUND.L.D */
{
double temp = FSVALD_FR0;
double temp = LFSVALD_FR0;
if (temp < 0)
temp = ceil(temp - 0.5);
else
temp = floor(temp + 0.5);
FDVALL_FR0 = (INT64)temp;
SFDVALL_FR0((INT64)temp);
}
break;
@ -1687,16 +1697,16 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
temp = ceil(temp);
else
temp = floor(temp);
FDVALL_FR0 = (INT64)temp;
SFDVALL_FR0((INT64)temp);
}
else /* TRUNC.L.D */
{
double temp = FSVALD_FR0;
double temp = LFSVALD_FR0;
if (temp < 0)
temp = ceil(temp);
else
temp = floor(temp);
FDVALL_FR0 = (INT64)temp;
SFDVALL_FR0((INT64)temp);
}
break;
@ -1704,16 +1714,16 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* CEIL.L.S */
dtemp = ceil(FSVALS_FR0);
else /* CEIL.L.D */
dtemp = ceil(FSVALD_FR0);
FDVALL_FR0 = (INT64)dtemp;
dtemp = ceil(LFSVALD_FR0);
SFDVALL_FR0((INT64)dtemp);
break;
case 0x0b:
if (IS_SINGLE(op)) /* FLOOR.L.S */
dtemp = floor(FSVALS_FR0);
else /* FLOOR.L.D */
dtemp = floor(FSVALD_FR0);
FDVALL_FR0 = (INT64)dtemp;
dtemp = floor(LFSVALD_FR0);
SFDVALL_FR0((INT64)dtemp);
break;
case 0x0c:
@ -1728,7 +1738,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
}
else /* ROUND.W.D */
{
dtemp = FSVALD_FR0;
dtemp = LFSVALD_FR0;
if (dtemp < 0)
dtemp = ceil(dtemp - 0.5);
else
@ -1749,7 +1759,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
}
else /* TRUNC.W.D */
{
dtemp = FSVALD_FR0;
dtemp = LFSVALD_FR0;
if (dtemp < 0)
dtemp = ceil(dtemp);
else
@ -1762,7 +1772,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* CEIL.W.S */
dtemp = ceil(FSVALS_FR0);
else /* CEIL.W.D */
dtemp = ceil(FSVALD_FR0);
dtemp = ceil(LFSVALD_FR0);
FDVALW_FR0 = (INT32)dtemp;
break;
@ -1770,7 +1780,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* FLOOR.W.S */
dtemp = floor(FSVALS_FR0);
else /* FLOOR.W.D */
dtemp = floor(FSVALD_FR0);
dtemp = floor(LFSVALD_FR0);
FDVALW_FR0 = (INT32)dtemp;
break;
@ -1780,7 +1790,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* MOVT/F.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOVT/F.D */
FDVALD_FR0 = FSVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0);
}
break;
@ -1790,7 +1800,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* MOVZ.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOVZ.D */
FDVALD_FR0 = FSVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0);
}
break;
@ -1800,7 +1810,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* MOVN.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOVN.D */
FDVALD_FR0 = FSVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0);
}
break;
@ -1808,14 +1818,14 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* RECIP.S */
FDVALS_FR0 = 1.0f / FSVALS_FR0;
else /* RECIP.D */
FDVALD_FR0 = 1.0 / FSVALD_FR0;
SFDVALD_FR0(1.0 / LFSVALD_FR0);
break;
case 0x16: /* R5000 */
if (IS_SINGLE(op)) /* RSQRT.S */
FDVALS_FR0 = 1.0f / sqrt(FSVALS_FR0);
else /* RSQRT.D */
FDVALD_FR0 = 1.0 / sqrt(FSVALD_FR0);
SFDVALD_FR0(1.0 / sqrt(LFSVALD_FR0));
break;
case 0x20:
@ -1824,36 +1834,36 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* CVT.S.W */
FDVALS_FR0 = (INT32)FSVALW_FR0;
else /* CVT.S.L */
FDVALS_FR0 = (INT64)FSVALL_FR0;
FDVALS_FR0 = (INT64)LFSVALL_FR0;
}
else /* CVT.S.D */
FDVALS_FR0 = FSVALD_FR0;
FDVALS_FR0 = LFSVALD_FR0;
break;
case 0x21:
if (IS_INTEGRAL(op))
{
if (IS_SINGLE(op)) /* CVT.D.W */
FDVALD_FR0 = (INT32)FSVALW_FR0;
SFDVALD_FR0((INT32)FSVALW_FR0);
else /* CVT.D.L */
FDVALD_FR0 = (INT64)FSVALL_FR0;
SFDVALD_FR0((INT64)LFSVALL_FR0);
}
else /* CVT.D.S */
FDVALD_FR0 = FSVALS_FR0;
SFDVALD_FR0(FSVALS_FR0);
break;
case 0x24:
if (IS_SINGLE(op)) /* CVT.W.S */
FDVALW_FR0 = (INT32)FSVALS_FR0;
else
FDVALW_FR0 = (INT32)FSVALD_FR0;
FDVALW_FR0 = (INT32)LFSVALD_FR0;
break;
case 0x25:
if (IS_SINGLE(op)) /* CVT.L.S */
FDVALL_FR0 = (INT64)FSVALS_FR0;
SFDVALL_FR0((INT64)FSVALS_FR0);
else /* CVT.L.D */
FDVALL_FR0 = (INT64)FSVALD_FR0;
SFDVALL_FR0((INT64)LFSVALD_FR0);
break;
case 0x30:
@ -1877,7 +1887,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* C.EQ.S */
SET_FCC((op >> 8) & 7, (FSVALS_FR0 == FTVALS_FR0));
else /* C.EQ.D */
SET_FCC((op >> 8) & 7, (FSVALD_FR0 == FTVALD_FR0));
SET_FCC((op >> 8) & 7, (LFSVALD_FR0 == LFTVALD_FR0));
break;
case 0x33:
@ -1885,7 +1895,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* C.UEQ.S */
SET_FCC((op >> 8) & 7, (FSVALS_FR0 == FTVALS_FR0));
else /* C.UEQ.D */
SET_FCC((op >> 8) & 7, (FSVALD_FR0 == FTVALD_FR0));
SET_FCC((op >> 8) & 7, (LFSVALD_FR0 == LFTVALD_FR0));
break;
case 0x34:
@ -1893,7 +1903,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* C.OLT.S */
SET_FCC((op >> 8) & 7, (FSVALS_FR0 < FTVALS_FR0));
else /* C.OLT.D */
SET_FCC((op >> 8) & 7, (FSVALD_FR0 < FTVALD_FR0));
SET_FCC((op >> 8) & 7, (LFSVALD_FR0 < LFTVALD_FR0));
break;
case 0x35:
@ -1901,7 +1911,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* C.ULT.S */
SET_FCC((op >> 8) & 7, (FSVALS_FR0 < FTVALS_FR0));
else /* C.ULT.D */
SET_FCC((op >> 8) & 7, (FSVALD_FR0 < FTVALD_FR0));
SET_FCC((op >> 8) & 7, (LFSVALD_FR0 < LFTVALD_FR0));
break;
case 0x36:
@ -1909,7 +1919,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* C.OLE.S */
SET_FCC((op >> 8) & 7, (FSVALS_FR0 <= FTVALS_FR0));
else /* C.OLE.D */
SET_FCC((op >> 8) & 7, (FSVALD_FR0 <= FTVALD_FR0));
SET_FCC((op >> 8) & 7, (LFSVALD_FR0 <= LFTVALD_FR0));
break;
case 0x37:
@ -1917,7 +1927,7 @@ void mips3_device::handle_cop1_fr0(UINT32 op)
if (IS_SINGLE(op)) /* C.ULE.S */
SET_FCC((op >> 8) & 7, (FSVALS_FR0 <= FTVALS_FR0));
else /* C.ULE.D */
SET_FCC((op >> 8) & 7, (FSVALD_FR0 <= FTVALD_FR0));
SET_FCC((op >> 8) & 7, (LFSVALD_FR0 <= LFTVALD_FR0));
break;
default:
@ -2311,7 +2321,7 @@ void mips3_device::handle_cop1x_fr0(UINT32 op)
break;
case 0x01: /* LDXC1 */
if (RDOUBLE(RSVAL32 + RTVAL32, &temp64)) FDVALL_FR0 = temp64;
if (RDOUBLE(RSVAL32 + RTVAL32, &temp64)) SFDVALL_FR0(temp64);
break;
case 0x08: /* SWXC1 */
@ -2330,7 +2340,7 @@ void mips3_device::handle_cop1x_fr0(UINT32 op)
break;
case 0x21: /* MADD.D */
FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0 + FRVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0 * LFTVALD_FR0 + LFRVALD_FR0);
break;
case 0x28: /* MSUB.S */
@ -2338,7 +2348,7 @@ void mips3_device::handle_cop1x_fr0(UINT32 op)
break;
case 0x29: /* MSUB.D */
FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0 - FRVALD_FR0;
SFDVALD_FR0(LFSVALD_FR0 * LFTVALD_FR0 - LFRVALD_FR0);
break;
case 0x30: /* NMADD.S */
@ -2346,7 +2356,7 @@ void mips3_device::handle_cop1x_fr0(UINT32 op)
break;
case 0x31: /* NMADD.D */
FDVALD_FR0 = -(FSVALD_FR0 * FTVALD_FR0 + FRVALD_FR0);
SFDVALD_FR0(-(LFSVALD_FR0 * LFTVALD_FR0 + LFRVALD_FR0));
break;
case 0x38: /* NMSUB.S */
@ -2354,7 +2364,7 @@ void mips3_device::handle_cop1x_fr0(UINT32 op)
break;
case 0x39: /* NMSUB.D */
FDVALD_FR0 = -(FSVALD_FR0 * FTVALD_FR0 - FRVALD_FR0);
SFDVALD_FR0(-(LFSVALD_FR0 * LFTVALD_FR0 - LFRVALD_FR0));
break;
case 0x24: /* MADD.W */