diff options
Diffstat (limited to 'src/devices/cpu/mips/mips3.cpp')
-rw-r--r-- | src/devices/cpu/mips/mips3.cpp | 995 |
1 files changed, 919 insertions, 76 deletions
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index b2a1e3b7fdf..a06067ed3ef 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -15,7 +15,9 @@ #include "mips3dsm.h" -#define ENABLE_OVERFLOWS 0 +#define ENABLE_OVERFLOWS (0) +#define ENABLE_EE_ELF_LOADER (0) +#define ENABLE_EE_DECI2 (0) /*************************************************************************** HELPER MACROS @@ -242,6 +244,42 @@ void mips3_device::generate_exception(int exception, int backup) if (backup) m_core->pc = m_ppc; +#if ENABLE_EE_DECI2 + if (exception == EXCEPTION_SYSCALL && m_flavor == MIPS3_TYPE_R5900) + { + uint32_t call = 0; + bool success = RBYTE(m_core->pc - 4, &call); + //logerror("Syscall: %08x\n", call); + if (call == 0x7c) + { + const uint32_t func = m_core->r[4]; + const uint32_t param = m_core->r[5]; + logerror("Deci2 syscall, func=%08x, param=%08x\n", func, param); + if (func == 0x10 && success) + { + uint32_t str_addr = 0; + success = RWORD(param, &str_addr); + + logerror("Deci2 str_addr: %08x\n", str_addr); + + uint32_t curr_char = 0; + success = RBYTE(str_addr & 0x01ffffff, &curr_char); + + char buf[0x10000] = { 0 }; + uint32_t index = 0; + while (success && curr_char != 0 && index < 0xffff) + { + buf[index] = (char)curr_char; + success = RBYTE(str_addr & 0x01ffffff, &curr_char); + str_addr++; + } + buf[index] = 0; + logerror("Deci2 log: %s\n", buf); + } + } + } +#endif + /* translate our fake fill exceptions into real exceptions */ if (exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL) { @@ -283,8 +321,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) { - //printf("TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]); - //machine().debug_break(); + fprintf(stderr, "TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]); + machine().debug_break(); } else { @@ -1491,16 +1529,16 @@ inline void r5900le_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t dat { if (address >= 0x70000000 && address < 0x70004000) { - (*m_memory.write_qword)(*m_program, address, data_hi); - (*m_memory.write_qword)(*m_program, address + 8, data_lo); + (*m_memory.write_qword)(*m_program, address, data_lo); + (*m_memory.write_qword)(*m_program, address + 8, data_hi); return; } const uint32_t tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { - (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data_hi); - (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff), data_lo); + (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data_lo); + (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff), data_hi); } else { @@ -1581,16 +1619,16 @@ inline bool r5900le_device::RQUAD(offs_t address, uint64_t *result_hi, uint64_t { if (address >= 0x70000000 && address < 0x70004000) { - *result_hi = (*m_memory.read_qword)(*m_program, address); - *result_lo = (*m_memory.read_qword)(*m_program, address + 8); + *result_lo = (*m_memory.read_qword)(*m_program, address); + *result_hi = (*m_memory.read_qword)(*m_program, address + 8); return true; } const uint32_t tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { - *result_hi = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff)); - *result_lo = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff)); + *result_lo = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff)); + *result_hi = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff)); } else { @@ -2828,6 +2866,7 @@ inline void r5900le_device::set_cop2_reg(int idx, uint64_t val) inline uint64_t r5900le_device::get_cop2_creg(int idx) { + logerror("%s: CFC2: Getting ccr[%d] (%08x)\n", machine().describe_context(), idx, m_core->vcr[idx]); return m_core->vcr[idx]; } @@ -2839,6 +2878,7 @@ inline void r5900le_device::set_cop2_creg(int idx, uint64_t val) } else { + logerror("%s: CTC2: Setting ccr[%d] (%08x)\n", machine().describe_context(), idx, (uint32_t)val); switch (idx) { case 16: // Status flag @@ -2846,9 +2886,17 @@ inline void r5900le_device::set_cop2_creg(int idx, uint64_t val) break; case 17: // MAC flag + m_core->vcr[idx] = val & 0xffff; + break; + case 26: // TPC register + m_core->vcr[idx] = val & 0xffff; + logerror("%s: CTC2: Setting TPC to %08x\n", machine().describe_context(), m_core->vcr[idx]); + break; + case 27: // CMSAR0 register m_core->vcr[idx] = val & 0xffff; + logerror("%s: CTC2: Setting CMSAR0 to %08x\n", machine().describe_context(), m_core->vcr[idx]); break; case 18: // clipping flag @@ -2865,7 +2913,8 @@ inline void r5900le_device::set_cop2_creg(int idx, uint64_t val) break; case 28: // FBRST register - m_core->vcr[idx] = val & 0xf0f; + m_core->vcr[idx] = val & 0xc0c; + logerror("%s: CTC2: Setting FBRST to %08x\n", machine().describe_context(), val); break; case 29: // VPU-STAT register @@ -2874,6 +2923,7 @@ inline void r5900le_device::set_cop2_creg(int idx, uint64_t val) case 31: // CMSAR1 register m_core->vcr[idx] = val & 0xffff; + logerror("%s: CTC2: Setting CMSAR1 to %08x\n", machine().describe_context(), m_core->vcr[idx]); // TODO: Begin execution break; @@ -2912,7 +2962,7 @@ void mips3_device::handle_cop2(uint32_t op) switch (RTREG) { case 0x00: /* BCzF */ if (!m_cf[2]) ADDPC(SIMMVAL); break; - case 0x01: /* BCzF */ if (m_cf[2]) ADDPC(SIMMVAL); break; + case 0x01: /* BCzT */ if (m_cf[2]) ADDPC(SIMMVAL); break; case 0x02: /* BCzFL */ invalid_instruction(op); break; case 0x03: /* BCzTL */ invalid_instruction(op); break; default: invalid_instruction(op); break; @@ -3664,8 +3714,9 @@ void r5900le_device::handle_extra_cop1(uint32_t op) void r5900le_device::handle_idt(uint32_t op) { const int rs = (op >> 21) & 31; - //const int rt = (op >> 16) & 31; + const int rt = (op >> 16) & 31; const int rd = (op >> 11) & 31; + const int sa = (op >> 6) & 31; switch (op & 0x3f) { @@ -3691,7 +3742,7 @@ void r5900le_device::handle_idt(uint32_t op) { uint32_t value = (uint32_t)(rsval >> (word * 32)); const uint32_t compare = value & (1U << 31); - for (int bit = 30; bit > 0; bit--) + for (int bit = 30; bit >= 0; bit--) { value <<= 1; if ((value & (1U << 31)) == compare) @@ -3771,22 +3822,112 @@ void r5900le_device::handle_idt(uint32_t op) printf("Unsupported instruction: PMTHL @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x34: /* PSLLH */ - printf("Unsupported instruction: PSLLH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint16_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint16_t result = rthalf << (sa & 0xf); + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x36: /* PSRLH */ - printf("Unsupported instruction: PSRLH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint16_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint16_t result = rthalf >> (sa & 0xf); + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x37: /* PSRAH */ - printf("Unsupported instruction: PSRAH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const int16_t rthalf = (int16_t)(rtval[dword_idx] >> shift); + const int16_t result = rthalf >> (sa & 0xf); + rdval[dword_idx] |= (uint64_t)(uint16_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x3c: /* PSLLW */ - printf("Unsupported instruction: PSLLW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const uint32_t rtword = (uint32_t)(rtval[dword_idx] >> shift); + const uint32_t result = rtword << (sa & 0x1f); + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x3e: /* PSRLW */ - printf("Unsupported instruction: PSRLW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const uint32_t rtword = (uint32_t)(rtval[dword_idx] >> shift); + const uint32_t result = rtword >> (sa & 0x1f); + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x3f: /* PSRAW */ - printf("Unsupported instruction: PSRAW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const int32_t rtword = (int32_t)(rtval[dword_idx] >> shift); + const int32_t result = rtword >> (sa & 0x1f); + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; default: invalid_instruction(op); @@ -3803,42 +3944,188 @@ void r5900le_device::handle_mmi0(uint32_t op) switch ((op >> 6) & 0x1f) { case 0x00: /* PADDW */ - printf("Unsupported instruction: PADDW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const uint32_t rsword = (uint32_t)(rsval[dword_idx] >> shift); + const uint32_t rtword = (uint32_t)(rtval[dword_idx] >> shift); + const uint32_t result = rsword + rtword; + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x01: /* PSUBW */ 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++) + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) { - rdval[word_idx] = rsval[word_idx] - rtval[word_idx]; + for (int shift = 0; shift < 64; shift += 32) + { + const uint32_t rsword = (uint32_t)(rsval[dword_idx] >> shift); + const uint32_t rtword = (uint32_t)(rtval[dword_idx] >> shift); + const uint32_t result = rsword - rtword; + rdval[dword_idx] |= (uint64_t)result << shift; + } } - m_core->rh[rd] = ((uint64_t)rdval[0] << 32) | rdval[1]; - m_core->r[rd] = ((uint64_t)rdval[2] << 32) | rdval[3]; + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; } break; case 0x02: /* PCGTW */ - printf("Unsupported instruction: PCGTW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int word_idx = 0; word_idx < 64; word_idx += 32) + { + const int32_t rsword = (int32_t)(rsval[dword_idx] >> word_idx); + const int32_t rtword = (int32_t)(rtval[dword_idx] >> word_idx); + if (rsword > rtword) + { + rdval[dword_idx] |= (uint64_t)0xffffffff << word_idx; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x03: /* PMAXW */ - printf("Unsupported instruction: PMAXW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const int32_t rsword = (int32_t)(rsval[dword_idx] >> shift); + const int32_t rtword = (int32_t)(rtval[dword_idx] >> shift); + const int32_t result = (rsword > rtword) ? rsword : rtword; + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x04: /* PADDH */ - printf("Unsupported instruction: PADDH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint16_t rshalf = (uint16_t)(rsval[dword_idx] >> shift); + const uint16_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint16_t result = rshalf + rthalf; + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x05: /* PSUBH */ - printf("Unsupported instruction: PSUBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint16_t rshalf = (uint16_t)(rsval[dword_idx] >> shift); + const uint16_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint16_t result = rshalf - rthalf; + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x06: /* PCGTH */ - printf("Unsupported instruction: PCGTH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int half_idx = 0; half_idx < 64; half_idx += 16) + { + const int16_t rshalf = (int16_t)(rsval[dword_idx] >> half_idx); + const int16_t rthalf = (int16_t)(rtval[dword_idx] >> half_idx); + if (rshalf > rthalf) + { + rdval[dword_idx] |= (uint64_t)0xffff << half_idx; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x07: /* PMAXH */ - printf("Unsupported instruction: PMAXH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const int16_t rshalf = (int16_t)(rsval[dword_idx] >> shift); + const int16_t rthalf = (int16_t)(rtval[dword_idx] >> shift); + const int16_t result = (rshalf > rthalf) ? rshalf : rthalf; + rdval[dword_idx] |= (uint64_t)(uint16_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x08: /* PADDB */ - printf("Unsupported instruction: PADDB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int byte_idx = 0; byte_idx < 64; byte_idx += 8) + { + const uint8_t rsbyte = (uint8_t)(rsval[dword_idx] >> byte_idx); + const uint8_t rtbyte = (uint8_t)(rtval[dword_idx] >> byte_idx); + const uint8_t result = rsbyte + rtbyte; + rdval[dword_idx] |= (uint64_t)result << byte_idx; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x09: /* PSUBB */ if (rd) @@ -3846,14 +4133,14 @@ void r5900le_device::handle_mmi0(uint32_t op) const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; uint64_t rdval[2] = { 0, 0 }; - for (int word_idx = 0; word_idx < 2; word_idx++) + for (int dword_idx = 0; dword_idx < 2; dword_idx++) { for (int byte_idx = 0; byte_idx < 64; byte_idx += 8) { - const uint8_t rsbyte = (uint8_t)(rsval[word_idx] >> byte_idx); - const uint8_t rtbyte = (uint8_t)(rtval[word_idx] >> byte_idx); + const uint8_t rsbyte = (uint8_t)(rsval[dword_idx] >> byte_idx); + const uint8_t rtbyte = (uint8_t)(rtval[dword_idx] >> byte_idx); const uint8_t result = rsbyte - rtbyte; - rdval[word_idx] |= (uint64_t)result << byte_idx; + rdval[dword_idx] |= (uint64_t)result << byte_idx; } } m_core->rh[rd] = rdval[0]; @@ -3861,13 +4148,88 @@ void r5900le_device::handle_mmi0(uint32_t op) } break; case 0x0a: /* PCGTB */ - printf("Unsupported instruction: PCGTB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int byte_idx = 0; byte_idx < 64; byte_idx += 8) + { + const int8_t rsbyte = (int8_t)(rsval[dword_idx] >> byte_idx); + const int8_t rtbyte = (int8_t)(rtval[dword_idx] >> byte_idx); + if (rsbyte > rtbyte) + { + rdval[dword_idx] |= (uint64_t)0xff << byte_idx; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x10: /* PADDSW */ - printf("Unsupported instruction: PADDSW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const int64_t rsword = (int64_t)(int32_t)(rsval[dword_idx] >> shift); + const int64_t rtword = (int64_t)(int32_t)(rtval[dword_idx] >> shift); + const int64_t result = rsword + rtword; + if (result < (int32_t)0x80000000) + { + rdval[dword_idx] |= (uint64_t)0x80000000 << shift; + } + else if (result > 0x7fffffff) + { + rdval[dword_idx] |= (uint64_t)0x7fffffff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x11: /* PSUBSW */ - printf("Unsupported instruction: PSUBSW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const int64_t rsword = (int64_t)(int32_t)(rsval[dword_idx] >> shift); + const int64_t rtword = (int64_t)(int32_t)(rtval[dword_idx] >> shift); + const int64_t result = rsword - rtword; + if (result < (int32_t)0x80000000) + { + rdval[dword_idx] |= (uint64_t)0x80000000 << shift; + } + else if (result > 0x7fffffff) + { + rdval[dword_idx] |= (uint64_t)0x7fffffff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x12: /* PEXTLW */ { @@ -3885,10 +4247,66 @@ void r5900le_device::handle_mmi0(uint32_t op) printf("Unsupported instruction: PPACW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x14: /* PADDSH */ - printf("Unsupported instruction: PADDSH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const int32_t rshalf = (int32_t)(int16_t)(rsval[dword_idx] >> shift); + const int32_t rthalf = (int32_t)(int16_t)(rtval[dword_idx] >> shift); + const int32_t result = rshalf + rthalf; + if (result < -32768) + { + rdval[dword_idx] |= (uint64_t)0x8000 << shift; + } + else if (result > 32767) + { + rdval[dword_idx] |= (uint64_t)0x7fff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)(uint16_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x15: /* PSUBSH */ - printf("Unsupported instruction: PSUBSH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const int32_t rshalf = (int32_t)(int16_t)(rsval[dword_idx] >> shift); + const int32_t rthalf = (int32_t)(int16_t)(rtval[dword_idx] >> shift); + const int32_t result = rshalf - rthalf; + if (result < -32768) + { + rdval[dword_idx] |= (uint64_t)0x8000 << shift; + } + else if (result > 32767) + { + rdval[dword_idx] |= (uint64_t)0x7fff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)(uint16_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x16: /* PEXTLH */ printf("Unsupported instruction: PEXTLH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -3897,10 +4315,66 @@ void r5900le_device::handle_mmi0(uint32_t op) printf("Unsupported instruction: PPACH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x18: /* PADDSB */ - printf("Unsupported instruction: PADDSB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 8) + { + const int32_t rsbyte = (int32_t)(int8_t)(rsval[dword_idx] >> shift); + const int32_t rtbyte = (int32_t)(int8_t)(rtval[dword_idx] >> shift); + const int32_t result = rsbyte + rtbyte; + if (result < -128) + { + rdval[dword_idx] |= (uint64_t)0x80 << shift; + } + else if (result > 127) + { + rdval[dword_idx] |= (uint64_t)0x7f << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)(uint8_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x19: /* PSUBSB */ - printf("Unsupported instruction: PSUBSB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 8) + { + const int32_t rsbyte = (int32_t)(int8_t)(rsval[dword_idx] >> shift); + const int32_t rtbyte = (int32_t)(int8_t)(rtval[dword_idx] >> shift); + const int32_t result = rsbyte - rtbyte; + if (result < -128) + { + rdval[dword_idx] |= (uint64_t)0x80 << shift; + } + else if (result >= 127) + { + rdval[dword_idx] |= (uint64_t)0x7f << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)(uint8_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x1a: /* PEXTLB */ printf("Unsupported instruction: PEXTLB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -3929,47 +4403,236 @@ void r5900le_device::handle_mmi1(uint32_t op) switch ((op >> 6) & 0x1f) { case 0x01: /* PABSW */ - printf("Unsupported instruction: PABSW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const int32_t rtword = (int32_t)(rtval[dword_idx] >> shift); + if (rtword == 0x80000000) + { + rdval[dword_idx] |= (uint64_t)0x7fffffff << shift; + } + else if (rtword < 0) + { + rdval[dword_idx] |= (uint64_t)(0 - rtword) << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)rtword << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x02: /* PCEQW */ - printf("Unsupported instruction: PCEQW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int word_idx = 0; word_idx < 64; word_idx += 32) + { + const uint32_t rsword = (uint32_t)(rsval[dword_idx] >> word_idx); + const uint32_t rtword = (uint32_t)(rtval[dword_idx] >> word_idx); + if (rsword == rtword) + { + rdval[dword_idx] |= (uint64_t)0xffffffff << word_idx; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x03: /* PMINW */ - printf("Unsupported instruction: PMINW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const int32_t rsword = (int32_t)(rsval[dword_idx] >> shift); + const int32_t rtword = (int32_t)(rtval[dword_idx] >> shift); + const int32_t result = (rsword > rtword) ? rtword : rsword; + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x04: /* PADSBH */ - printf("Unsupported instruction: PADSBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint16_t rshalf = (uint16_t)(rsval[dword_idx] >> shift); + const uint16_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint16_t result = dword_idx ? (rshalf - rthalf) : (rshalf + rthalf); + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x05: /* PABSH */ - printf("Unsupported instruction: PABSH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const int16_t rthalf = (int16_t)(rtval[dword_idx] >> shift); + if (rthalf == -32768) + { + rdval[dword_idx] |= (uint64_t)0x7fff << shift; + } + else if (rthalf < 0) + { + rdval[dword_idx] |= (uint64_t)(0 - rthalf) << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)rthalf << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x06: /* PCEQH */ - printf("Unsupported instruction: PCEQH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int half_idx = 0; half_idx < 64; half_idx += 16) + { + const uint16_t rshalf = (uint16_t)(rsval[dword_idx] >> half_idx); + const uint16_t rthalf = (uint16_t)(rtval[dword_idx] >> half_idx); + if (rshalf == rthalf) + { + rdval[dword_idx] |= (uint64_t)0xffff << half_idx; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x07: /* PMINH */ - printf("Unsupported instruction: PMINH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const int16_t rshalf = (int16_t)(rsval[dword_idx] >> shift); + const int16_t rthalf = (int16_t)(rtval[dword_idx] >> shift); + const int16_t result = (rshalf > rthalf) ? rthalf : rshalf; + rdval[dword_idx] |= (uint64_t)(uint16_t)result << shift; + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x0a: /* PCEQB */ - printf("Unsupported instruction: PCEQB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int byte_idx = 0; byte_idx < 64; byte_idx += 8) + { + const uint8_t rsbyte = (uint8_t)(rsval[dword_idx] >> byte_idx); + const uint8_t rtbyte = (uint8_t)(rtval[dword_idx] >> byte_idx); + if (rsbyte == rtbyte) + { + rdval[dword_idx] |= (uint64_t)0xff << byte_idx; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x10: /* PADDUW */ - if (rd) - { - 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) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) { - uint64_t sum = (uint64_t)rsval[i] + (uint64_t)rtval[i]; - rdval[i] = (sum >= 0x100000000ULL) ? 0xffffffffULL : sum; + for (int shift = 0; shift < 64; shift += 32) + { + const uint64_t rshalf = (uint32_t)(rsval[dword_idx] >> shift); + const uint64_t rthalf = (uint32_t)(rtval[dword_idx] >> shift); + const uint64_t result = rshalf + rthalf; + if (result > 0xffffffff) + { + rdval[dword_idx] |= (uint64_t)0xffffffff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)result << shift; + } + } } - m_core->r[rd] = rdval[0] | (rdval[1] << 32); - m_core->rh[rd] = rdval[2] | (rdval[3] << 32); + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; } break; case 0x11: /* PSUBUW */ - printf("Unsupported instruction: PSUBUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 32) + { + const uint64_t rsword = (uint32_t)(rsval[dword_idx] >> shift); + const uint64_t rtword = (uint32_t)(rtval[dword_idx] >> shift); + const uint64_t result = rsword - rtword; + if (result < 0x100000000ULL) + { + rdval[dword_idx] |= (uint64_t)(uint32_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x12: /* PEXTUW */ if (rd) @@ -3981,19 +4644,107 @@ void r5900le_device::handle_mmi1(uint32_t op) } break; case 0x14: /* PADDUH */ - printf("Unsupported instruction: PADDUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint32_t rshalf = (uint16_t)(rsval[dword_idx] >> shift); + const uint32_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint32_t result = rshalf + rthalf; + if (result > 0xffff) + { + rdval[dword_idx] |= (uint64_t)0xffff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x15: /* PSUBUH */ - printf("Unsupported instruction: PSUBUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 16) + { + const uint32_t rshalf = (uint16_t)(rsval[dword_idx] >> shift); + const uint32_t rthalf = (uint16_t)(rtval[dword_idx] >> shift); + const uint32_t result = rshalf - rthalf; + if (result < 0x10000) + { + rdval[dword_idx] |= (uint64_t)(uint16_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x16: /* PEXTUH */ printf("Unsupported instruction: PEXTUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x18: /* PADDUB */ - printf("Unsupported instruction: PADDUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 8) + { + const uint32_t rsbyte = (uint8_t)(rsval[dword_idx] >> shift); + const uint32_t rtbyte = (uint8_t)(rtval[dword_idx] >> shift); + const uint32_t result = rsbyte + rtbyte; + if (result > 0xff) + { + rdval[dword_idx] |= (uint64_t)0xff << shift; + } + else + { + rdval[dword_idx] |= (uint64_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x19: /* PSUBUB */ - printf("Unsupported instruction: PSUBUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + for (int shift = 0; shift < 64; shift += 8) + { + const uint32_t rsbyte = (uint8_t)(rsval[dword_idx] >> shift); + const uint32_t rtbyte = (uint8_t)(rtval[dword_idx] >> shift); + const uint32_t result = rsbyte - rtbyte; + if (result < 0x100) + { + rdval[dword_idx] |= (uint64_t)(uint8_t)result << shift; + } + } + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x1a: /* PEXTUB */ printf("Unsupported instruction: PEXTUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -4019,10 +4770,37 @@ void r5900le_device::handle_mmi2(uint32_t op) printf("Unsupported instruction: PMADDW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x02: /* PSLLVW */ - printf("Unsupported instruction: PSLLVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + const uint64_t rsword = (uint32_t)rsval[dword_idx]; + const uint64_t rtword = (uint32_t)rtval[dword_idx]; + const uint32_t result = rtword << (rsword & 0x1f); + rdval[dword_idx] = (uint64_t)(int64_t)(int32_t)result; + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x03: /* PSRLVW */ - printf("Unsupported instruction: PSRLVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + const uint64_t rsword = (uint32_t)rsval[dword_idx]; + const uint64_t rtword = (uint32_t)rtval[dword_idx]; + rdval[dword_idx] = (uint64_t)(int64_t)(int32_t)(rtword >> (rsword & 0x1f)); + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x04: /* PMSUBW */ printf("Unsupported instruction: PMSUBW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -4119,13 +4897,29 @@ void r5900le_device::handle_mmi3(uint32_t op) printf("Unsupported instruction: PMADDUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x03: /* PSRAVW */ - printf("Unsupported instruction: PSRAVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval[2] = { m_core->rh[rs], m_core->r[rs] }; + const uint64_t rtval[2] = { m_core->rh[rt], m_core->r[rt] }; + uint64_t rdval[2] = { 0, 0 }; + for (int dword_idx = 0; dword_idx < 2; dword_idx++) + { + const uint32_t rsword = (uint32_t)rsval[dword_idx]; + const int32_t rtword = (int32_t)rtval[dword_idx]; + const int32_t result = rtword >> (rsword & 0x1f); + rdval[dword_idx] = (uint64_t)(int64_t)result; + } + m_core->rh[rd] = rdval[0]; + m_core->r[rd] = rdval[1]; + } break; case 0x08: /* PMTHI */ - printf("Unsupported instruction: PMTHI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + m_core->r[REG_HI] = m_core->r[rs]; + m_core->rh[REG_HI] = m_core->rh[rs]; break; case 0x09: /* PTMLO */ - printf("Unsupported instruction: PMTLO @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + m_core->r[REG_LO] = m_core->r[rs]; + m_core->rh[REG_LO] = m_core->rh[rs]; break; case 0x0a: /* PINTEH */ printf("Unsupported instruction: PINTEH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); @@ -4446,10 +5240,24 @@ void mips3_device::execute_run() handle_extra_base(op); break; } + +#if ENABLE_EE_ELF_LOADER + bool had_delay = m_delayslot; +#endif + /* Clear this flag once instruction execution is finished, will interfere with interrupt exceptions otherwise */ m_delayslot = false; m_core->icount--; +#if ENABLE_EE_ELF_LOADER + static bool elf_loaded = false; + if (had_delay && m_core->pc < 0x80000000 && m_core->pc >= 0x00100000 && !elf_loaded) + { + load_elf(); + m_core->icount = 0; + elf_loaded = true; + } +#endif } while (m_core->icount > 0 || m_nextpc != ~0); m_core->icount -= m_interrupt_cycles; @@ -4615,3 +5423,38 @@ void mips3_device::sdr_le(uint32_t op) uint64_t mask = 0xffffffffffffffffU << shift; WDOUBLE_MASKED(offs & ~7, RTVAL64 << shift, mask); } + +void mips3_device::load_elf() +{ + FILE *elf = fopen("alu.elf", "rb"); + fseek(elf, 0, SEEK_END); + const uint32_t size = ftell(elf); + fseek(elf, 0, SEEK_SET); + uint8_t *buf = new uint8_t[size]; + fread(buf, 1, size, elf); + fclose(elf); + + const uint32_t header_offset = *reinterpret_cast<uint32_t*>(&buf[0x1c]); + const uint16_t block_count = *reinterpret_cast<uint16_t*>(&buf[0x2c]); + + for (uint32_t i = 0; i < block_count; i++) + { + const uint32_t *header_entry = reinterpret_cast<uint32_t*>(&buf[header_offset + i * 0x20]); + + const uint32_t word_count = header_entry[4] >> 2; + const uint32_t file_offset = header_entry[1]; + const uint32_t *file_data = reinterpret_cast<uint32_t*>(&buf[file_offset]); + uint32_t addr = header_entry[3]; + for (uint32_t word = 0; word < word_count; word++) + { + WWORD(addr, file_data[word]); + addr += 4; + } + } + + const uint32_t entry_point = *reinterpret_cast<uint32_t*>(&buf[0x18]); + m_core->pc = entry_point; + m_ppc = entry_point; + + delete [] buf; +} |