From 5db11a5e0229ee65361943b64ca7972c2788a6a6 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Tue, 17 Jul 2018 18:14:12 +0200 Subject: [PATCH] ps2sony: Checkpoint, nw --- scripts/src/cpu.lua | 4 + src/devices/cpu/mips/mips3.cpp | 995 +++++++++++++++++++++++++++--- src/devices/cpu/mips/mips3.h | 17 +- src/devices/cpu/mips/mips3com.cpp | 2 +- src/devices/cpu/mips/r3000.cpp | 9 +- src/devices/cpu/mips/sonyvu.cpp | 878 ++++++++++++++++++++++++++ src/devices/cpu/mips/sonyvu.h | 209 +++++++ src/devices/cpu/mips/vudasm.cpp | 461 ++++++++++++++ src/devices/cpu/mips/vudasm.h | 39 ++ src/mame/drivers/ps2sony.cpp | 28 +- src/mame/machine/iopcdvd.cpp | 168 +++-- src/mame/machine/iopcdvd.h | 31 +- src/mame/machine/ioptimer.cpp | 6 +- src/mame/machine/ps2dma.cpp | 67 +- src/mame/machine/ps2vif1.cpp | 80 ++- src/mame/machine/ps2vif1.h | 8 +- src/mame/video/ps2gs.cpp | 10 +- src/mame/video/ps2gs.h | 31 +- 18 files changed, 2816 insertions(+), 227 deletions(-) create mode 100644 src/devices/cpu/mips/sonyvu.cpp create mode 100644 src/devices/cpu/mips/sonyvu.h create mode 100644 src/devices/cpu/mips/vudasm.cpp create mode 100644 src/devices/cpu/mips/vudasm.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 132c32861a7..afb115313a3 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1263,12 +1263,16 @@ if (CPUS["MIPS"]~=null) then MAME_DIR .. "src/devices/cpu/mips/mips3fe.cpp", MAME_DIR .. "src/devices/cpu/mips/mips3fe.h", MAME_DIR .. "src/devices/cpu/mips/mips3drc.cpp", + MAME_DIR .. "src/devices/cpu/mips/sonyvu.cpp", + MAME_DIR .. "src/devices/cpu/mips/sonyvu.h", } end if (CPUS["MIPS"]~=null or _OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/mips3dsm.cpp") table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/mips3dsm.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/vudasm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/vudasm.h") end -------------------------------------------------- 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(&buf[0x1c]); + const uint16_t block_count = *reinterpret_cast(&buf[0x2c]); + + for (uint32_t i = 0; i < block_count; i++) + { + const uint32_t *header_entry = reinterpret_cast(&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(&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(&buf[0x18]); + m_core->pc = entry_point; + m_ppc = entry_point; + + delete [] buf; +} diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index a2aa5a345dc..653d8ce6841 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -18,6 +18,7 @@ MIPS III/IV emulator. #include "divtlb.h" #include "cpu/drcfe.h" #include "cpu/drcuml.h" +#include "sonyvu.h" // NEC VR4300 series is MIPS III with 32-bit address bus and slightly custom COP0/TLB @@ -366,7 +367,7 @@ protected: float acc; /* VU0 registers (R5900 only) */ - float vfr[32][4]; // 0..3 = w..x + float vfr[32][4]; // 0..3 = x..w uint32_t vcr[32]; float vumem[0x1000]; float* vfmem; @@ -629,6 +630,7 @@ private: void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); void log_opcode_desc(const opcode_desc *desclist, int indent); + void load_elf(); }; @@ -778,8 +780,17 @@ public: class r5900le_device : public mips3_device { public: // construction/destruction + template + r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&vu0_tag) + : r5900le_device(mconfig, tag, owner, clock) + { + m_vu0.set_tag(std::forward(vu0_tag)); + } + r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE, 64) { + : mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE, 64) + , m_vu0(*this, finder_base::DUMMY_TAG) + { } protected: @@ -824,6 +835,8 @@ protected: void handle_sdc2(uint32_t op) override; void handle_dmfc2(uint32_t op) override; void handle_dmtc2(uint32_t op) override; + + required_device m_vu0; }; class qed5271be_device : public mips3_device { diff --git a/src/devices/cpu/mips/mips3com.cpp b/src/devices/cpu/mips/mips3com.cpp index 8b8accf8c4c..32fdfe9ec95 100644 --- a/src/devices/cpu/mips/mips3com.cpp +++ b/src/devices/cpu/mips/mips3com.cpp @@ -326,7 +326,7 @@ uint32_t mips3_device::compute_prid_register() return 0x2700; case MIPS3_TYPE_R5900: - return 0x2e59; + return 0x2e14; default: fatalerror("Unknown MIPS flavor specified\n"); diff --git a/src/devices/cpu/mips/r3000.cpp b/src/devices/cpu/mips/r3000.cpp index cc821ef6350..ab17dab98d3 100644 --- a/src/devices/cpu/mips/r3000.cpp +++ b/src/devices/cpu/mips/r3000.cpp @@ -14,7 +14,8 @@ #include "debugger.h" -#define ENABLE_OVERFLOWS 0 +#define ENABLE_OVERFLOWS (0) +#define ENABLE_IOP_KPUTS (0) /*************************************************************************** @@ -1075,7 +1076,8 @@ void r3000_device::execute_run() // debugging m_ppc = m_pc; debugger_instruction_hook(m_pc); - /* + +#if ENABLE_IOP_KPUTS if ((m_pc & 0x1fffffff) == 0x00012C48 || (m_pc & 0x1fffffff) == 0x0001420C || (m_pc & 0x1fffffff) == 0x0001430C) { uint32_t ptr = m_r[5]; @@ -1090,7 +1092,8 @@ void r3000_device::execute_run() } fflush(stdout); } - */ +#endif + // instruction fetch m_op = readop(m_pc); diff --git a/src/devices/cpu/mips/sonyvu.cpp b/src/devices/cpu/mips/sonyvu.cpp new file mode 100644 index 00000000000..550956cdd52 --- /dev/null +++ b/src/devices/cpu/mips/sonyvu.cpp @@ -0,0 +1,878 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 Vector Unit device skeleton +* +* To Do: +* Everything +* +*/ + +#include "emu.h" +#include "sonyvu.h" +#include "vudasm.h" +#include "debugger.h" + +DEFINE_DEVICE_TYPE(SONYVU0, sonyvu0_device, "sonyvu0", "Sony PlayStation 2 VU0") +DEFINE_DEVICE_TYPE(SONYVU1, sonyvu1_device, "sonyvu1", "Sony PlayStation 2 VU1") + +sonyvu_device::sonyvu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, + address_map_constructor micro_cons, address_map_constructor vu_cons, chip_type chiptype, uint32_t mem_size) + : cpu_device(mconfig, type, tag, owner, clock) + , m_micro_config("micro", ENDIANNESS_LITTLE, 64, 12, 0, micro_cons) + , m_vu_config("vu", ENDIANNESS_LITTLE, 32, 12, 0, vu_cons) + , m_micro_space(nullptr) + , m_vu_space(nullptr) + , m_mem_size(mem_size) + , m_mem_mask(mem_size-1) + , m_micro_mem(*this, "micro") + , m_vu_mem(*this, "vu") + , m_vfmem(nullptr) + , m_vimem(nullptr) + , m_v(nullptr) + , m_status_flag(0) + , m_mac_flag(0) + , m_clip_flag(0) + , m_r(0) + , m_i(0.0f) + , m_q(0.0f) + , m_pc(0) + , m_running(false) + , m_icount(0) +{ +} + +sonyvu0_device::sonyvu0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sonyvu_device(mconfig, SONYVU0, tag, owner, clock, address_map_constructor(FUNC(sonyvu0_device::micro_map), this), address_map_constructor(FUNC(sonyvu0_device::vu_map), this), CHIP_TYPE_VU0, 0x1000) + , m_vu1(*this, finder_base::DUMMY_TAG) +{ +} + +sonyvu1_device::sonyvu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sonyvu_device(mconfig, SONYVU1, tag, owner, clock, address_map_constructor(FUNC(sonyvu1_device::micro_map), this), address_map_constructor(FUNC(sonyvu1_device::vu_map), this), CHIP_TYPE_VU0, 0x4000) +{ +} + +void sonyvu_device::device_start() +{ + // set our instruction counter + set_icountptr(m_icount); + + m_micro_space = &space(AS_PROGRAM); + m_vu_space = &space(AS_DATA); + + /* register for save states */ + for (int i = 0; i < 32; i++) + { + save_item(NAME(m_vfr[i][0]), i); + save_item(NAME(m_vfr[i][1]), i); + save_item(NAME(m_vfr[i][2]), i); + save_item(NAME(m_vfr[i][3]), i); + } + save_item(NAME(m_vcr)); + save_item(NAME(m_acc)); + save_item(NAME(m_running)); + save_item(NAME(m_icount)); + + save_item(NAME(m_status_flag)); + save_item(NAME(m_mac_flag)); + save_item(NAME(m_clip_flag)); + save_item(NAME(m_r)); + save_item(NAME(m_i)); + save_item(NAME(m_q)); + save_item(NAME(m_pc)); + + state_add(STATE_GENPC, "GENPC", m_pc).noshow(); + state_add(SONYVU_TPC, "TPC", m_pc); + state_add(SONYVU_SF, "SF", m_status_flag); + state_add(SONYVU_MF, "MF", m_mac_flag); + state_add(SONYVU_CF, "CF", m_clip_flag); + state_add(SONYVU_R, "R", m_r); + state_add(SONYVU_I, "I", *(uint32_t*)&m_i).formatstr("%17s"); + state_add(SONYVU_Q, "Q", *(uint32_t*)&m_q).formatstr("%17s"); + + char elements[4] = { 'x', 'y', 'z', 'w' }; + char regname[6]; + + for (int i = 0; i < 4; i++) + { + snprintf(regname, 6, "ACC%c", elements[i]); + state_add(SONYVU_ACCx + i, regname, *(uint32_t*)&m_acc[i]).formatstr("%17s"); + } + for (int i = 0; i < 32; i++) + { + for (int j = 0; j < 4; j++) + { + snprintf(regname, 6, "VF%02d%c", i, elements[j]); + state_add(SONYVU_VF00x + i*4 + j, regname, *(uint32_t*)&m_vfr[i][j]).formatstr("%17s"); + } + } + for (int i = 0; i < 16; i++) + { + snprintf(regname, 6, "VI%02d", i); + state_add(SONYVU_VI00 + i, regname, m_vcr[i]); + } +} + +void sonyvu_device::device_reset() +{ + m_vfmem = reinterpret_cast(&m_vu_mem[0]); + m_vimem = &m_vu_mem[0]; + + // clear some additional state + memset(m_vfr, 0, sizeof(float) * 32 * 4); + memset(m_vcr, 0, sizeof(float) * 32); + memset(m_acc, 0, sizeof(float) * 4); + + m_v = reinterpret_cast(m_vfr); + + m_status_flag = 0; + m_mac_flag = 0; + m_clip_flag = 0; + m_r = 0; + m_i = 0.0f; + m_q = 0.0f; + m_pc = 0; + + m_v[3] = 1.0f; + + m_running = false; +} + +device_memory_interface::space_config_vector sonyvu_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_micro_config), + std::make_pair(AS_DATA, &m_vu_config) + }; +} + +void sonyvu_device::state_import(const device_state_entry &entry) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + break; + + default: + fatalerror("sonyvu_device::state_import called for unexpected value\n"); + } +} + +void sonyvu_device::state_export(const device_state_entry &entry) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + break; + + default: + fatalerror("sonyvu_device::state_export called for unexpected value\n"); + } +} + +void sonyvu_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + switch (entry.index()) + { + case SONYVU_I: str = string_format("!%16g", m_i); break; + case SONYVU_Q: str = string_format("!%16g", m_q); break; + case SONYVU_ACCx: str = string_format("!%16g", m_acc[0]); break; + case SONYVU_ACCy: str = string_format("!%16g", m_acc[1]); break; + case SONYVU_ACCz: str = string_format("!%16g", m_acc[2]); break; + case SONYVU_ACCw: str = string_format("!%16g", m_acc[3]); break; + case SONYVU_VF00x: str = string_format("!%16g", m_vfr[0][0]); break; + case SONYVU_VF00y: str = string_format("!%16g", m_vfr[0][1]); break; + case SONYVU_VF00z: str = string_format("!%16g", m_vfr[0][2]); break; + case SONYVU_VF00w: str = string_format("!%16g", m_vfr[0][3]); break; + case SONYVU_VF01x: str = string_format("!%16g", m_vfr[1][0]); break; + case SONYVU_VF01y: str = string_format("!%16g", m_vfr[1][1]); break; + case SONYVU_VF01z: str = string_format("!%16g", m_vfr[1][2]); break; + case SONYVU_VF01w: str = string_format("!%16g", m_vfr[1][3]); break; + case SONYVU_VF02x: str = string_format("!%16g", m_vfr[2][0]); break; + case SONYVU_VF02y: str = string_format("!%16g", m_vfr[2][1]); break; + case SONYVU_VF02z: str = string_format("!%16g", m_vfr[2][2]); break; + case SONYVU_VF02w: str = string_format("!%16g", m_vfr[2][3]); break; + case SONYVU_VF03x: str = string_format("!%16g", m_vfr[3][0]); break; + case SONYVU_VF03y: str = string_format("!%16g", m_vfr[3][1]); break; + case SONYVU_VF03z: str = string_format("!%16g", m_vfr[3][2]); break; + case SONYVU_VF03w: str = string_format("!%16g", m_vfr[3][3]); break; + case SONYVU_VF04x: str = string_format("!%16g", m_vfr[4][0]); break; + case SONYVU_VF04y: str = string_format("!%16g", m_vfr[4][1]); break; + case SONYVU_VF04z: str = string_format("!%16g", m_vfr[4][2]); break; + case SONYVU_VF04w: str = string_format("!%16g", m_vfr[4][3]); break; + case SONYVU_VF05x: str = string_format("!%16g", m_vfr[5][0]); break; + case SONYVU_VF05y: str = string_format("!%16g", m_vfr[5][1]); break; + case SONYVU_VF05z: str = string_format("!%16g", m_vfr[5][2]); break; + case SONYVU_VF05w: str = string_format("!%16g", m_vfr[5][3]); break; + case SONYVU_VF06x: str = string_format("!%16g", m_vfr[6][0]); break; + case SONYVU_VF06y: str = string_format("!%16g", m_vfr[6][1]); break; + case SONYVU_VF06z: str = string_format("!%16g", m_vfr[6][2]); break; + case SONYVU_VF06w: str = string_format("!%16g", m_vfr[6][3]); break; + case SONYVU_VF07x: str = string_format("!%16g", m_vfr[7][0]); break; + case SONYVU_VF07y: str = string_format("!%16g", m_vfr[7][1]); break; + case SONYVU_VF07z: str = string_format("!%16g", m_vfr[7][2]); break; + case SONYVU_VF07w: str = string_format("!%16g", m_vfr[7][3]); break; + case SONYVU_VF08x: str = string_format("!%16g", m_vfr[8][0]); break; + case SONYVU_VF08y: str = string_format("!%16g", m_vfr[8][1]); break; + case SONYVU_VF08z: str = string_format("!%16g", m_vfr[8][2]); break; + case SONYVU_VF08w: str = string_format("!%16g", m_vfr[8][3]); break; + case SONYVU_VF09x: str = string_format("!%16g", m_vfr[9][0]); break; + case SONYVU_VF09y: str = string_format("!%16g", m_vfr[9][1]); break; + case SONYVU_VF09z: str = string_format("!%16g", m_vfr[9][2]); break; + case SONYVU_VF09w: str = string_format("!%16g", m_vfr[9][3]); break; + case SONYVU_VF10x: str = string_format("!%16g", m_vfr[10][0]); break; + case SONYVU_VF10y: str = string_format("!%16g", m_vfr[10][1]); break; + case SONYVU_VF10z: str = string_format("!%16g", m_vfr[10][2]); break; + case SONYVU_VF10w: str = string_format("!%16g", m_vfr[10][3]); break; + case SONYVU_VF11x: str = string_format("!%16g", m_vfr[11][0]); break; + case SONYVU_VF11y: str = string_format("!%16g", m_vfr[11][1]); break; + case SONYVU_VF11z: str = string_format("!%16g", m_vfr[11][2]); break; + case SONYVU_VF11w: str = string_format("!%16g", m_vfr[11][3]); break; + case SONYVU_VF12x: str = string_format("!%16g", m_vfr[12][0]); break; + case SONYVU_VF12y: str = string_format("!%16g", m_vfr[12][1]); break; + case SONYVU_VF12z: str = string_format("!%16g", m_vfr[12][2]); break; + case SONYVU_VF12w: str = string_format("!%16g", m_vfr[12][3]); break; + case SONYVU_VF13x: str = string_format("!%16g", m_vfr[13][0]); break; + case SONYVU_VF13y: str = string_format("!%16g", m_vfr[13][1]); break; + case SONYVU_VF13z: str = string_format("!%16g", m_vfr[13][2]); break; + case SONYVU_VF13w: str = string_format("!%16g", m_vfr[13][3]); break; + case SONYVU_VF14x: str = string_format("!%16g", m_vfr[14][0]); break; + case SONYVU_VF14y: str = string_format("!%16g", m_vfr[14][1]); break; + case SONYVU_VF14z: str = string_format("!%16g", m_vfr[14][2]); break; + case SONYVU_VF14w: str = string_format("!%16g", m_vfr[14][3]); break; + case SONYVU_VF15x: str = string_format("!%16g", m_vfr[15][0]); break; + case SONYVU_VF15y: str = string_format("!%16g", m_vfr[15][1]); break; + case SONYVU_VF15z: str = string_format("!%16g", m_vfr[15][2]); break; + case SONYVU_VF15w: str = string_format("!%16g", m_vfr[15][3]); break; + case SONYVU_VF16x: str = string_format("!%16g", m_vfr[16][0]); break; + case SONYVU_VF16y: str = string_format("!%16g", m_vfr[16][1]); break; + case SONYVU_VF16z: str = string_format("!%16g", m_vfr[16][2]); break; + case SONYVU_VF16w: str = string_format("!%16g", m_vfr[16][3]); break; + case SONYVU_VF17x: str = string_format("!%16g", m_vfr[17][0]); break; + case SONYVU_VF17y: str = string_format("!%16g", m_vfr[17][1]); break; + case SONYVU_VF17z: str = string_format("!%16g", m_vfr[17][2]); break; + case SONYVU_VF17w: str = string_format("!%16g", m_vfr[17][3]); break; + case SONYVU_VF18x: str = string_format("!%16g", m_vfr[18][0]); break; + case SONYVU_VF18y: str = string_format("!%16g", m_vfr[18][1]); break; + case SONYVU_VF18z: str = string_format("!%16g", m_vfr[18][2]); break; + case SONYVU_VF18w: str = string_format("!%16g", m_vfr[18][3]); break; + case SONYVU_VF19x: str = string_format("!%16g", m_vfr[19][0]); break; + case SONYVU_VF19y: str = string_format("!%16g", m_vfr[19][1]); break; + case SONYVU_VF19z: str = string_format("!%16g", m_vfr[19][2]); break; + case SONYVU_VF19w: str = string_format("!%16g", m_vfr[19][3]); break; + case SONYVU_VF20x: str = string_format("!%16g", m_vfr[20][0]); break; + case SONYVU_VF20y: str = string_format("!%16g", m_vfr[20][1]); break; + case SONYVU_VF20z: str = string_format("!%16g", m_vfr[20][2]); break; + case SONYVU_VF20w: str = string_format("!%16g", m_vfr[20][3]); break; + case SONYVU_VF21x: str = string_format("!%16g", m_vfr[21][0]); break; + case SONYVU_VF21y: str = string_format("!%16g", m_vfr[21][1]); break; + case SONYVU_VF21z: str = string_format("!%16g", m_vfr[21][2]); break; + case SONYVU_VF21w: str = string_format("!%16g", m_vfr[21][3]); break; + case SONYVU_VF22x: str = string_format("!%16g", m_vfr[22][0]); break; + case SONYVU_VF22y: str = string_format("!%16g", m_vfr[22][1]); break; + case SONYVU_VF22z: str = string_format("!%16g", m_vfr[22][2]); break; + case SONYVU_VF22w: str = string_format("!%16g", m_vfr[22][3]); break; + case SONYVU_VF23x: str = string_format("!%16g", m_vfr[23][0]); break; + case SONYVU_VF23y: str = string_format("!%16g", m_vfr[23][1]); break; + case SONYVU_VF23z: str = string_format("!%16g", m_vfr[23][2]); break; + case SONYVU_VF23w: str = string_format("!%16g", m_vfr[23][3]); break; + case SONYVU_VF24x: str = string_format("!%16g", m_vfr[24][0]); break; + case SONYVU_VF24y: str = string_format("!%16g", m_vfr[24][1]); break; + case SONYVU_VF24z: str = string_format("!%16g", m_vfr[24][2]); break; + case SONYVU_VF24w: str = string_format("!%16g", m_vfr[24][3]); break; + case SONYVU_VF25x: str = string_format("!%16g", m_vfr[25][0]); break; + case SONYVU_VF25y: str = string_format("!%16g", m_vfr[25][1]); break; + case SONYVU_VF25z: str = string_format("!%16g", m_vfr[25][2]); break; + case SONYVU_VF25w: str = string_format("!%16g", m_vfr[25][3]); break; + case SONYVU_VF26x: str = string_format("!%16g", m_vfr[26][0]); break; + case SONYVU_VF26y: str = string_format("!%16g", m_vfr[26][1]); break; + case SONYVU_VF26z: str = string_format("!%16g", m_vfr[26][2]); break; + case SONYVU_VF26w: str = string_format("!%16g", m_vfr[26][3]); break; + case SONYVU_VF27x: str = string_format("!%16g", m_vfr[27][0]); break; + case SONYVU_VF27y: str = string_format("!%16g", m_vfr[27][1]); break; + case SONYVU_VF27z: str = string_format("!%16g", m_vfr[27][2]); break; + case SONYVU_VF27w: str = string_format("!%16g", m_vfr[27][3]); break; + case SONYVU_VF28x: str = string_format("!%16g", m_vfr[28][0]); break; + case SONYVU_VF28y: str = string_format("!%16g", m_vfr[28][1]); break; + case SONYVU_VF28z: str = string_format("!%16g", m_vfr[28][2]); break; + case SONYVU_VF28w: str = string_format("!%16g", m_vfr[28][3]); break; + case SONYVU_VF29x: str = string_format("!%16g", m_vfr[29][0]); break; + case SONYVU_VF29y: str = string_format("!%16g", m_vfr[29][1]); break; + case SONYVU_VF29z: str = string_format("!%16g", m_vfr[29][2]); break; + case SONYVU_VF29w: str = string_format("!%16g", m_vfr[29][3]); break; + case SONYVU_VF30x: str = string_format("!%16g", m_vfr[30][0]); break; + case SONYVU_VF30y: str = string_format("!%16g", m_vfr[30][1]); break; + case SONYVU_VF30z: str = string_format("!%16g", m_vfr[30][2]); break; + case SONYVU_VF30w: str = string_format("!%16g", m_vfr[30][3]); break; + case SONYVU_VF31x: str = string_format("!%16g", m_vfr[31][0]); break; + case SONYVU_VF31y: str = string_format("!%16g", m_vfr[31][1]); break; + case SONYVU_VF31z: str = string_format("!%16g", m_vfr[31][2]); break; + case SONYVU_VF31w: str = string_format("!%16g", m_vfr[31][3]); break; + } +} + +std::unique_ptr sonyvu_device::create_disassembler() +{ + return std::make_unique(); +} + +void sonyvu_device::execute_run() +{ + while (m_icount > 0) + { + if (!m_running) + { + m_icount = 0; + return; + } + + debugger_instruction_hook(m_pc); + + const uint64_t op = m_micro_mem[(m_pc & m_mem_mask) >> 3]; + execute_upper((uint32_t)(op >> 32)); + if (op & OP_UPPER_I) + { + uint32_t lower_op = (uint32_t)op; + m_i = *reinterpret_cast(&lower_op); + } + else + { + execute_lower((uint32_t)op); + } + + m_pc += 8; + m_icount--; + } +} + +void sonyvu_device::execute_upper(const uint32_t op) +{ + switch (op & 0x3f) + { + case 0x00: case 0x01: case 0x02: case 0x03: // ADDbc + printf("Unsupported VU instruction: ADDbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x04: case 0x05: case 0x06: case 0x07: // SUBbc + printf("Unsupported VU instruction: SUBbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x08: case 0x09: case 0x0a: case 0x0b: // MADDbc + printf("Unsupported VU instruction: MADDbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // MSUBbc + printf("Unsupported VU instruction: MSUBbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x10: case 0x11: case 0x12: case 0x13: // MAXbc + printf("Unsupported VU instruction: MAXbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x14: case 0x15: case 0x16: case 0x17: // MINIbc + printf("Unsupported VU instruction: MINIbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x18: case 0x19: case 0x1a: case 0x1b: // MULbc + printf("Unsupported VU instruction: MULbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1c: // MULq + printf("Unsupported VU instruction: MULq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1d: // MAXi + printf("Unsupported VU instruction: MAXi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1e: // MULi + printf("Unsupported VU instruction: MULi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1f: // MINIi + printf("Unsupported VU instruction: MINIi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x20: // ADDq + printf("Unsupported VU instruction: ADDq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x21: // MADDq + printf("Unsupported VU instruction: MADDq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x22: // ADDi + printf("Unsupported VU instruction: ADDi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x23: // MADDi + printf("Unsupported VU instruction: MADDi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x24: // SUBq + printf("Unsupported VU instruction: SUBq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x25: // MSUBq + printf("Unsupported VU instruction: MSUBq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x26: // SUBi + printf("Unsupported VU instruction: SUBi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x27: // MSUBi + printf("Unsupported VU instruction: MSUBi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x28: // ADD + printf("Unsupported VU instruction: ADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x29: // MADD + printf("Unsupported VU instruction: MADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2a: // MUL + printf("Unsupported VU instruction: MUL\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2b: // MAX + printf("Unsupported VU instruction: MAX\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2c: // SUB + printf("Unsupported VU instruction: SUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2d: // MSUB + printf("Unsupported VU instruction: MSUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2e: // OPMSUB + printf("Unsupported VU instruction: OPMSUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2f: // MINI + printf("Unsupported VU instruction: MINI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + { + const uint8_t type2_op = ((op & 0x3c0) >> 4) | (op & 3); + switch (type2_op) + { + case 0x00: case 0x01: case 0x02: case 0x03: // ADDAbc + printf("Unsupported VU instruction: ADDAb\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x04: case 0x05: case 0x06: case 0x07: // SUBAbc + printf("Unsupported VU instruction: SUBAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x08: case 0x09: case 0x0a: case 0x0b: // MADDAbc + printf("Unsupported VU instruction: MADDAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // MSUBAbc + printf("Unsupported VU instruction: MSUBAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x18: case 0x19: case 0x1a: case 0x1b: // MULAbc + printf("Unsupported VU instruction: MULAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x10: // ITOF0 + printf("Unsupported VU instruction: ITOF0\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x11: // ITOF4 + printf("Unsupported VU instruction: ITOF4\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x12: // ITOF12 + printf("Unsupported VU instruction: ITOF12\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x13: // ITOF15 + printf("Unsupported VU instruction: ITOF15\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x14: // FTOI0 + printf("Unsupported VU instruction: FTOI0\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x15: // FTOI4 + printf("Unsupported VU instruction: FTOI4\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x16: // FTOI12 + printf("Unsupported VU instruction: FTOI12\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x17: // FTOI15 + printf("Unsupported VU instruction: FTOI15\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1c: // MULAq + printf("Unsupported VU instruction: MULAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1d: // ABS + printf("Unsupported VU instruction: ABS\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1e: // MULAi + printf("Unsupported VU instruction: MULAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1f: // CLIP + printf("Unsupported VU instruction: CLIP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x20: // ADDAq + printf("Unsupported VU instruction: ADDAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x21: // MADDAq + printf("Unsupported VU instruction: MADDAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x22: // ADDAi + printf("Unsupported VU instruction: ADDAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x23: // MADDAi + printf("Unsupported VU instruction: MADDAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x24: // SUBAq + printf("Unsupported VU instruction: SUBAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x25: // MSUBAq + printf("Unsupported VU instruction: MSUBAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x26: // SUBAi + printf("Unsupported VU instruction: SUBAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x27: // MSUBAi + printf("Unsupported VU instruction: MSUBAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x28: // ADDA + printf("Unsupported VU instruction: ADDA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x29: // MADDA + printf("Unsupported VU instruction: MADDA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2a: // MULA + printf("Unsupported VU instruction: MULA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2c: // SUBA + printf("Unsupported VU instruction: SUBA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2d: // MSUBA + printf("Unsupported VU instruction: MSUBA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2e: // OPMULA + printf("Unsupported VU instruction: OPMULA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2f: // NOP + break; + default: + logerror("%s: %08x: Unknown upper opcode %08x\n", machine().describe_context(), m_pc, op); + break; + } + break; + } + default: + logerror("%s: %08x: Unknown upper opcode %08x\n", machine().describe_context(), m_pc, op); + break; + } +} + +void sonyvu_device::execute_lower(const uint32_t op) +{ + switch ((op >> 25) & 0x7f) + { + case 0x00: // LQ + printf("Unsupported VU instruction: LQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x01: // SQ + printf("Unsupported VU instruction: SQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x04: // ILW + printf("Unsupported VU instruction: ILW\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x05: // ISW + printf("Unsupported VU instruction: ISW\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x08: // IADDIU + printf("Unsupported VU instruction: IADDIU\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x09: // ISUBIU + printf("Unsupported VU instruction: ISUBIU\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x10: // FCEQ + printf("Unsupported VU instruction: FCEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x11: // FCSET + printf("Unsupported VU instruction: FCSET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x12: // FCAND + printf("Unsupported VU instruction: FCAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x13: // FCOR + printf("Unsupported VU instruction: FCOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x14: // FSEQ + printf("Unsupported VU instruction: FSEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x15: // FSSET + printf("Unsupported VU instruction: FSSET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x16: // FSAND + printf("Unsupported VU instruction: FSAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x17: // FSOR + printf("Unsupported VU instruction: FSOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x18: // FMEQ + printf("Unsupported VU instruction: FMEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1a: // FMAND + printf("Unsupported VU instruction: FMAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1b: // FMOR + printf("Unsupported VU instruction: FMOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x1c: // FCGET + printf("Unsupported VU instruction: FCGET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x20: // B + printf("Unsupported VU instruction: B\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x21: // BAL + printf("Unsupported VU instruction: BAL\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x24: // JR + printf("Unsupported VU instruction: JR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x25: // JALR + printf("Unsupported VU instruction: JALR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x28: // IBEQ + printf("Unsupported VU instruction: IBEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x29: // IBNE + printf("Unsupported VU instruction: IBNE\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2c: // IBLTZ + printf("Unsupported VU instruction: IBLTZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2d: // IBGTZ + printf("Unsupported VU instruction: IBGTZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2e: // IBLEZ + printf("Unsupported VU instruction: IBLEZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x2f: // IBGEZ + printf("Unsupported VU instruction: IBGEZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x40: // SPECIAL + { + if ((op & 0x3c) == 0x3c) + { + uint8_t type4_op = ((op & 0x7c0) >> 4) | (op & 3); + switch (type4_op) + { + case 0x30: // MOVE + printf("Unsupported VU instruction: MOVE\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x31: // MR32 + printf("Unsupported VU instruction: MR32\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x34: // LQI + printf("Unsupported VU instruction: LQI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x35: // SQI + printf("Unsupported VU instruction: SQI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x36: // LQD + printf("Unsupported VU instruction: LQD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x37: // SQD + printf("Unsupported VU instruction: SQD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x38: // DIV + printf("Unsupported VU instruction: DIV\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x39: // SQRT + printf("Unsupported VU instruction: SQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3a: // RSQRT + printf("Unsupported VU instruction: RSQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3b: // WAITQ + printf("Unsupported VU instruction: WAITQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3c: // MTIR + printf("Unsupported VU instruction: MTIR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3d: // MFIR + printf("Unsupported VU instruction: MFIR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3e: // ILWR + printf("Unsupported VU instruction: ILWR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x3f: // ISWR + printf("Unsupported VU instruction: ISWR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x40: // RNEXT + printf("Unsupported VU instruction: RNEXT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x41: // RGET + printf("Unsupported VU instruction: RGET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x42: // RINIT + printf("Unsupported VU instruction: RINIT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x43: // RXOR + printf("Unsupported VU instruction: RXOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x64: // MFP + printf("Unsupported VU instruction: MFP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x68: // XTOP + printf("Unsupported VU instruction: XTOP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x69: // XITOP + printf("Unsupported VU instruction: XITOP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x6c: // XGKICK + printf("Unsupported VU instruction: XGKICK\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x70: // ESADD + printf("Unsupported VU instruction: ESADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x71: // ERSADD + printf("Unsupported VU instruction: ERSADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x72: // ELENG + printf("Unsupported VU instruction: ELENG\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x73: // ERLENG + printf("Unsupported VU instruction: ERLENG\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x74: // EATANxy + printf("Unsupported VU instruction: EATANxy\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x75: // EATANxz + printf("Unsupported VU instruction: EATANxz\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x76: // ESUM + printf("Unsupported VU instruction: ESUM\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x78: // ESQRT + printf("Unsupported VU instruction: ESQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x79: // ERSQRT + printf("Unsupported VU instruction: ERSQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x7a: // ERCPR + printf("Unsupported VU instruction: ERCPR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x7b: // WAITP + printf("Unsupported VU instruction: WAITP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x7c: // ESIN + printf("Unsupported VU instruction: ESIN\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x7d: // EATAN + printf("Unsupported VU instruction: EATAN\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x7e: // EEXP + printf("Unsupported VU instruction: EEXP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + default: + logerror("%s: %08x: Unknown lower opcode %08x\n", machine().describe_context(), m_pc, op); + break; + } + break; + } + else + { + switch (op & 0x3f) + { + case 0x30: // IADD + printf("Unsupported VU instruction: IADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x31: // ISUB + printf("Unsupported VU instruction: ISUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x32: // IADDI + printf("Unsupported VU instruction: IADDI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x34: // IAND + printf("Unsupported VU instruction: IAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + case 0x35: // IOR + printf("Unsupported VU instruction: IOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + break; + default: + logerror("%s: %08x: Unknown lower opcode %08x\n", machine().describe_context(), m_pc, op); + break; + } + } + break; + } + default: + logerror("%s: %08x: Unknown lower opcode %08x\n", machine().describe_context(), m_pc, op); + break; + } +} + +void sonyvu0_device::micro_map(address_map &map) +{ + map(0x000, 0xfff).ram().share(m_micro_mem); +} + +void sonyvu0_device::vu_map(address_map &map) +{ + map(0x000, 0xfff).ram().share(m_vu_mem); +} + +void sonyvu0_device::device_start() +{ + sonyvu_device::device_start(); + + save_item(NAME(m_cmsar0)); + save_item(NAME(m_cmsar1)); + save_item(NAME(m_control)); + save_item(NAME(m_vpu_stat)); + + state_add(SONYVU0_CMSAR0, "CMSAR0", m_cmsar0); + state_add(SONYVU0_CMSAR1, "CMSAR1", m_cmsar1); + state_add(SONYVU0_FBRST, "FBRST", m_control); + state_add(SONYVU0_VPU_STAT, "VPU_STAT", m_vpu_stat); +} + +void sonyvu0_device::device_reset() +{ + sonyvu_device::device_reset(); + + m_vu1_regs = m_vu1->vector_regs(); + + m_cmsar0 = 0; + m_control = 0; + m_vpu_stat = 0; + m_cmsar1 = 0; +} + +READ32_MEMBER(sonyvu0_device::vu1_reg_r) +{ + return m_vu1_regs[offset]; +} + +WRITE32_MEMBER(sonyvu0_device::vu1_reg_w) +{ + m_vu1_regs[offset] = data; +} + +void sonyvu1_device::device_start() +{ + sonyvu_device::device_start(); + + save_item(NAME(m_p)); + + state_add(SONYVU1_P, "P", *(uint32_t*)&m_p).formatstr("%17s");; +} + +void sonyvu1_device::device_reset() +{ + sonyvu_device::device_reset(); + + m_p = 0.0f; +} + +void sonyvu1_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + switch (entry.index()) + { + case SONYVU1_P: str = string_format("!%16g", m_p); break; + default: sonyvu_device::state_string_export(entry, str); break; + } +} + +void sonyvu1_device::micro_map(address_map &map) +{ + map(0x000, 0xfff).ram().share(m_micro_mem); +} + +void sonyvu1_device::vu_map(address_map &map) +{ + map(0x000, 0xfff).ram().share(m_vu_mem); +} + +void sonyvu_device::write_vu_mem(uint32_t address, uint32_t data) +{ + m_vu_mem[(address & m_mem_mask) >> 2] = data; +} + +void sonyvu_device::write_micro_mem(uint32_t address, uint64_t data) +{ + m_micro_mem[(address & m_mem_mask) >> 3] = data; +} diff --git a/src/devices/cpu/mips/sonyvu.h b/src/devices/cpu/mips/sonyvu.h new file mode 100644 index 00000000000..17536c24fe5 --- /dev/null +++ b/src/devices/cpu/mips/sonyvu.h @@ -0,0 +1,209 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 Vector Unit device skeleton +* +* To Do: +* Everything +* +*/ + +#ifndef MAME_CPU_MIPS_SONYVU_H +#define MAME_CPU_MIPS_SONYVU_H + +#pragma once + +enum +{ + SONYVU_TPC, + SONYVU_SF, + SONYVU_MF, + SONYVU_CF, + SONYVU_R, + SONYVU_I, + SONYVU_Q, + SONYVU_ACCx, SONYVU_ACCy, SONYVU_ACCz, SONYVU_ACCw, + SONYVU_VF00x, SONYVU_VF00y, SONYVU_VF00z, SONYVU_VF00w, + SONYVU_VF01x, SONYVU_VF01y, SONYVU_VF01z, SONYVU_VF01w, + SONYVU_VF02x, SONYVU_VF02y, SONYVU_VF02z, SONYVU_VF02w, + SONYVU_VF03x, SONYVU_VF03y, SONYVU_VF03z, SONYVU_VF03w, + SONYVU_VF04x, SONYVU_VF04y, SONYVU_VF04z, SONYVU_VF04w, + SONYVU_VF05x, SONYVU_VF05y, SONYVU_VF05z, SONYVU_VF05w, + SONYVU_VF06x, SONYVU_VF06y, SONYVU_VF06z, SONYVU_VF06w, + SONYVU_VF07x, SONYVU_VF07y, SONYVU_VF07z, SONYVU_VF07w, + SONYVU_VF08x, SONYVU_VF08y, SONYVU_VF08z, SONYVU_VF08w, + SONYVU_VF09x, SONYVU_VF09y, SONYVU_VF09z, SONYVU_VF09w, + SONYVU_VF10x, SONYVU_VF10y, SONYVU_VF10z, SONYVU_VF10w, + SONYVU_VF11x, SONYVU_VF11y, SONYVU_VF11z, SONYVU_VF11w, + SONYVU_VF12x, SONYVU_VF12y, SONYVU_VF12z, SONYVU_VF12w, + SONYVU_VF13x, SONYVU_VF13y, SONYVU_VF13z, SONYVU_VF13w, + SONYVU_VF14x, SONYVU_VF14y, SONYVU_VF14z, SONYVU_VF14w, + SONYVU_VF15x, SONYVU_VF15y, SONYVU_VF15z, SONYVU_VF15w, + SONYVU_VF16x, SONYVU_VF16y, SONYVU_VF16z, SONYVU_VF16w, + SONYVU_VF17x, SONYVU_VF17y, SONYVU_VF17z, SONYVU_VF17w, + SONYVU_VF18x, SONYVU_VF18y, SONYVU_VF18z, SONYVU_VF18w, + SONYVU_VF19x, SONYVU_VF19y, SONYVU_VF19z, SONYVU_VF19w, + SONYVU_VF20x, SONYVU_VF20y, SONYVU_VF20z, SONYVU_VF20w, + SONYVU_VF21x, SONYVU_VF21y, SONYVU_VF21z, SONYVU_VF21w, + SONYVU_VF22x, SONYVU_VF22y, SONYVU_VF22z, SONYVU_VF22w, + SONYVU_VF23x, SONYVU_VF23y, SONYVU_VF23z, SONYVU_VF23w, + SONYVU_VF24x, SONYVU_VF24y, SONYVU_VF24z, SONYVU_VF24w, + SONYVU_VF25x, SONYVU_VF25y, SONYVU_VF25z, SONYVU_VF25w, + SONYVU_VF26x, SONYVU_VF26y, SONYVU_VF26z, SONYVU_VF26w, + SONYVU_VF27x, SONYVU_VF27y, SONYVU_VF27z, SONYVU_VF27w, + SONYVU_VF28x, SONYVU_VF28y, SONYVU_VF28z, SONYVU_VF28w, + SONYVU_VF29x, SONYVU_VF29y, SONYVU_VF29z, SONYVU_VF29w, + SONYVU_VF30x, SONYVU_VF30y, SONYVU_VF30z, SONYVU_VF30w, + SONYVU_VF31x, SONYVU_VF31y, SONYVU_VF31z, SONYVU_VF31w, + SONYVU_VI00, SONYVU_VI01, SONYVU_VI02, SONYVU_VI03, + SONYVU_VI04, SONYVU_VI05, SONYVU_VI06, SONYVU_VI07, + SONYVU_VI08, SONYVU_VI09, SONYVU_VI10, SONYVU_VI11, + SONYVU_VI12, SONYVU_VI13, SONYVU_VI14, SONYVU_VI15, + + SONYVU0_VPU_STAT, + SONYVU0_FBRST, + SONYVU0_CMSAR0, + SONYVU0_CMSAR1, + + SONYVU1_P = SONYVU0_VPU_STAT +}; + +class sonyvu_device : public cpu_device +{ +public: + // construction/destruction + virtual ~sonyvu_device() {} + + void write_vu_mem(uint32_t address, uint32_t data); + void write_micro_mem(uint32_t address, uint64_t data); + float* vector_regs() { return m_v; } + +protected: + enum chip_type + { + CHIP_TYPE_VU0, + CHIP_TYPE_VU1, + }; + + sonyvu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor micro_cons, address_map_constructor vu_cons, chip_type chiptype, uint32_t mem_size); + + enum : uint64_t + { + OP_UPPER_I = 0x8000000000000000ULL, + OP_UPPER_E = 0x4000000000000000ULL, + OP_UPPER_M = 0x2000000000000000ULL, + OP_UPPER_D = 0x1000000000000000ULL, + OP_UPPER_T = 0x0800000000000000ULL + }; + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual uint32_t execute_min_cycles() const override { return 1; } + virtual uint32_t execute_max_cycles() const override { return 1; } + virtual uint32_t execute_input_lines() const override { return 0; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override { } + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_state_interface overrides + virtual void state_import(const device_state_entry &entry) override; + virtual void state_export(const device_state_entry &entry) override; + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + // device_disasm_interface overrides + virtual std::unique_ptr create_disassembler() override; + + void execute_upper(const uint32_t op); + void execute_lower(const uint32_t op); + + // address spaces + const address_space_config m_micro_config; + const address_space_config m_vu_config; + address_space *m_micro_space; + address_space *m_vu_space; + + // core registers + uint32_t m_mem_size; + uint32_t m_mem_mask; + required_shared_ptr m_micro_mem; + required_shared_ptr m_vu_mem; + float* m_vfmem; + uint32_t* m_vimem; + + float m_vfr[32][4]; // 0..3 = x..w + uint32_t m_vcr[16]; + float m_acc[4]; + + float* m_v; + + uint32_t m_status_flag; + uint32_t m_mac_flag; + uint32_t m_clip_flag; + uint32_t m_r; + float m_i; + float m_q; + + uint32_t m_pc; + bool m_running; + + int m_icount; +}; + +class sonyvu1_device : public sonyvu_device +{ +public: + sonyvu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + void micro_map(address_map &map); + void vu_map(address_map &map); + + float m_p; +}; + +class sonyvu0_device : public sonyvu_device +{ +public: + template + sonyvu0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&vu1_tag) + : sonyvu0_device(mconfig, tag, owner, clock) + { + m_vu1.set_tag(std::forward(vu1_tag)); + } + + sonyvu0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + void micro_map(address_map &map); + void vu_map(address_map &map); + + DECLARE_READ32_MEMBER(vu1_reg_r); + DECLARE_WRITE32_MEMBER(vu1_reg_w); + + required_device m_vu1; + + float* m_vu1_regs; + uint32_t m_control; + uint32_t m_vpu_stat; + uint32_t m_cmsar0; + uint32_t m_cmsar1; +}; + +DECLARE_DEVICE_TYPE(SONYVU1, sonyvu1_device) +DECLARE_DEVICE_TYPE(SONYVU0, sonyvu0_device) + +#endif // MAME_CPU_MIPS_SONYVU_H \ No newline at end of file diff --git a/src/devices/cpu/mips/vudasm.cpp b/src/devices/cpu/mips/vudasm.cpp new file mode 100644 index 00000000000..da376798d92 --- /dev/null +++ b/src/devices/cpu/mips/vudasm.cpp @@ -0,0 +1,461 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 Vector Unit disassembler +* +*/ + +#include "emu.h" +#include "vudasm.h" + +/*static*/ const char* sonyvu_disassembler::DEST_STR[] = +{ + " ", "w ", "z ", "zw ", "y ", "yw ", "yz ", "yzw ", + "x ", "xw ", "xz ", "xzw ", "xy ", "xyw ", "xyz ", "xyzw" +}; + +/*static*/ const char* sonyvu_disassembler::DEST_COMMA_STR[] = +{ + ",", "w,", "z,", "zw,", "y,", "yw,", "yz,", "yzw,", + "x,", "xw,", "xz,", "xzw,", "xy,", "xyw,", "xyz,", "xyzw," +}; + +/*static*/ const char* sonyvu_disassembler::BC_STR[] = { "x", "y", "z", "w" }; +/*static*/ const char* sonyvu_disassembler::BC_COMMA_STR[] = { "x,", "y,", "z,", "w," }; + +/*static*/ const char* sonyvu_disassembler::VFREG[] = +{ + "$vf00", "$vf01", "$vf02", "$vf03", "$vf04", "$vf05", "$vf06", "$vf07", + "$vf08", "$vf09", "$vf10", "$vf11", "$vf12", "$vf13", "$vf14", "$vf15", + "$vf16", "$vf17", "$vf18", "$vf19", "$vf20", "$vf21", "$vf22", "$vf23", + "$vf24", "$vf25", "$vf26", "$vf27", "$vf28", "$vf29", "$vf30", "$vf31" +}; + +/*static*/ const char* sonyvu_disassembler::VIREG[] = +{ + "$vi00", "$vi01", "$vi02", "$vi03", "$vi04", "$vi05", "$vi06", "$vi07", + "$vi08", "$vi09", "$vi10", "$vi11", "$vi12", "$vi13", "$vi14", "$vi15", + "STATUS", "MACF", "CLIPF", "res19", "R", "I", "Q", "res23", + "res24", "res25", "TPC", "CMSAR0", "FBRST", "VPU_STAT", "res30", "CMSAR1" +}; + +offs_t sonyvu_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + uint64_t op = opcodes.r64(pc & ~7); + if (pc & 4) + { + if (op & 0x8000000000000000ULL) + { + util::stream_format(stream, "loi %f", *reinterpret_cast(&op)); + } + else + { + dasm_lower(pc, (uint32_t)op, stream); + } + } + else + { + dasm_upper(pc, (uint32_t)(op >> 32), stream); + } + return 4 | SUPPORTED; +} + +void sonyvu_disassembler::dasm_upper(uint32_t pc, uint32_t op, std::ostream &stream) +{ + const int rd = (op >> 6) & 31; + const int rs = (op >> 11) & 31; + const int rt = (op >> 16) & 31; + const char* bc = BC_STR[op & 3]; + const char* dest = DEST_STR[(op >> 21) & 15]; + const char* destc = DEST_COMMA_STR[(op >> 21) & 15]; + + switch (op & 0x3f) + { + case 0x08: case 0x09: case 0x0a: case 0x0b: + util::stream_format(stream, "madd%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + util::stream_format(stream, "msub%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x10: case 0x11: case 0x12: case 0x13: + util::stream_format(stream, "max%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x14: case 0x15: case 0x16: case 0x17: + util::stream_format(stream, "mini%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x18: case 0x19: case 0x1a: case 0x1b: + util::stream_format(stream, "mul%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x1c: util::stream_format(stream, "mulq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x1d: util::stream_format(stream, "maxi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x1e: util::stream_format(stream, "muli.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x1f: util::stream_format(stream, "minii.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x20: util::stream_format(stream, "addq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x21: util::stream_format(stream, "maddq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x22: util::stream_format(stream, "addi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x23: util::stream_format(stream, "maddi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x24: util::stream_format(stream, "subq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x25: util::stream_format(stream, "msubq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x26: util::stream_format(stream, "subi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x27: util::stream_format(stream, "msubi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break; + case 0x28: util::stream_format(stream, "add.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x29: util::stream_format(stream, "madd.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2a: util::stream_format(stream, "mul.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2b: util::stream_format(stream, "max.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2c: util::stream_format(stream, "sub.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2d: util::stream_format(stream, "msub.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2e: util::stream_format(stream, "opmsub.xyz %sxyz, %sxyz, %sxyz", VFREG[rd], VFREG[rs], VFREG[rt]); break; + case 0x2f: util::stream_format(stream, "mini.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + { + const uint8_t type2_op = ((op & 0x3c0) >> 4) | (op & 3); + switch (type2_op) + { + case 0x00: case 0x01: case 0x02: case 0x03: + util::stream_format(stream, "adda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x04: case 0x05: case 0x06: case 0x07: + util::stream_format(stream, "suba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x08: case 0x09: case 0x0a: case 0x0b: + util::stream_format(stream, "madda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + util::stream_format(stream, "msuba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x10: util::stream_format(stream, "itof0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x11: util::stream_format(stream, "itof4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x12: util::stream_format(stream, "itof12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x13: util::stream_format(stream, "itof15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x14: util::stream_format(stream, "ftoi0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x15: util::stream_format(stream, "ftoi4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x16: util::stream_format(stream, "ftoi12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x17: util::stream_format(stream, "ftoi15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x18: case 0x19: case 0x1a: case 0x1b: + util::stream_format(stream, "mula%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break; + case 0x1c: util::stream_format(stream, "mulaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break; + case 0x1d: util::stream_format(stream, "abs.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break; + case 0x1e: util::stream_format(stream, "mulai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break; + case 0x1f: util::stream_format(stream, "clipw.xyz %sxyz, %sw", VFREG[rs], VFREG[rt]); break; + case 0x20: util::stream_format(stream, "addaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break; + case 0x21: util::stream_format(stream, "maddaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break; + case 0x22: util::stream_format(stream, "addai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break; + case 0x23: util::stream_format(stream, "maddai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break; + case 0x24: util::stream_format(stream, "subaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break; + case 0x25: util::stream_format(stream, "msubaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break; + case 0x26: util::stream_format(stream, "subai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break; + case 0x27: util::stream_format(stream, "msubai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break; + case 0x28: util::stream_format(stream, "adda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x29: util::stream_format(stream, "madda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2a: util::stream_format(stream, "mula.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break; + // 2b? + case 0x2c: util::stream_format(stream, "suba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2d: util::stream_format(stream, "msuba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break; + case 0x2e: util::stream_format(stream, "opmula.xyz ACCxyz, %sxyz, %sxyz", VFREG[rs], VFREG[rt]); break; + case 0x2f: util::stream_format(stream, "nop"); break; + default: + util::stream_format(stream, "invalid"); + break; + } + break; + } + default: + util::stream_format(stream, "invalid"); + break; + } +} + +void sonyvu_disassembler::dasm_lower(uint32_t pc, uint32_t op, std::ostream &stream) +{ + const int rd = (op >> 6) & 31; + const int rs = (op >> 11) & 31; + const int rt = (op >> 16) & 31; + const char* dest = DEST_STR[(op >> 21) & 15]; + const char* destc = DEST_COMMA_STR[(op >> 21) & 15]; + const char* ftf = BC_STR[(op >> 23) & 3]; + const char* fsf = BC_STR[(op >> 21) & 3]; + const char* fsfc = BC_COMMA_STR[(op >> 21) & 3]; + + switch ((op >> 25) & 0x7f) + { + case 0x00: // LQ + util::stream_format(stream, "lq.%s %s%s %s(%s)", dest, VFREG[rt], destc, signed_11bit(op), VIREG[rs]); + break; + case 0x01: // SQ + util::stream_format(stream, "sq.%s %s%s %s(%s)", dest, VFREG[rs], destc, signed_11bit(op), VIREG[rt]); + break; + case 0x04: // ILW + util::stream_format(stream, "ilw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest); + break; + case 0x05: // ISW + util::stream_format(stream, "isw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest); + break; + case 0x08: // IADDIU + util::stream_format(stream, "iaddiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op)); + break; + case 0x09: // ISUBIU + util::stream_format(stream, "isubiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op)); + break; + case 0x10: // FCEQ + util::stream_format(stream, "fceq $vi01, %06x", op & 0xffffff); + break; + case 0x11: // FCSET + util::stream_format(stream, "fcset %06x", op & 0xffffff); + break; + case 0x12: // FCAND + util::stream_format(stream, "fcand $vi01, %06x", op & 0xffffff); + break; + case 0x13: // FCOR + util::stream_format(stream, "fcor $vi01, %06x", op & 0xffffff); + break; + case 0x14: // FSEQ + util::stream_format(stream, "fseq %s, %s", VIREG[rt], op & 0xfff); + break; + case 0x15: // FSSET + util::stream_format(stream, "fsset %03x", op & 0xfff); + break; + case 0x16: // FSAND + util::stream_format(stream, "fsand %s, %s", VIREG[rt], op & 0xfff); + break; + case 0x17: // FSOR + util::stream_format(stream, "fsor %s, %s", VIREG[rt], op & 0xfff); + break; + case 0x18: // FMEQ + util::stream_format(stream, "fmeq %s, %s", VIREG[rt], VIREG[rs]); + break; + case 0x1a: // FMAND + util::stream_format(stream, "fmand %s, %s", VIREG[rt], VIREG[rs]); + break; + case 0x1b: // FMOR + util::stream_format(stream, "fmor %s, %s", VIREG[rt], VIREG[rs]); + break; + case 0x1c: // FCGET + util::stream_format(stream, "fcget %s", VIREG[rt]); + break; + case 0x20: // B + util::stream_format(stream, "b %s", signed_11bit_x8(op)); + break; + case 0x21: // BAL + util::stream_format(stream, "bal %s, %s", VIREG[rt], signed_11bit_x8(op)); + break; + case 0x24: // JR + util::stream_format(stream, "jr %s", VIREG[rs]); + break; + case 0x25: // JALR + util::stream_format(stream, "jalr %s, %s", VIREG[rt], VIREG[rs]); + break; + case 0x28: // IBEQ + util::stream_format(stream, "ibeq %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op)); + break; + case 0x29: // IBNE + util::stream_format(stream, "ibne %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op)); + break; + case 0x2c: // IBLTZ + util::stream_format(stream, "ibltz %s, %s", VIREG[rs], signed_11bit_x8(op)); + break; + case 0x2d: // IBGTZ + util::stream_format(stream, "ibgtz %s, %s", VIREG[rs], signed_11bit_x8(op)); + break; + case 0x2e: // IBLEZ + util::stream_format(stream, "iblez %s, %s", VIREG[rs], signed_11bit_x8(op)); + break; + case 0x2f: // IBGEZ + util::stream_format(stream, "ibgez %s, %s", VIREG[rs], signed_11bit_x8(op)); + break; + case 0x40: // SPECIAL + { + if ((op & 0x3c) == 0x3c) + { + uint8_t type4_op = ((op & 0x7c0) >> 4) | (op & 3); + switch (type4_op) + { + case 0x30: // MOVE + util::stream_format(stream, "move.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); + break; + case 0x31: // MR32 + util::stream_format(stream, "mr32.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); + break; + case 0x34: // LQI + util::stream_format(stream, "lqi.%s %s%s (%s++)", dest, VFREG[rt], destc, VIREG[rs]); + break; + case 0x35: // SQI + util::stream_format(stream, "sqi.%s %s%s (%s++)", dest, VFREG[rs], destc, VIREG[rt]); + break; + case 0x36: // LQD + util::stream_format(stream, "lqi.%s %s%s (--%s)", dest, VFREG[rt], destc, VIREG[rs]); + break; + case 0x37: // SQD + util::stream_format(stream, "sqi.%s %s%s (--%s)", dest, VFREG[rs], destc, VIREG[rt]); + break; + case 0x38: // DIV + util::stream_format(stream, "div Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf); + break; + case 0x39: // SQRT + util::stream_format(stream, "sqrt Q, %s%s", dest, VFREG[rt], ftf); + break; + case 0x3a: // RSQRT + util::stream_format(stream, "rsqrt Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf); + break; + case 0x3b: // WAITQ + util::stream_format(stream, "waitq"); + break; + case 0x3c: // MTIR + util::stream_format(stream, "mtir %s, %s%s", VIREG[rt], VFREG[rs], fsf); + break; + case 0x3d: // MFIR + util::stream_format(stream, "mtir.%s %s%s %s", dest, VFREG[rt], destc, VIREG[rs] ); + break; + case 0x3e: // ILWR + util::stream_format(stream, "ilwr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest); + break; + case 0x3f: // ISWR + util::stream_format(stream, "iswr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest); + break; + case 0x40: // RNEXT + util::stream_format(stream, "rnext.%s %s%s R", dest, VFREG[rt], destc); + break; + case 0x41: // RGET + util::stream_format(stream, "rget.%s %s%s R", dest, VFREG[rt], destc); + break; + case 0x42: // RINIT + util::stream_format(stream, "rinit R, %s%s", dest, VFREG[rs], dest); + break; + case 0x43: // RXOR + util::stream_format(stream, "rxor R, %s%s", dest, VFREG[rs], dest); + break; + case 0x64: // MFP + util::stream_format(stream, "mfp.%s %s%s P", dest, VFREG[rt], destc); + break; + case 0x68: // XTOP + util::stream_format(stream, "xtop %s", VIREG[rt]); + break; + case 0x69: // XITOP + util::stream_format(stream, "xitop %s", VIREG[rt]); + break; + case 0x6c: // XGKICK + util::stream_format(stream, "xgkick %s", VIREG[rs]); + break; + case 0x70: // ESADD + util::stream_format(stream, "esadd P, %s", VFREG[rs]); + break; + case 0x71: // ERSADD + util::stream_format(stream, "ersadd P, %s", VFREG[rs]); + break; + case 0x72: // ELENG + util::stream_format(stream, "eleng P, %s", VFREG[rs]); + break; + case 0x73: // ERLENG + util::stream_format(stream, "erleng P, %s", VFREG[rs]); + break; + case 0x74: // EATANxy + util::stream_format(stream, "eatanxy P, %s", VFREG[rs]); + break; + case 0x75: // EATANxz + util::stream_format(stream, "eatanxz P, %s", VFREG[rs]); + break; + case 0x76: // ESUM + util::stream_format(stream, "esum P, %s", VFREG[rs]); + break; + case 0x78: // ESQRT + util::stream_format(stream, "esqrt P, %s%s", VFREG[rs], fsf); + break; + case 0x79: // ERSQRT + util::stream_format(stream, "ersqrt P, %s%s", VFREG[rs], fsf); + break; + case 0x7a: // ERCPR + util::stream_format(stream, "ercpr P, %s%s", VFREG[rs], fsf); + break; + case 0x7b: // WAITP + util::stream_format(stream, "waitp"); + break; + case 0x7c: // ESIN + util::stream_format(stream, "esin P, %s%s", VFREG[rs], fsf); + break; + case 0x7d: // EATAN + util::stream_format(stream, "eatan P, %s%s", VFREG[rs], fsf); + break; + case 0x7e: // EEXP + util::stream_format(stream, "eexp P, %s%s", VFREG[rs], fsf); + break; + default: + util::stream_format(stream, "invalid"); + break; + } + break; + } + else + { + switch (op & 0x3f) + { + case 0x30: // IADD + util::stream_format(stream, "iadd %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]); + break; + case 0x31: // ISUB + util::stream_format(stream, "isub %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]); + break; + case 0x32: // IADDI + util::stream_format(stream, "iaddi %s, %s, %s", VIREG[rt], VIREG[rs], signed_5bit(op)); + break; + case 0x34: // IAND + util::stream_format(stream, "iand %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]); + break; + case 0x35: // IOR + util::stream_format(stream, "ior %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]); + break; + default: + util::stream_format(stream, "invalid"); + break; + } + } + break; + } + default: + util::stream_format(stream, "invalid"); + break; + } +} + +uint32_t sonyvu_disassembler::opcode_alignment() const +{ + return 4; +} + +std::string sonyvu_disassembler::signed_5bit(uint16_t val) +{ + int16_t sval = (int32_t)val; + sval <<= 11; + sval >>= 11; + + if (sval < 0) + return util::string_format("-$%x", -sval); + else + return util::string_format("$%x", sval); +} + +std::string sonyvu_disassembler::signed_11bit(uint16_t val) +{ + int16_t sval = (int32_t)val; + sval <<= 5; + sval >>= 5; + + if (sval < 0) + return util::string_format("-$%x", -sval); + else + return util::string_format("$%x", sval); +} + +std::string sonyvu_disassembler::signed_11bit_x8(uint16_t val) +{ + int16_t sval = (int32_t)val; + sval <<= 5; + sval >>= 5; + + if (sval < 0) + return util::string_format("-$%x", -sval * 8); + else + return util::string_format("$%x", sval * 8); +} + +std::string sonyvu_disassembler::signed_15bit(uint16_t val) +{ + int16_t sval = (int32_t)val; + sval <<= 1; + sval >>= 1; + + if (sval < 0) + return util::string_format("-$%x", -sval); + else + return util::string_format("$%x", sval); +} diff --git a/src/devices/cpu/mips/vudasm.h b/src/devices/cpu/mips/vudasm.h new file mode 100644 index 00000000000..0ff2ad67adc --- /dev/null +++ b/src/devices/cpu/mips/vudasm.h @@ -0,0 +1,39 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/****************************************************************************** +* +* Sony Playstation 2 Vector Unit disassembler +* +*/ + +#ifndef MAME_CPU_MIPS_VUDASM_H +#define MAME_CPU_MIPS_VUDASM_H + +#pragma once + +class sonyvu_disassembler : public util::disasm_interface +{ +public: + sonyvu_disassembler() = default; + virtual ~sonyvu_disassembler() = default; + + virtual u32 opcode_alignment() const override; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + +private: + void dasm_upper(uint32_t pc, uint32_t op, std::ostream &stream); + void dasm_lower(uint32_t pc, uint32_t op, std::ostream &stream); + std::string signed_5bit(uint16_t val); + std::string signed_11bit(uint16_t val); + std::string signed_11bit_x8(uint16_t val); + std::string signed_15bit(uint16_t val); + + static const char * DEST_STR[16]; + static const char * DEST_COMMA_STR[16]; + static const char * BC_STR[16]; + static const char * BC_COMMA_STR[16]; + static const char * VFREG[32]; + static const char * VIREG[32]; +}; + +#endif // MAME_CPU_MIPS_VUDASM_H \ No newline at end of file diff --git a/src/mame/drivers/ps2sony.cpp b/src/mame/drivers/ps2sony.cpp index 826b629d938..d6a11058e40 100644 --- a/src/mame/drivers/ps2sony.cpp +++ b/src/mame/drivers/ps2sony.cpp @@ -162,6 +162,7 @@ iLinkSGUID=0x-------- #include "cpu/mips/mips3.h" #include "cpu/mips/r3000.h" +#include "cpu/mips/sonyvu.h" #include "machine/iopcdvd.h" #include "machine/iopdma.h" @@ -203,6 +204,8 @@ public: , m_gif(*this, "gif") , m_gs(*this, "gs") , m_vif1(*this, "vif1") + , m_vu0(*this, "vu0") + , m_vu1(*this, "vu1") , m_pad(*this, "pad%u", 0U) , m_mc(*this, "mc") , m_screen(*this, "screen") @@ -266,6 +269,8 @@ protected: required_device m_gif; required_device m_gs; required_device m_vif1; + required_device m_vu0; + required_device m_vu1; required_device_array m_pad; required_device m_mc; required_device m_screen; @@ -550,7 +555,7 @@ void ps2sony_state::machine_reset() memset(m_ipu_out_fifo, 0, sizeof(uint64_t)*0x1000); m_ipu_out_fifo_index = 0; - m_vblank_timer->adjust(m_screen->time_until_pos(480), 1); + m_vblank_timer->adjust(m_screen->time_until_pos(0), 1); } TIMER_CALLBACK_MEMBER(ps2sony_state::vblank) @@ -558,17 +563,17 @@ TIMER_CALLBACK_MEMBER(ps2sony_state::vblank) if (param) { // VBlank enter - m_intc->raise_interrupt(ps2_intc_device::INT_VB_ON); m_iop_intc->raise_interrupt(iop_intc_device::INT_VB_ON); - m_vblank_timer->adjust(m_screen->time_until_pos(0), 0); + m_intc->raise_interrupt(ps2_intc_device::INT_VB_ON); + m_vblank_timer->adjust(m_screen->time_until_pos(32), 0); m_gs->vblank_start(); } else { // VBlank exit - //m_intc->raise_interrupt(ps2_intc_device::INT_VB_OFF); m_iop_intc->raise_interrupt(iop_intc_device::INT_VB_OFF); - m_vblank_timer->adjust(m_screen->time_until_pos(480), 1); + m_intc->raise_interrupt(ps2_intc_device::INT_VB_OFF); + m_vblank_timer->adjust(m_screen->time_until_pos(0), 1); m_gs->vblank_end(); } } @@ -734,21 +739,24 @@ static INPUT_PORTS_START( ps2sony ) INPUT_PORTS_END MACHINE_CONFIG_START(ps2sony_state::ps2sony) - MCFG_DEVICE_ADD(m_maincpu, R5900LE, 294'912'000) + MCFG_DEVICE_ADD(m_maincpu, R5900LE, 294'912'000, m_vu0) MCFG_CPU_FORCE_NO_DRC() MCFG_MIPS3_ICACHE_SIZE(16384) MCFG_MIPS3_DCACHE_SIZE(16384) MCFG_DEVICE_PROGRAM_MAP(mem_map) - MCFG_DEVICE_ADD(m_vif1, SONYPS2_VIF1, 294912000/2, m_gif) + MCFG_DEVICE_ADD(m_vu0, SONYVU0, 294'912'000, m_vu1) + MCFG_DEVICE_ADD(m_vu1, SONYVU1, 294'912'000) + + MCFG_DEVICE_ADD(m_vif1, SONYPS2_VIF1, 294912000/2, m_gif, m_vu1) MCFG_DEVICE_ADD(m_timer[0], SONYPS2_TIMER, 294912000/2, true) MCFG_DEVICE_ADD(m_timer[1], SONYPS2_TIMER, 294912000/2, true) MCFG_DEVICE_ADD(m_timer[2], SONYPS2_TIMER, 294912000/2, false) MCFG_DEVICE_ADD(m_timer[3], SONYPS2_TIMER, 294912000/2, false) - MCFG_DEVICE_ADD(m_gs, SONYPS2_GS, 294912000/2) MCFG_DEVICE_ADD(m_intc, SONYPS2_INTC, m_maincpu) + MCFG_DEVICE_ADD(m_gs, SONYPS2_GS, 294912000/2, m_intc) MCFG_DEVICE_ADD(m_dmac, SONYPS2_DMAC, 294912000/2, m_maincpu, m_ram, m_sif, m_gif, m_vif1) MCFG_DEVICE_ADD(m_sif, SONYPS2_SIF, m_intc) MCFG_DEVICE_ADD(m_gif, SONYPS2_GIF, m_gs) @@ -776,8 +784,8 @@ MACHINE_CONFIG_START(ps2sony_state::ps2sony) MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(60) MCFG_SCREEN_UPDATE_DRIVER(ps2sony_state, screen_update) - MCFG_SCREEN_SIZE(640, 525) - MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479) + MCFG_SCREEN_SIZE(640, 256) + MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 223) MCFG_PALETTE_ADD("palette", 65536) MACHINE_CONFIG_END diff --git a/src/mame/machine/iopcdvd.cpp b/src/mame/machine/iopcdvd.cpp index ff3ce8ac021..16c8eb25973 100644 --- a/src/mame/machine/iopcdvd.cpp +++ b/src/mame/machine/iopcdvd.cpp @@ -11,7 +11,7 @@ #include "iopcdvd.h" -/*static*/ const size_t iop_cdvd_device::BUFFER_SIZE = 2048; // Total guess +/*static*/ const size_t iop_cdvd_device::BUFFER_SIZE = 16; // Total guess DEFINE_DEVICE_TYPE(SONYIOP_CDVD, iop_cdvd_device, "iopcdvd", "Playstation 2 disc controller") @@ -23,23 +23,31 @@ iop_cdvd_device::iop_cdvd_device(const machine_config &mconfig, const char *tag, void iop_cdvd_device::device_start() { - m_out_buf = std::make_unique(BUFFER_SIZE); - - save_item(NAME(m_status_0x05)); - save_item(NAME(m_status_0x17)); - save_item(NAME(m_command)); - save_item(NAME(m_out_count)); - save_item(NAME(m_out_curr)); + save_item(NAME(m_channel[0].m_buffer)); + save_item(NAME(m_channel[0].m_curr)); + save_item(NAME(m_channel[0].m_end)); + save_item(NAME(m_channel[0].m_status)); + save_item(NAME(m_channel[0].m_command)); + save_item(NAME(m_channel[1].m_buffer)); + save_item(NAME(m_channel[1].m_curr)); + save_item(NAME(m_channel[1].m_end)); + save_item(NAME(m_channel[1].m_status)); + save_item(NAME(m_channel[1].m_command)); } void iop_cdvd_device::device_reset() { - m_status_0x05 = CDVD_STATUS_BOOT; - m_status_0x17 = CDVD_STATUS_IDLE; - m_command = 0; - memset(&m_out_buf[0], 0, BUFFER_SIZE); - m_out_count = 0; - m_out_curr = 0; + for (offs_t i = 0; i < 2; i++) + { + memset(m_channel[i].m_buffer, 0, BUFFER_SIZE); + m_channel[i].m_curr = 0; + m_channel[i].m_end = 0; + m_channel[i].m_status = 0; + m_channel[i].m_command = 0; + } + + m_channel[0].m_status |= CDVD_STATUS_IDLE; + m_channel[1].m_status |= CDVD_STATUS_IDLE; } READ8_MEMBER(iop_cdvd_device::read) @@ -47,31 +55,25 @@ READ8_MEMBER(iop_cdvd_device::read) uint8_t ret = 0; switch (offset) { + case 0x04: + ret = m_channel[CHAN_SERVO].m_command; + logerror("%s: cdvd_r: Servo Command (%02x)\n", machine().describe_context(), ret); + break; case 0x05: - ret = m_status_0x05; - logerror("%s: cdvd_r: Status 0x05? (%02x)\n", machine().describe_context(), ret); + ret = m_channel[CHAN_SERVO].m_status; + logerror("%s: cdvd_r: Servo Status (%02x)\n", machine().describe_context(), ret); break; case 0x16: - ret = m_command; - logerror("%s: cdvd_r: Command? (%02x)\n", machine().describe_context(), ret); + ret = m_channel[CHAN_DATA].m_command; + logerror("%s: cdvd_r: Data Command (%02x)\n", machine().describe_context(), ret); break; case 0x17: - ret = m_status_0x17; - logerror("%s: cdvd_r: Status 0x17? (%02x)\n", machine().describe_context(), ret); + ret = m_channel[CHAN_DATA].m_status; + logerror("%s: cdvd_r: Data Status (%02x)\n", machine().describe_context(), ret); break; case 0x18: - ret = m_out_buf[m_out_curr]; - if (m_out_curr < m_out_count) - { - m_out_curr++; - if (m_out_curr == m_out_count) - { - m_status_0x17 |= CDVD_STATUS_IDLE; - m_out_count = 0; - m_out_curr = 0; - } - } - logerror("%s: cdvd_r: Command Output (%02x) (%d left)\n", machine().describe_context(), ret, m_out_count - m_out_curr); + ret = data_fifo_pop(); + logerror("%s: cdvd_r: Data FIFO Out (%02x) (%d left)\n", machine().describe_context(), ret, m_channel[CHAN_DATA].m_end - m_channel[CHAN_DATA].m_curr); break; default: logerror("%s: cdvd_r: Unknown read: %08x\n", machine().describe_context(), 0x1f402000 + offset); @@ -80,43 +82,87 @@ READ8_MEMBER(iop_cdvd_device::read) return ret; } +void iop_cdvd_device::data_fifo_push(uint8_t data) +{ + drive_channel_t &channel = m_channel[CHAN_DATA]; + if (channel.m_end >= BUFFER_SIZE) + { + return; + } + + channel.m_buffer[channel.m_end++] = data; +} + +uint8_t iop_cdvd_device::data_fifo_pop() +{ + drive_channel_t &channel = m_channel[CHAN_DATA]; + if (channel.m_end == channel.m_curr) + { + channel.m_status |= CDVD_STATUS_IDLE; + return 0; + } + + const uint8_t ret = channel.m_buffer[channel.m_curr++]; + if (channel.m_end == channel.m_curr) + { + channel.m_status |= CDVD_STATUS_IDLE; + channel.m_curr = 0; + channel.m_end = 0; + } + return ret; +} + WRITE8_MEMBER(iop_cdvd_device::write) { switch (offset) { case 0x16: - m_command = data; - m_status_0x17 &= ~(CDVD_STATUS_IDLE | CDVD_STATUS_BOOT); - m_status_0x05 &= ~CDVD_STATUS_BOOT; - if (m_out_count > 0) - logerror("%s: cdvd_w: Command warning: Issuing command without reading previous results\n", machine().describe_context()); - switch (data) - { - case 0x15: - logerror("%s: cdvd_w: Command 0x15?\n", machine().describe_context()); - m_out_buf[m_out_count++] = 1; - m_intc->raise_interrupt(5); - break; - case 0x40: - logerror("%s: cdvd_w: Command 0x40?\n", machine().describe_context()); - m_out_buf[m_out_count++] = 0; - break; - case 0x41: - logerror("%s: cdvd_w: Command 0x41?\n", machine().describe_context()); - m_out_count = 0x10; - memset(&m_out_buf[0], 0, 0x10); - break; - case 0x43: - logerror("%s: cdvd_w: Command 0x43?\n", machine().describe_context()); - m_out_buf[m_out_count++] = 0; - break; - default: - logerror("%s: cdvd_r: Unknown command(?) %02x\n", machine().describe_context(), data); - break; - } + handle_data_command(data); + break; + case 0x17: + data_fifo_push(data); + logerror("%s: cdvd_w: Data FIFO push? %02x\n", machine().describe_context(), data); break; default: logerror("%s: cdvd_w: Unknown write: %08x = %02x\n", machine().describe_context(), 0x1f402000 + offset, data); break; } } + +void iop_cdvd_device::handle_data_command(uint8_t data) +{ + drive_channel_t &channel = m_channel[CHAN_DATA]; + channel.m_command = data; + channel.m_status &= ~CDVD_STATUS_IDLE; + if (channel.m_end) + logerror("%s: cdvd_w: Data Command warning: Issuing command without reading previous results\n", machine().describe_context()); + + switch (data) + { + case 0x08: + logerror("%s: cdvd_w: Command 0x08?\n", machine().describe_context()); + for (size_t i = 0; i < 8; i++) + data_fifo_push(0); + break; + case 0x15: + logerror("%s: cdvd_w: Command 0x15?\n", machine().describe_context()); + data_fifo_push(1); + break; + case 0x40: + logerror("%s: cdvd_w: Command 0x40?\n", machine().describe_context()); + data_fifo_push(0); + break; + case 0x41: + logerror("%s: cdvd_w: Command 0x41?\n", machine().describe_context()); + for (size_t i = 0; i < 0x10; i++) + data_fifo_push(0); + break; + case 0x43: + logerror("%s: cdvd_w: Command 0x43?\n", machine().describe_context()); + data_fifo_push(0); + break; + default: + logerror("%s: cdvd_w: Unknown command(?) %02x\n", machine().describe_context(), data); + break; + } +} diff --git a/src/mame/machine/iopcdvd.h b/src/mame/machine/iopcdvd.h index e8d13da45b0..c9e8b4b2315 100644 --- a/src/mame/machine/iopcdvd.h +++ b/src/mame/machine/iopcdvd.h @@ -36,21 +36,34 @@ protected: virtual void device_start() override; virtual void device_reset() override; + void handle_data_command(uint8_t data); + void data_fifo_push(uint8_t data); + uint8_t data_fifo_pop(); + enum { - CDVD_STATUS_BOOT = 0x08, CDVD_STATUS_IDLE = 0x40, - - CDVD_COMMAND_0x15 = 0x15, }; required_device m_intc; - uint8_t m_status_0x05; - uint8_t m_status_0x17; - uint8_t m_command; - std::unique_ptr m_out_buf; - uint8_t m_out_count; - uint8_t m_out_curr; + + enum + { + CHAN_SERVO = 0, + CHAN_DATA = 1 + }; + + struct drive_channel_t + { + uint8_t m_buffer[0x10]; // Buffer size is a total guess + uint8_t m_curr; + uint8_t m_end; + + uint8_t m_status; + uint8_t m_command; + }; + + drive_channel_t m_channel[2]; static const size_t BUFFER_SIZE; }; diff --git a/src/mame/machine/ioptimer.cpp b/src/mame/machine/ioptimer.cpp index 55b05dbdd61..5a5fa0ed592 100644 --- a/src/mame/machine/ioptimer.cpp +++ b/src/mame/machine/ioptimer.cpp @@ -205,11 +205,11 @@ READ32_MEMBER(iop_timer_device::read) { case 0x00: { - const uint32_t old = m_count; + //const uint32_t old = m_count; update_count(); ret = m_count; - if (old != m_count) - logerror("%s: IOP timer read: COUNT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //if (old != m_count) + //logerror("%s: IOP timer read: COUNT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; } diff --git a/src/mame/machine/ps2dma.cpp b/src/mame/machine/ps2dma.cpp index b342445176a..5d331fb69d0 100644 --- a/src/mame/machine/ps2dma.cpp +++ b/src/mame/machine/ps2dma.cpp @@ -129,26 +129,29 @@ void ps2_dmac_device::transfer_vif1() if (count) { //logerror("%s: DMAC VIF1 quadword count: %08x\n", machine().describe_context(), count); - uint32_t addr = channel.addr(); - if (BIT(addr, 31)) - addr -= 0x10000000; - address_space &space = m_ee->space(AS_PROGRAM); - uint32_t words[4] = { 0, 0, 0, 0 }; - for (int word = 0; word < 4; word++) + if (m_vif1->fifo_available(4)) { - words[word] = space.read_dword(addr); - addr += 4; + uint32_t addr = channel.addr(); + if (BIT(addr, 31)) + addr -= 0x10000000; + address_space &space = m_ee->space(AS_PROGRAM); + uint32_t words[4] = { 0, 0, 0, 0 }; + for (int word = 0; word < 4; word++) + { + words[word] = space.read_dword(addr); + addr += 4; + } + m_vif1->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]); + channel.set_addr(channel.addr() + 0x10); + channel.set_quadword_count(count - 1); } - m_vif1->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]); - channel.set_addr(channel.addr() + 0x10); - channel.set_quadword_count(count - 1); } else if (channel.end_tag()) { logerror("%s: DMAC VIF1 end tag\n", machine().describe_context()); transfer_finish(VIF1); } - else + else if (m_vif1->fifo_available(2)) { logerror("%s: DMAC VIF1 following source tag\n", machine().describe_context()); uint32_t tag_addr = channel.tag_addr(); @@ -232,7 +235,7 @@ void ps2_dmac_device::transfer_sif0() } else if (channel.end_tag()) { - logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context()); + //logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context()); transfer_finish(SIF0); } else if (m_sif->fifo_depth(0) >= 2) @@ -240,7 +243,7 @@ void ps2_dmac_device::transfer_sif0() const uint32_t hi = m_sif->fifo_pop(0); const uint32_t lo = m_sif->fifo_pop(0); const uint32_t tag = hi; - logerror("%s: SIF0 chaining tag, tag %08x %08x\n", machine().describe_context(), hi, lo); + //logerror("%s: SIF0 chaining tag, tag %08x %08x\n", machine().describe_context(), hi, lo); channel.set_addr(lo); channel.set_tag_addr(channel.tag_addr() + 0x10); channel.set_quadword_count(tag & 0x0000ffff); @@ -280,12 +283,12 @@ void ps2_dmac_device::transfer_sif1() } else if (channel.end_tag()) { - logerror("%s: DMAC SIF1 end tag\n", machine().describe_context()); + //logerror("%s: DMAC SIF1 end tag\n", machine().describe_context()); transfer_finish(SIF1); } else { - logerror("%s: DMAC SIF1 following source tag\n", machine().describe_context()); + //logerror("%s: DMAC SIF1 following source tag\n", machine().describe_context()); follow_source_tag(SIF1); } } @@ -301,7 +304,8 @@ void ps2_dmac_device::follow_source_tag(uint32_t chan) const uint64_t lo = space.read_dword(tag_addr + 8); const uint32_t tag = (uint32_t)hi; const uint32_t addr = (uint32_t)(hi >> 32) & ~0xf; - logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo); + if (chan != GIF && chan != VIF1) + logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo); channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000)); channel.set_quadword_count(tag & 0x0000ffff); @@ -338,6 +342,7 @@ void ps2_dmac_device::follow_source_tag(uint32_t chan) logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id); break; } + if (irq && channel.irq_enable()) { channel.set_end_tag(true); @@ -521,15 +526,15 @@ READ32_MEMBER(ps2_dmac_device::channel_r) break; case 0xc000/8: /* SIF0_CHCR */ ret = m_channels[SIF0].chcr(); - logerror("%s: dmac_channel_r: SIF0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc010/8: /* SIF0_MADR */ ret = m_channels[SIF0].addr(); - logerror("%s: dmac_channel_r: SIF0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc020/8: /* SIF0_QWC */ ret = m_channels[SIF0].quadword_count(); - logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc400/8: /* SIF1_CHCR */ ret = m_channels[SIF1].chcr(); @@ -537,11 +542,11 @@ READ32_MEMBER(ps2_dmac_device::channel_r) break; case 0xc410/8: /* SIF1_MADR */ ret = m_channels[SIF1].addr(); - logerror("%s: dmac_channel_r: SIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc420/8: /* SIF1_QWC */ ret = m_channels[SIF1].quadword_count(); - logerror("%s: dmac_channel_r: SIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + //logerror("%s: dmac_channel_r: SIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc430/8: /* SIF1_TADR */ ret = m_channels[SIF1].tag_addr(); @@ -682,33 +687,33 @@ WRITE32_MEMBER(ps2_dmac_device::channel_w) logerror("%s: dmac_channel_w: D4_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); break; case 0xc000/8: /* SIF0_CHCR */ - logerror("%s: dmac_channel_w: SIF0_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer"); - logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16); + //logerror("%s: dmac_channel_w: SIF0_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer"); + //logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16); m_channels[SIF0].set_chcr(data); break; case 0xc010/8: /* SIF0_MADR */ - logerror("%s: dmac_channel_w: SIF0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + //logerror("%s: dmac_channel_w: SIF0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); m_channels[SIF0].set_addr(data); break; case 0xc020/8: /* SIF0_QWC */ - logerror("%s: dmac_channel_w: SIF0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); + //logerror("%s: dmac_channel_w: SIF0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); m_channels[SIF0].set_quadword_count(data); break; case 0xc400/8: /* D6_CHCR */ - logerror("%s: dmac_channel_w: SIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer"); - logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16); + //logerror("%s: dmac_channel_w: SIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer"); + //logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16); m_channels[SIF1].set_chcr(data); break; case 0xc410/8: /* D6_MADR */ - logerror("%s: dmac_channel_w: SIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + //logerror("%s: dmac_channel_w: SIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); m_channels[SIF1].set_addr(data); break; case 0xc420/8: /* D6_QWC */ - logerror("%s: dmac_channel_w: SIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); + //logerror("%s: dmac_channel_w: SIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask); m_channels[SIF1].set_quadword_count(data); break; case 0xc430/8: /* D6_TADR */ - logerror("%s: dmac_channel_w: SIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + //logerror("%s: dmac_channel_w: SIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask); m_channels[SIF1].set_tag_addr(data); break; case 0xc800/8: /* D7_CHCR */ diff --git a/src/mame/machine/ps2vif1.cpp b/src/mame/machine/ps2vif1.cpp index 57901041e47..11aba89b0ba 100644 --- a/src/mame/machine/ps2vif1.cpp +++ b/src/mame/machine/ps2vif1.cpp @@ -27,6 +27,7 @@ ps2_vif1_device::ps2_vif1_device(const machine_config &mconfig, const char *tag, : device_t(mconfig, SONYPS2_VIF1, tag, owner, clock) , device_execute_interface(mconfig, *this) , m_gif(*this, finder_base::DUMMY_TAG) + , m_vu1(*this, finder_base::DUMMY_TAG) { } @@ -264,11 +265,11 @@ WRITE64_MEMBER(ps2_vif1_device::mmio_w) void ps2_vif1_device::dma_write(const uint64_t hi, const uint64_t lo) { - logerror("%s: dma_write: %08x%08x%08x%08x\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo); - fifo_push((uint32_t)(hi >> 32)); - fifo_push((uint32_t)hi); + //logerror("%s: dma_write: %08x%08x%08x%08x\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo); fifo_push((uint32_t)(lo >> 32)); fifo_push((uint32_t)lo); + fifo_push((uint32_t)(hi >> 32)); + fifo_push((uint32_t)hi); } void ps2_vif1_device::tag_write(uint32_t *data) @@ -278,14 +279,19 @@ void ps2_vif1_device::tag_write(uint32_t *data) fifo_push(data[3]); } -void ps2_vif1_device::fifo_push(uint32_t value) +void ps2_vif1_device::fifo_push(uint32_t data) { if (m_end >= BUFFER_SIZE) { + printf("FIFO overflow :(\n"); return; } - m_buffer[m_end++] = value; + m_buffer[m_end++] = data; + + m_status &= ~0x1f000000; + m_status |= ((m_end - m_curr) >> 2) << 24; + logerror("%s: Pushing %08x onto FIFO, depth is now %d, status is now %08x\n", machine().describe_context(), data, m_end - m_curr, m_status); } uint32_t ps2_vif1_device::fifo_pop() @@ -303,6 +309,11 @@ uint32_t ps2_vif1_device::fifo_pop() m_curr = 0; m_end = 0; } + + m_status &= ~0x1f000000; + m_status |= ((m_end - m_curr) >> 2) << 24; + logerror("%s: Popping %08x from FIFO, depth is now %d, status is now %08x\n", machine().describe_context(), ret, m_end - m_curr, m_status); + return ret; } @@ -322,9 +333,11 @@ void ps2_vif1_device::execute_run() if (fifo_depth()) { m_code = fifo_pop(); + logerror("%s: New VIFcode: %08x\n", machine().describe_context(), m_code); } else { + //logerror("%s: Nothing in FIFO, idle\n", machine().describe_context()); m_icount = 0; break; } @@ -333,7 +346,7 @@ void ps2_vif1_device::execute_run() decode_vifcode(); break; case STAT_MODE_WAIT: - if (fifo_depth() == 0) + if (fifo_depth() < m_data_needed) { m_icount = 0; break; @@ -351,6 +364,7 @@ void ps2_vif1_device::transfer_vifcode_data() m_status &= ~STAT_MODE_MASK; if (fifo_depth() < m_data_needed) { + //logerror("%s: transfer: We need %d but only have %d, waiting\n", machine().describe_context(), m_data_needed, fifo_depth()); m_status |= STAT_MODE_WAIT; m_icount = 0; return; @@ -360,15 +374,18 @@ void ps2_vif1_device::transfer_vifcode_data() { case 0x20: /* STMASK */ m_mask = fifo_pop(); + logerror("%s: STMASK: %08x\n", machine().describe_context(), m_mask); m_data_needed = 0; break; case 0x30: /* STROW */ m_row_fill[m_data_index] = fifo_pop(); - m_data_needed = 0; + logerror("%s: STMASK: %08x\n", machine().describe_context(), m_row_fill[m_data_index]); + m_data_needed--; break; case 0x31: /* STCOL */ m_col_fill[m_data_index] = fifo_pop(); - m_data_needed = 0; + logerror("%s: STMASK: %08x\n", machine().describe_context(), m_col_fill[m_data_index]); + m_data_needed--; break; case 0x4a: /* MPG */ transfer_mpg(); @@ -376,8 +393,13 @@ void ps2_vif1_device::transfer_vifcode_data() default: if ((m_command & 0x60) == 0x60) { + logerror("%s: Unpack: %02x\n", machine().describe_context(), m_command); transfer_unpack(); } + else + { + logerror("%s: Unknown command: %02x\n", machine().describe_context(), m_command); + } break; } @@ -397,6 +419,7 @@ void ps2_vif1_device::transfer_vifcode_data() else if (fifo_depth() > 0) { m_code = fifo_pop(); + logerror("%s: New VIFcode: %08x\n", machine().describe_context(), m_code); m_status |= STAT_MODE_DECODE; m_icount--; } @@ -412,22 +435,28 @@ void ps2_vif1_device::transfer_unpack() switch (m_unpack_format) { case FMT_V4_32: - logerror("%s: Unpacking V4-32.\n", machine().describe_context()); + //logerror("%s: Unpacking V4-32.\n", machine().describe_context()); for (int element = 0; element < 4; element++) { - fifo_pop(); - //const uint32_t data = fifo_pop(); - //m_vu->write_data(m_unpack_addr, data); + const uint32_t data = fifo_pop(); + m_vu1->write_vu_mem(m_unpack_addr, data); m_unpack_addr += 4; + m_unpack_count--; } - m_unpack_count--; break; default: logerror("%s: Unsupported unpack format: %02x\n", machine().describe_context(), m_unpack_format); break; } - m_data_needed = FORMAT_SIZE[m_unpack_format] - (m_unpack_bits_remaining ? 1 : 0); + if (m_unpack_count > 0) + { + m_data_needed = FORMAT_SIZE[m_unpack_format] - (m_unpack_bits_remaining ? 1 : 0); + } + else + { + m_data_needed = 0; + } } void ps2_vif1_device::transfer_mpg() @@ -438,26 +467,27 @@ void ps2_vif1_device::transfer_mpg() m_data_needed--; } - m_mpg_insn = fifo_pop(); - m_mpg_insn |= (uint64_t)fifo_pop() << 32; - m_mpg_addr += 8; + m_mpg_insn = (uint64_t)fifo_pop() << 32; + m_mpg_insn |= fifo_pop(); m_mpg_count--; + + m_vu1->write_micro_mem(m_mpg_addr, m_mpg_insn); + logerror("%s: MPG, VU insn: %08x = %08x%08x, %d remaining\n", machine().describe_context(), m_mpg_addr, (uint32_t)(m_mpg_insn >> 32), (uint32_t)m_mpg_insn, m_mpg_count); + + m_mpg_addr += 8; m_data_needed = m_mpg_count ? 2 : 0; - - logerror("%s: MPG, VU insn: %08x%08x, %d remaining\n", machine().describe_context(), (uint32_t)(m_mpg_insn >> 32), (uint32_t)m_mpg_insn, m_mpg_count); - - //m_vu->write_instruction(m_mpg_addr, m_mpg_insn); } void ps2_vif1_device::decode_vifcode() { - //bool trigger_interrupt = BIT(m_code, 31); + bool trigger_interrupt = BIT(m_code, 31); m_command = (m_code >> 24) & 0x7f; m_status &= ~STAT_MODE_MASK; switch (m_command) { case 0x00: /* NOP */ + logerror("%s: NOP\n", machine().describe_context()); break; case 0x01: /* STCYCL */ m_cycle = (uint16_t)m_code; @@ -519,6 +549,7 @@ void ps2_vif1_device::decode_vifcode() m_unpack_add_tops = BIT(m_code, 15); m_unpack_format = (uint8_t)(m_command & 0xf); m_data_needed = FORMAT_SIZE[m_unpack_format]; + logerror("%s: UNPACK (%08x), count %d\n", machine().describe_context(), m_code, m_unpack_count); } else { /* unknown */ @@ -551,6 +582,11 @@ void ps2_vif1_device::decode_vifcode() m_status |= STAT_MODE_IDLE; m_icount = 0; } + + if (trigger_interrupt) + { + printf("******************\n"); + } } uint32_t ps2_vif1_device::calculate_unpack_count() diff --git a/src/mame/machine/ps2vif1.h b/src/mame/machine/ps2vif1.h index cc2d1d0d359..462e5e5533b 100644 --- a/src/mame/machine/ps2vif1.h +++ b/src/mame/machine/ps2vif1.h @@ -15,16 +15,18 @@ #pragma once #include "emu.h" +#include "cpu/mips/sonyvu.h" #include "ps2gif.h" class ps2_vif1_device : public device_t, public device_execute_interface { public: - template - ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&gif_tag) + template + ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&gif_tag, U &&vu1_tag) : ps2_vif1_device(mconfig, tag, owner, clock) { m_gif.set_tag(std::forward(gif_tag)); + m_vu1.set_tag(std::forward(vu1_tag)); } ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -37,6 +39,7 @@ public: void dma_write(const uint64_t hi, const uint64_t lo); void tag_write(uint32_t *data); + bool fifo_available(uint32_t count) const { return (BUFFER_SIZE - m_end) >= count; } protected: virtual void device_start() override; @@ -103,6 +106,7 @@ protected: }; required_device m_gif; + required_device m_vu1; int m_icount; diff --git a/src/mame/video/ps2gs.cpp b/src/mame/video/ps2gs.cpp index a7d77c392b3..a6811a28e70 100644 --- a/src/mame/video/ps2gs.cpp +++ b/src/mame/video/ps2gs.cpp @@ -41,6 +41,7 @@ DEFINE_DEVICE_TYPE(SONYPS2_GS, ps2_gs_device, "ps2gs", "Playstation 2 GS") ps2_gs_device::ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SONYPS2_GS, tag, owner, clock) + , m_intc(*this, finder_base::DUMMY_TAG) { } @@ -366,7 +367,7 @@ READ64_MEMBER(ps2_gs_device::priv_regs1_r) switch (offset) { case 0x00: - ret = m_csr; + ret = m_csr | (CSR_REV | CSR_ID | CSR_FIFO_EMPTY); logerror("%s: regs1_r: CSR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break; case 0x02: @@ -394,7 +395,8 @@ WRITE64_MEMBER(ps2_gs_device::priv_regs1_w) { case 0x00: logerror("%s: regs1_w: CSR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); - m_csr = data &~ CSR_RESET; + m_csr = data &~ (CSR_RESET | CSR_SIGNAL | CSR_HSINT | CSR_VSINT | CSR_EDWINT | CSR_FLUSH); + //m_csr |= (CSR_SIGNAL | CSR_HSINT | CSR_VSINT | CSR_EDWINT | CSR_FLUSH); break; case 0x02: logerror("%s: regs1_w: IMR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); @@ -724,7 +726,7 @@ void ps2_gs_device::vblank_end() { m_curr_field ^= 1; if (m_curr_field) - m_csr |= CSR_FIELD_ODD; - else m_csr &= ~CSR_FIELD_ODD; + else + m_csr |= CSR_FIELD_ODD; } diff --git a/src/mame/video/ps2gs.h b/src/mame/video/ps2gs.h index ed825e4a6e0..fadb259cadb 100644 --- a/src/mame/video/ps2gs.h +++ b/src/mame/video/ps2gs.h @@ -15,11 +15,20 @@ #pragma once #include "emu.h" +#include "machine/ps2intc.h" class ps2_gs_device : public device_t { public: - ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template + + ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc_tag) + : ps2_gs_device(mconfig, tag, owner, clock) + { + m_intc.set_tag(std::forward(intc_tag)); + } + + ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); DECLARE_READ64_MEMBER(priv_regs0_r); DECLARE_WRITE64_MEMBER(priv_regs0_w); @@ -115,8 +124,22 @@ protected: enum : uint32_t { - CSR_RESET = 0x00000200, - CSR_FIELD_ODD = 0x00002000 + CSR_SIGNAL = 0x00000001, + CSR_FINISH = 0x00000002, + CSR_HSINT = 0x00000004, + CSR_VSINT = 0x00000008, + CSR_EDWINT = 0x00000010, + CSR_FLUSH = 0x00000100, + CSR_RESET = 0x00000200, + CSR_NFIELD = 0x00001000, + CSR_FIELD_ODD = 0x00002000, + CSR_FIFO_MASK = 0x0000c000, + CSR_FIFO_MID = 0x00000000, + CSR_FIFO_EMPTY = 0x00004000, + CSR_FIFO_HI = 0x00008000, + CSR_FIFO_INV = 0x0000c000, + CSR_REV = 0x001b0000, + CSR_ID = 0x55000000 }; struct vertex_t @@ -137,6 +160,8 @@ protected: uint8_t m_fog; }; + required_device m_intc; + std::unique_ptr m_ram; std::unique_ptr m_vertices;