Merge pull request #2101 from Happy-yappH/master

mips3:  Retry fixing FPU register aliasing
This commit is contained in:
R. Belmont 2017-02-26 22:36:21 -05:00 committed by GitHub
commit 94bbcc889b
3 changed files with 182 additions and 856 deletions

View File

@ -28,26 +28,19 @@
#define RTVAL64 (m_core->r[RTREG])
#define RDVAL64 (m_core->r[RDREG])
#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_t *)&m_core->cpr[1][FSREG])[BYTE_XOR_LE(0)])
#define FDVALW_FR0 (((uint32_t *)&m_core->cpr[1][FDREG])[BYTE_XOR_LE(0)])
#define FRVALS_FR0 (((float *)&m_core->cpr[1][FRREG & 0x1E])[BYTE_XOR_LE(FRREG & 1)])
#define FTVALS_FR0 (((float *)&m_core->cpr[1][FTREG & 0x1E])[BYTE_XOR_LE(FTREG & 1)])
#define FSVALS_FR0 (((float *)&m_core->cpr[1][FSREG & 0x1E])[BYTE_XOR_LE(FSREG & 1)])
#define FDVALS_FR0 (((float *)&m_core->cpr[1][FDREG & 0x1E])[BYTE_XOR_LE(FDREG & 1)])
#define FSVALW_FR0 (((uint32_t *)&m_core->cpr[1][FSREG & 0x1E])[BYTE_XOR_LE(FSREG & 1)])
#define FDVALW_FR0 (((uint32_t *)&m_core->cpr[1][FDREG & 0x1E])[BYTE_XOR_LE(FDREG & 1)])
#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 FRVALD_FR0 (*(double *)&m_core->cpr[1][FRREG & 0x1E])
#define FTVALD_FR0 (*(double *)&m_core->cpr[1][FTREG & 0x1E])
#define FSVALD_FR0 (*(double *)&m_core->cpr[1][FSREG & 0x1E])
#define FDVALD_FR0 (*(double *)&m_core->cpr[1][FDREG & 0x1E])
#define FSVALL_FR0 (*(uint64_t *)&m_core->cpr[1][FSREG & 0x1E])
#define FDVALL_FR0 (*(uint64_t *)&m_core->cpr[1][FDREG & 0x1E])
#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)])
@ -1516,35 +1509,34 @@ void mips3_device::handle_cop0(uint32_t op)
inline uint32_t mips3_device::get_cop1_reg32(int idx)
{
return m_core->cpr[1][idx];
if (IS_FR0)
return ((uint32_t *)&m_core->cpr[1][idx & 0x1E])[idx & 1];
else
return m_core->cpr[1][idx];
}
inline uint64_t mips3_device::get_cop1_reg64(int idx)
{
if (IS_FR0)
return (uint64_t(((uint32_t *)&m_core->cpr[1][(idx&0x1E) + 1])[BYTE_XOR_LE(0)])) << 32
| (uint64_t(((uint32_t *)&m_core->cpr[1][idx&0x1E])[BYTE_XOR_LE(0)]));
else
return m_core->cpr[1][idx];
idx &= 0x1E;
return m_core->cpr[1][idx];
}
inline void mips3_device::set_cop1_reg32(int idx, uint32_t val)
{
m_core->cpr[1][idx] = val;
if (IS_FR0)
((uint32_t *)&m_core->cpr[1][idx & 0x1E])[idx & 1] = val;
else
m_core->cpr[1][idx] = val;
}
inline void mips3_device::set_cop1_reg64(int idx, uint64_t val)
{
if (IS_FR0)
{
((uint32_t *)&m_core->cpr[1][idx&0x1E])[BYTE_XOR_LE(0)] = val & 0xFFFFFFFF;
((uint32_t *)&m_core->cpr[1][(idx&0x1E) + 1])[BYTE_XOR_LE(0)] = val >> 32;
}
else
{
m_core->cpr[1][idx] = val;
}
idx &= 0x1E;
m_core->cpr[1][idx] = val;
}
inline uint64_t mips3_device::get_cop1_creg(int idx)
{
if (idx == 31)
@ -1609,56 +1601,56 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* ADD.S */
FDVALS_FR0 = FSVALS_FR0 + FTVALS_FR0;
else /* ADD.D */
SFDVALD_FR0(LFSVALD_FR0 + LFTVALD_FR0);
FDVALD_FR0 = FSVALD_FR0 + FTVALD_FR0;
break;
case 0x01:
if (IS_SINGLE(op)) /* SUB.S */
FDVALS_FR0 = FSVALS_FR0 - FTVALS_FR0;
else /* SUB.D */
SFDVALD_FR0(LFSVALD_FR0 - LFTVALD_FR0);
FDVALD_FR0 = FSVALD_FR0 - FTVALD_FR0;
break;
case 0x02:
if (IS_SINGLE(op)) /* MUL.S */
FDVALS_FR0 = FSVALS_FR0 * FTVALS_FR0;
else /* MUL.D */
SFDVALD_FR0(LFSVALD_FR0 * LFTVALD_FR0);
FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0;
break;
case 0x03:
if (IS_SINGLE(op)) /* DIV.S */
FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0;
else /* DIV.D */
SFDVALD_FR0(LFSVALD_FR0 / LFTVALD_FR0);
FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0;
break;
case 0x04:
if (IS_SINGLE(op)) /* SQRT.S */
FDVALS_FR0 = sqrt(FSVALS_FR0);
else /* SQRT.D */
SFDVALD_FR0(sqrt(LFSVALD_FR0));
FDVALD_FR0 = sqrt(FSVALD_FR0);
break;
case 0x05:
if (IS_SINGLE(op)) /* ABS.S */
FDVALS_FR0 = fabs(FSVALS_FR0);
else /* ABS.D */
SFDVALD_FR0(fabs(LFSVALD_FR0));
FDVALD_FR0 = fabs(FSVALD_FR0);
break;
case 0x06:
if (IS_SINGLE(op)) /* MOV.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOV.D */
SFDVALD_FR0(LFSVALD_FR0);
FDVALD_FR0 = FSVALD_FR0;
break;
case 0x07:
if (IS_SINGLE(op)) /* NEG.S */
FDVALS_FR0 = -FSVALS_FR0;
else /* NEG.D */
SFDVALD_FR0(-LFSVALD_FR0);
FDVALD_FR0 = -FSVALD_FR0;
break;
case 0x08:
@ -1669,16 +1661,16 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
temp = ceil(temp - 0.5);
else
temp = floor(temp + 0.5);
SFDVALL_FR0((int64_t)temp);
FDVALL_FR0 = (int64_t)temp;
}
else /* ROUND.L.D */
{
double temp = LFSVALD_FR0;
double temp = FSVALD_FR0;
if (temp < 0)
temp = ceil(temp - 0.5);
else
temp = floor(temp + 0.5);
SFDVALL_FR0((int64_t)temp);
FDVALL_FR0 = (int64_t)temp;
}
break;
@ -1690,16 +1682,16 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
temp = ceil(temp);
else
temp = floor(temp);
SFDVALL_FR0((int64_t)temp);
FDVALL_FR0 = (int64_t)temp;
}
else /* TRUNC.L.D */
{
double temp = LFSVALD_FR0;
double temp = FSVALD_FR0;
if (temp < 0)
temp = ceil(temp);
else
temp = floor(temp);
SFDVALL_FR0((int64_t)temp);
FDVALL_FR0 = (int64_t)temp;
}
break;
@ -1707,16 +1699,16 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* CEIL.L.S */
dtemp = ceil(FSVALS_FR0);
else /* CEIL.L.D */
dtemp = ceil(LFSVALD_FR0);
SFDVALL_FR0((int64_t)dtemp);
dtemp = ceil(FSVALD_FR0);
FDVALL_FR0 = (int64_t)dtemp;
break;
case 0x0b:
if (IS_SINGLE(op)) /* FLOOR.L.S */
dtemp = floor(FSVALS_FR0);
else /* FLOOR.L.D */
dtemp = floor(LFSVALD_FR0);
SFDVALL_FR0((int64_t)dtemp);
dtemp = floor(FSVALD_FR0);
FDVALL_FR0 = (int64_t)dtemp;
break;
case 0x0c:
@ -1731,7 +1723,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
}
else /* ROUND.W.D */
{
dtemp = LFSVALD_FR0;
dtemp = FSVALD_FR0;
if (dtemp < 0)
dtemp = ceil(dtemp - 0.5);
else
@ -1752,7 +1744,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
}
else /* TRUNC.W.D */
{
dtemp = LFSVALD_FR0;
dtemp = FSVALD_FR0;
if (dtemp < 0)
dtemp = ceil(dtemp);
else
@ -1765,7 +1757,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* CEIL.W.S */
dtemp = ceil(FSVALS_FR0);
else /* CEIL.W.D */
dtemp = ceil(LFSVALD_FR0);
dtemp = ceil(FSVALD_FR0);
FDVALW_FR0 = (int32_t)dtemp;
break;
@ -1773,7 +1765,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* FLOOR.W.S */
dtemp = floor(FSVALS_FR0);
else /* FLOOR.W.D */
dtemp = floor(LFSVALD_FR0);
dtemp = floor(FSVALD_FR0);
FDVALW_FR0 = (int32_t)dtemp;
break;
@ -1783,7 +1775,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* MOVT/F.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOVT/F.D */
SFDVALD_FR0(LFSVALD_FR0);
FDVALD_FR0 = FSVALD_FR0;
}
break;
@ -1793,7 +1785,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* MOVZ.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOVZ.D */
SFDVALD_FR0(LFSVALD_FR0);
FDVALD_FR0 = FSVALD_FR0;
}
break;
@ -1803,7 +1795,7 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* MOVN.S */
FDVALS_FR0 = FSVALS_FR0;
else /* MOVN.D */
SFDVALD_FR0(LFSVALD_FR0);
FDVALD_FR0 = FSVALD_FR0;
}
break;
@ -1811,14 +1803,14 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* RECIP.S */
FDVALS_FR0 = 1.0f / FSVALS_FR0;
else /* RECIP.D */
SFDVALD_FR0(1.0 / LFSVALD_FR0);
FDVALD_FR0 = 1.0 / FSVALD_FR0;
break;
case 0x16: /* R5000 */
if (IS_SINGLE(op)) /* RSQRT.S */
FDVALS_FR0 = 1.0f / sqrt(FSVALS_FR0);
else /* RSQRT.D */
SFDVALD_FR0(1.0 / sqrt(LFSVALD_FR0));
FDVALD_FR0 = 1.0 / sqrt(FSVALD_FR0);
break;
case 0x20:
@ -1827,36 +1819,36 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
if (IS_SINGLE(op)) /* CVT.S.W */
FDVALS_FR0 = (int32_t)FSVALW_FR0;
else /* CVT.S.L */
FDVALS_FR0 = (int64_t)LFSVALL_FR0;
FDVALS_FR0 = (int64_t)FSVALL_FR0;
}
else /* CVT.S.D */
FDVALS_FR0 = LFSVALD_FR0;
FDVALS_FR0 = FSVALD_FR0;
break;
case 0x21:
if (IS_INTEGRAL(op))
{
if (IS_SINGLE(op)) /* CVT.D.W */
SFDVALD_FR0((int32_t)FSVALW_FR0);
FDVALD_FR0 = (int32_t)FSVALW_FR0;
else /* CVT.D.L */
SFDVALD_FR0((int64_t)LFSVALL_FR0);
FDVALD_FR0 = (int64_t)FSVALL_FR0;
}
else /* CVT.D.S */
SFDVALD_FR0(FSVALS_FR0);
FDVALD_FR0 = FSVALS_FR0;
break;
case 0x24:
if (IS_SINGLE(op)) /* CVT.W.S */
FDVALW_FR0 = (int32_t)FSVALS_FR0;
else
FDVALW_FR0 = (int32_t)LFSVALD_FR0;
FDVALW_FR0 = (int32_t)FSVALD_FR0;
break;
case 0x25:
if (IS_SINGLE(op)) /* CVT.L.S */
SFDVALL_FR0((int64_t)FSVALS_FR0);
FDVALL_FR0 = (int64_t)FSVALS_FR0;
else /* CVT.L.D */
SFDVALL_FR0((int64_t)LFSVALD_FR0);
FDVALL_FR0 = (int64_t)FSVALD_FR0;
break;
case 0x30:
@ -1880,7 +1872,7 @@ void mips3_device::handle_cop1_fr0(uint32_t 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, (LFSVALD_FR0 == LFTVALD_FR0));
SET_FCC((op >> 8) & 7, (FSVALD_FR0 == FTVALD_FR0));
break;
case 0x33:
@ -1888,7 +1880,7 @@ void mips3_device::handle_cop1_fr0(uint32_t 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, (LFSVALD_FR0 == LFTVALD_FR0));
SET_FCC((op >> 8) & 7, (FSVALD_FR0 == FTVALD_FR0));
break;
case 0x34:
@ -1896,7 +1888,7 @@ void mips3_device::handle_cop1_fr0(uint32_t 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, (LFSVALD_FR0 < LFTVALD_FR0));
SET_FCC((op >> 8) & 7, (FSVALD_FR0 < FTVALD_FR0));
break;
case 0x35:
@ -1904,7 +1896,7 @@ void mips3_device::handle_cop1_fr0(uint32_t 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, (LFSVALD_FR0 < LFTVALD_FR0));
SET_FCC((op >> 8) & 7, (FSVALD_FR0 < FTVALD_FR0));
break;
case 0x36:
@ -1912,7 +1904,7 @@ void mips3_device::handle_cop1_fr0(uint32_t 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, (LFSVALD_FR0 <= LFTVALD_FR0));
SET_FCC((op >> 8) & 7, (FSVALD_FR0 <= FTVALD_FR0));
break;
case 0x37:
@ -1920,7 +1912,7 @@ void mips3_device::handle_cop1_fr0(uint32_t 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, (LFSVALD_FR0 <= LFTVALD_FR0));
SET_FCC((op >> 8) & 7, (FSVALD_FR0 <= FTVALD_FR0));
break;
default:
@ -2316,7 +2308,7 @@ void mips3_device::handle_cop1x_fr0(uint32_t op)
break;
case 0x01: /* LDXC1 */
if (RDOUBLE(RSVAL32 + RTVAL32, &temp64)) SFDVALL_FR0(temp64);
if (RDOUBLE(RSVAL32 + RTVAL32, &temp64)) FDVALL_FR0 = temp64;
break;
case 0x08: /* SWXC1 */
@ -2335,7 +2327,7 @@ void mips3_device::handle_cop1x_fr0(uint32_t op)
break;
case 0x21: /* MADD.D */
SFDVALD_FR0(LFSVALD_FR0 * LFTVALD_FR0 + LFRVALD_FR0);
FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0 + FRVALD_FR0;
break;
case 0x28: /* MSUB.S */
@ -2343,7 +2335,7 @@ void mips3_device::handle_cop1x_fr0(uint32_t op)
break;
case 0x29: /* MSUB.D */
SFDVALD_FR0(LFSVALD_FR0 * LFTVALD_FR0 - LFRVALD_FR0);
FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0 - FRVALD_FR0;
break;
case 0x30: /* NMADD.S */
@ -2351,7 +2343,7 @@ void mips3_device::handle_cop1x_fr0(uint32_t op)
break;
case 0x31: /* NMADD.D */
SFDVALD_FR0(-(LFSVALD_FR0 * LFTVALD_FR0 + LFRVALD_FR0));
FDVALD_FR0 = -(FSVALD_FR0 * FTVALD_FR0 + FRVALD_FR0);
break;
case 0x38: /* NMSUB.S */
@ -2359,7 +2351,7 @@ void mips3_device::handle_cop1x_fr0(uint32_t op)
break;
case 0x39: /* NMSUB.D */
SFDVALD_FR0(-(LFSVALD_FR0 * LFTVALD_FR0 - LFRVALD_FR0));
FDVALD_FR0 = -(FSVALD_FR0 * FTVALD_FR0 - FRVALD_FR0);
break;
case 0x24: /* MADD.W */

View File

@ -557,14 +557,8 @@ private:
bool generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint8_t reg);
bool generate_get_cop0_reg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint8_t reg);
bool generate_cop0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
bool generate_cop1_fr0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
bool generate_cop1_fr1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_get_cop1_reg64(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, const uint32_t reg, const uml::parameter& param);
void generate_get_cop1_reg64_d2i(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, const uint32_t reg, const uml::parameter& param);
void generate_set_cop1_reg64(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, const uint32_t reg, const uml::parameter& param);
void generate_set_cop1_reg64_i2d(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, const uint32_t reg, const uml::parameter& param);
bool generate_cop1x_fr0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
bool generate_cop1x_fr1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
bool generate_cop1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
bool generate_cop1x(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void check_cop0_access(drcuml_block *block);
void check_cop1_access(drcuml_block *block);

File diff suppressed because it is too large Load Diff