summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips3.cpp')
-rw-r--r--src/devices/cpu/mips/mips3.cpp157
1 files changed, 83 insertions, 74 deletions
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp
index 20d82bd3725..c09088fd669 100644
--- a/src/devices/cpu/mips/mips3.cpp
+++ b/src/devices/cpu/mips/mips3.cpp
@@ -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 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 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 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)])
@@ -60,7 +67,6 @@
#define FDVALL_FR1 (*(UINT64 *)&m_core->cpr[1][FDREG])
#define ADDPC(x) m_nextpc = m_core->pc + ((x) << 2)
-#define ADDPCL(x,l) { m_nextpc = m_core->pc + ((x) << 2); m_core->r[l] = (INT32)(m_core->pc + 4); }
#define ABSPC(x) m_nextpc = (m_core->pc & 0xf0000000) | ((x) << 2)
#define ABSPCL(x,l) { m_nextpc = (m_core->pc & 0xf0000000) | ((x) << 2); m_core->r[l] = (INT32)(m_core->pc + 4); }
#define SETPC(x) m_nextpc = (x)
@@ -316,7 +322,7 @@ void mips3_device::check_irqs()
void mips3_device::device_start()
{
- m_isdrc = (mconfig().options().drc() && !mconfig().m_force_no_drc) ? true : false;
+ m_isdrc = allow_drc();
/* allocate the implementation-specific state from the full cache */
m_core = (internal_mips3_state *)m_cache.alloc_near(sizeof(internal_mips3_state));
@@ -1513,36 +1519,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 +1615,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 +1675,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 +1696,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 +1713,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 +1737,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 +1758,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 +1771,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 +1779,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 +1789,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 +1799,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 +1809,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 +1817,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 +1833,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 +1886,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 +1894,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 +1902,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 +1910,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 +1918,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 +1926,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 +2320,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 +2339,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 +2347,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 +2355,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 +2363,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 */
@@ -2541,10 +2550,10 @@ void mips3_device::handle_regimm(UINT32 op)
case 0x0b: /* TLTIU */ if (RSVAL64 >= UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0c: /* TEQI */ if (RSVAL64 == UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0e: /* TNEI */ if (RSVAL64 != UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
- case 0x10: /* BLTZAL */ if ((INT64)RSVAL64 < 0) ADDPCL(SIMMVAL,31); break;
- case 0x11: /* BGEZAL */ if ((INT64)RSVAL64 >= 0) ADDPCL(SIMMVAL,31); break;
- case 0x12: /* BLTZALL */ if ((INT64)RSVAL64 < 0) ADDPCL(SIMMVAL,31) else m_core->pc += 4; break;
- case 0x13: /* BGEZALL */ if ((INT64)RSVAL64 >= 0) ADDPCL(SIMMVAL,31) else m_core->pc += 4; break;
+ case 0x10: /* BLTZAL */ m_core->r[31] = (INT32)(m_core->pc + 4); if ((INT64)RSVAL64 < 0) ADDPC(SIMMVAL); break;
+ case 0x11: /* BGEZAL */ m_core->r[31] = (INT32)(m_core->pc + 4); if ((INT64)RSVAL64 >= 0) ADDPC(SIMMVAL); break;
+ case 0x12: /* BLTZALL */ m_core->r[31] = (INT32)(m_core->pc + 4); if ((INT64)RSVAL64 < 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
+ case 0x13: /* BGEZALL */ m_core->r[31] = (INT32)(m_core->pc + 4); if ((INT64)RSVAL64 >= 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
default: /* ??? */ invalid_instruction(op); break;
}
}