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.cpp411
1 files changed, 348 insertions, 63 deletions
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp
index 6550aa27d2f..b2a1e3b7fdf 100644
--- a/src/devices/cpu/mips/mips3.cpp
+++ b/src/devices/cpu/mips/mips3.cpp
@@ -283,7 +283,8 @@ void mips3_device::generate_exception(int exception, int backup)
/* most exceptions go to offset 0x180, except for TLB stuff */
if (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE)
{
- osd_printf_debug("TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]);
+ //printf("TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]);
+ //machine().debug_break();
}
else
{
@@ -313,7 +314,7 @@ void mips3_device::generate_tlb_exception(int exception, offs_t address)
void mips3_device::invalid_instruction(uint32_t op)
{
- printf("Invalid instruction! %08x\n", op);
+ fatalerror("Invalid instruction! %08x\n", op);
generate_exception(EXCEPTION_INVALIDOP, 1);
}
@@ -345,9 +346,6 @@ void mips3_device::device_start()
/* initialize based on the config */
memset(m_core, 0, sizeof(internal_mips3_state));
- m_core->vfr[0][3] = 1.0f;
- m_core->vfmem = &m_core->vumem[0];
- m_core->vimem = reinterpret_cast<uint32_t*>(m_core->vfmem);
m_cpu_clock = clock();
m_program = &space(AS_PROGRAM);
@@ -1072,6 +1070,13 @@ void mips3_device::device_reset()
m_core->mode = (MODE_KERNEL << 1) | 0;
m_cache_dirty = true;
m_interrupt_cycles = 0;
+
+ m_core->vfr[0][3] = 1.0f;
+ m_core->vfmem = &m_core->vumem[0];
+ m_core->vimem = reinterpret_cast<uint32_t*>(m_core->vfmem);
+ m_core->vr = &m_core->vcr[20];
+ m_core->i = reinterpret_cast<float*>(&m_core->vcr[21]);
+ m_core->q = reinterpret_cast<float*>(&m_core->vcr[22]);
}
@@ -2929,6 +2934,7 @@ void mips3_device::handle_extra_cop2(uint32_t op)
void r5900le_device::handle_extra_cop2(uint32_t op)
{
+ // TODO: Flags, rounding...
const int rd = (op >> 6) & 31;
const int rs = (op >> 11) & 31;
const int rt = (op >> 16) & 31;
@@ -2936,25 +2942,136 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
switch (op & 0x3f)
{
- case 0x00: case 0x01: case 0x02: case 0x03:
- printf("Unsupported instruction: VADDbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x04: case 0x05: case 0x06: case 0x07:
- printf("Unsupported instruction: VSUBbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- printf("Unsupported instruction: VMADDbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x00: case 0x01: case 0x02: case 0x03: /* VADDbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] + ft[bc];
+ }
+ }
+ }
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x07: /* VSUBbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] - ft[bc];
+ }
+ }
+ }
+ break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b: /* VMADDbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = m_core->vacc[field] + fs[field] + ft[bc];
+ }
+ }
+ }
+ break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
printf("Unsupported instruction: VMSUBbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x10: case 0x11: case 0x12: case 0x13:
- printf("Unsupported instruction: VMAXbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x14: case 0x15: case 0x16: case 0x17:
- printf("Unsupported instruction: VMINIbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x18: case 0x19: case 0x1a: case 0x1b:
- printf("Unsupported instruction: VMULbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x1c: printf("Unsupported instruction: VMULq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x10: case 0x11: case 0x12: case 0x13: /* VMAXbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = std::fmax(fs[field], ft[bc]);
+ }
+ }
+ }
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17: /* VMINIbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = std::fmin(fs[field], ft[bc]);
+ }
+ }
+ }
+ break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b: /* VMULbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] * ft[bc];
+ }
+ }
+ }
+ break;
+ case 0x1c: /* VMULq */
+ if (rd)
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] * ft[field];
+ }
+ }
+ }
+ break;
case 0x1d: printf("Unsupported instruction: VMAXi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1e: printf("Unsupported instruction: VMULi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1f: printf("Unsupported instruction: VMINIi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x20: printf("Unsupported instruction: VADDq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x20: /* VADDq */
+ if (rd)
+ {
+ float *fs = m_core->vfr[rs];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] + *(m_core->q);
+ }
+ }
+ }
+ break;
case 0x21: printf("Unsupported instruction: VMADDq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x22: printf("Unsupported instruction: VADDi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x23: printf("Unsupported instruction: VMADDi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
@@ -2962,26 +3079,67 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
case 0x25: printf("Unsupported instruction: VMSUBq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x26: printf("Unsupported instruction: VSUBi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x27: printf("Unsupported instruction: VMSUBi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x28: printf("Unsupported instruction: VADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x28: /* VADD */
+ if (rd)
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] + ft[field];
+ }
+ }
+ }
+ break;
case 0x29: printf("Unsupported instruction: VMADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x2a: printf("Unsupported instruction: VMUL @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x2a: /* VMUL */
+ if (rd)
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] * ft[field];
+ }
+ }
+ }
+ break;
case 0x2b: printf("Unsupported instruction: VMAX @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x2c:
+ case 0x2c: /* VSUB */
{
- float *fs = m_core->vfr[rs];
- float *ft = m_core->vfr[rt];
- float *fd = m_core->vfr[rt];
- for (int field = 0; field < 4; field++)
+ if (rd)
{
- if (BIT(op, 24-field))
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
{
- fd[field] = fs[field] - ft[field];
+ if (BIT(op, 24-field))
+ {
+ fd[field] = fs[field] - ft[field];
+ }
}
}
break;
}
case 0x2d: printf("Unsupported instruction: VMSUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x2e: printf("Unsupported instruction: VOPMSUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x2e: /* VOPMSUB */
+ if (rd)
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ fd[0] = m_core->vacc[0] - fs[1] * ft[2];
+ fd[1] = m_core->vacc[1] - fs[2] * ft[0];
+ fd[2] = m_core->vacc[2] - fs[0] * ft[1];
+ }
+ break;
case 0x2f: printf("Unsupported instruction: VMINI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x30:
if (rd)
@@ -3002,20 +3160,72 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
printf("Unsupported instruction: VADDAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x04: case 0x05: case 0x06: case 0x07:
printf("Unsupported instruction: VSUBAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- printf("Unsupported instruction: VMADDAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b: /* VMADDAbc */
+ if (rd)
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ float *fd = m_core->vfr[rd];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ fd[field] = m_core->vacc[field] + fs[field] * ft[bc];
+ }
+ }
+ }
+ break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
printf("Unsupported instruction: VMSUBAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x10: printf("Unsupported instruction: VITOF0 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x11: printf("Unsupported instruction: VITOF4 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x12: printf("Unsupported instruction: VITOF12 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x13: printf("Unsupported instruction: VITOF15 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x14: printf("Unsupported instruction: VFTOI0 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x15: printf("Unsupported instruction: VFTOI4 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x14: /* VFTOI0 */
+ if (rt)
+ {
+ float *fs = m_core->vfr[rs];
+ int32_t *ft = reinterpret_cast<int32_t*>(m_core->vfr[rt]);
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ ft[field] = (int32_t)(fs[field]);
+ }
+ }
+ }
+ break;
+ case 0x15: /* VFTOI4 */
+ if (rt)
+ {
+ float *fs = m_core->vfr[rs];
+ int32_t *ft = reinterpret_cast<int32_t*>(m_core->vfr[rt]);
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ ft[field] = (int32_t)(fs[field] * 16.0f);
+ }
+ }
+ }
+ break;
case 0x16: printf("Unsupported instruction: VFTOI12 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x17: printf("Unsupported instruction: VFTOI15 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x18: case 0x19: case 0x1a: case 0x1b:
- printf("Unsupported instruction: VMULAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b: /* VMULAbc */
+ {
+ const uint32_t bc = op & 3;
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ m_core->vacc[field] = fs[field] * ft[bc];
+ }
+ }
+ }
+ break;
case 0x1c: printf("Unsupported instruction: VMULAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1d: printf("Unsupported instruction: VABS @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x1e: printf("Unsupported instruction: VMULAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
@@ -3034,16 +3244,51 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
// 2b?
case 0x2c: printf("Unsupported instruction: VSUBA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x2d: printf("Unsupported instruction: VMSUBA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x2e: printf("Unsupported instruction: VOPMULA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x2f: printf("Unsupported instruction: VNOP @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x30: printf("Unsupported instruction: VMOVE @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x31: printf("Unsupported instruction: VMR32 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x2e: /* VOPMULA */
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ m_core->vacc[0] = fs[1] * ft[2];
+ m_core->vacc[1] = fs[2] * ft[0];
+ m_core->vacc[2] = fs[0] * ft[1];
+ }
+ break;
+ case 0x2f: /* VNOP */
+ break;
+ case 0x30: /* VMOVE */
+ if (rt)
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ ft[field] = fs[field];
+ }
+ }
+ }
+ break;
+ case 0x31: /* VMR32 */
+ if (rt)
+ {
+ float *fs = m_core->vfr[rs];
+ float *ft = m_core->vfr[rt];
+ for (int field = 0; field < 4; field++)
+ {
+ if (BIT(op, 24-field))
+ {
+ ft[field] = fs[(field + 3) & 3];
+ }
+ }
+ }
+ break;
// 32?
// 33?
case 0x34: printf("Unsupported instruction: VLQI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x35:
+ case 0x35: /* VSQI */
{
- uint32_t *base = &m_core->vimem[m_core->vcr[rt] << 2];
+ uint32_t *base = &m_core->vimem[(m_core->vcr[rt] << 2) & 0xfff];
uint32_t *fs = reinterpret_cast<uint32_t*>(m_core->vfr[rs]);
for (int field = 0; field < 4; field++)
{
@@ -3061,10 +3306,27 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
}
case 0x36: printf("Unsupported instruction: VLQD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x37: printf("Unsupported instruction: VSQD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x38: printf("Unsupported instruction: VDIV @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x39: printf("Unsupported instruction: VSQRT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x38: /* VDIV */
+ {
+ const uint32_t fsf = (op >> 21) & 3;
+ const uint32_t ftf = (op >> 23) & 3;
+ const float *fs = m_core->vfr[rs];
+ const float *ft = m_core->vfr[rt];
+ const float ftval = ft[ftf];
+ if (ftval)
+ *(m_core->q) = fs[fsf] / ft[ftf];
+ }
+ break;
+ case 0x39: /* VSQRT */
+ {
+ const uint32_t ftf = (op >> 23) & 3;
+ *(m_core->q) = (float)sqrt(m_core->vfr[rt][ftf]);
+ }
+ break;
case 0x3a: printf("Unsupported instruction: VRSQRT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
- case 0x3b: printf("Unsupported instruction: VWAITQ @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
+ case 0x3b: /* VWAITQ */
+ // TODO: We assume Q is instantly available. Fix this!
+ break;
case 0x3c: printf("Unsupported instruction: VMTIR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x3d: printf("Unsupported instruction: VMFIR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
case 0x3e: printf("Unsupported instruction: VILWR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
@@ -3076,7 +3338,7 @@ void r5900le_device::handle_extra_cop2(uint32_t op)
{
if (BIT(op, 24-field))
{
- m_core->vimem[base + field] = val;
+ m_core->vimem[(base + field) & 0xfff] = val;
}
}
break;
@@ -3408,8 +3670,15 @@ void r5900le_device::handle_idt(uint32_t op)
switch (op & 0x3f)
{
case 0x00: /* MADD */
- printf("Unsupported instruction: MADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
+ {
+ uint64_t temp64 = (int64_t)(int32_t)RSVAL32 * (int64_t)(int32_t)RTVAL32;
+ m_core->r[REG_LO] += (int32_t)temp64;
+ m_core->r[REG_HI] += (int32_t)(temp64 >> 32);
+ if (rd)
+ m_core->r[rd] = m_core->r[REG_LO];
+ m_core->icount -= 3; // ?
break;
+ }
case 0x01: /* MADDU */
printf("Unsupported instruction: MADDU @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
@@ -3537,7 +3806,18 @@ void r5900le_device::handle_mmi0(uint32_t op)
printf("Unsupported instruction: PADDW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
case 0x01: /* PSUBW */
- printf("Unsupported instruction: PSUBW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
+ if (rd)
+ {
+ const uint32_t rsval[4] = { (uint32_t)(m_core->rh[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->r[rs] };
+ const uint32_t rtval[4] = { (uint32_t)(m_core->rh[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->r[rt] };
+ uint32_t rdval[4] = { 0, 0, 0, 0 };
+ for (int word_idx = 0; word_idx < 4; word_idx++)
+ {
+ rdval[word_idx] = rsval[word_idx] - rtval[word_idx];
+ }
+ m_core->rh[rd] = ((uint64_t)rdval[0] << 32) | rdval[1];
+ m_core->r[rd] = ((uint64_t)rdval[2] << 32) | rdval[3];
+ }
break;
case 0x02: /* PCGTW */
printf("Unsupported instruction: PCGTW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
@@ -3673,27 +3953,32 @@ void r5900le_device::handle_mmi1(uint32_t op)
printf("Unsupported instruction: PCEQB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
case 0x10: /* PADDUW */
- {
- if (rd == 0) break;
-
- uint32_t rsval[4] = { (uint32_t)m_core->r[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->rh[rs] >> 32) };
- uint32_t rtval[4] = { (uint32_t)m_core->r[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->rh[rt] >> 32) };
- uint64_t rdval[4] = { 0 };
-
- for (int i = 0; i < 4; i++)
+ if (rd)
{
- uint64_t sum = (uint64_t)rsval[i] + (uint64_t)rtval[i];
- rdval[i] = (sum >= 0x100000000ULL) ? 0xffffffffULL : sum;
- }
- m_core->r[rd] = rdval[0] | (rdval[1] << 32);
- m_core->rh[rd] = rdval[2] | (rdval[3] << 32);
- break;
- }
+ uint32_t rsval[4] = { (uint32_t)m_core->r[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->rh[rs] >> 32) };
+ uint32_t rtval[4] = { (uint32_t)m_core->r[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->rh[rt] >> 32) };
+ uint64_t rdval[4] = { 0 };
+
+ for (int i = 0; i < 4; i++)
+ {
+ uint64_t sum = (uint64_t)rsval[i] + (uint64_t)rtval[i];
+ rdval[i] = (sum >= 0x100000000ULL) ? 0xffffffffULL : sum;
+ }
+ m_core->r[rd] = rdval[0] | (rdval[1] << 32);
+ m_core->rh[rd] = rdval[2] | (rdval[3] << 32);
+ }
+ break;
case 0x11: /* PSUBUW */
printf("Unsupported instruction: PSUBUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
break;
case 0x12: /* PEXTUW */
- printf("Unsupported instruction: PEXTUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");
+ if (rd)
+ {
+ uint64_t rsval = m_core->rh[rs];
+ uint64_t rtval = m_core->rh[rt];
+ m_core->rh[rd] = (rsval & 0xffffffff00000000ULL) | (rtval >> 32);
+ m_core->r[rd] = (rtval & 0x00000000ffffffffULL) | (rsval << 32);
+ }
break;
case 0x14: /* PADDUH */
printf("Unsupported instruction: PADDUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n");