From f3ccd1f7f2fa8d8eef77a8ef1cfd69398e3a21fb Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Thu, 5 Jul 2018 19:04:39 +0200 Subject: -ps2sony: Various DMA and SIF bug fixes, initial OSDSYS ELF transfers to IOP now, but EE and IOP hang immediately thereafter. nw --- src/devices/cpu/mips/mips3.cpp | 75 +++++++++++++++---- src/devices/cpu/mips/mips3.h | 4 + src/devices/cpu/mips/mips3com.h | 2 + src/devices/cpu/mips/mips3dsm.cpp | 42 ++++++++++- src/devices/cpu/mips/mips3dsm.h | 4 + src/devices/cpu/mips/r3000.cpp | 1 + src/mame/machine/iopdma.cpp | 135 ++++++++++++++++++++++++--------- src/mame/machine/iopdma.h | 8 +- src/mame/machine/iopintc.cpp | 1 + src/mame/machine/ps2dma.cpp | 154 +++++++++++++++++++++++++++++++------- src/mame/machine/ps2dma.h | 30 +++++++- src/mame/machine/ps2sif.cpp | 15 +++- src/mame/machine/ps2sif.h | 4 +- 13 files changed, 389 insertions(+), 86 deletions(-) diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 021b81293b8..5cb9b147d05 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -248,6 +248,10 @@ void mips3_device::generate_exception(int exception, int backup) offset = 0; exception = (exception - EXCEPTION_TLBLOAD_FILL) + EXCEPTION_TLBLOAD; } + else if (exception == EXCEPTION_INTERRUPT && m_flavor == MIPS3_TYPE_R5900) + { + offset = 0x200; + } /* set the exception PC */ m_core->cpr[0][COP0_EPC] = m_core->pc; @@ -309,6 +313,7 @@ void mips3_device::generate_tlb_exception(int exception, offs_t address) void mips3_device::invalid_instruction(uint32_t op) { + printf("Invalid instruction! %08x\n", op); generate_exception(EXCEPTION_INVALIDOP, 1); } @@ -320,7 +325,8 @@ void mips3_device::invalid_instruction(uint32_t op) void mips3_device::check_irqs() { - if ((CAUSE & SR & 0xfc00) && (SR & SR_IE) && !(SR & SR_EXL) && !(SR & SR_ERL)) + bool ie = (SR & SR_IE) && ((SR & SR_EIE) || m_flavor != MIPS3_TYPE_R5900); + if ((CAUSE & SR & 0xfc00) && ie && !(SR & SR_EXL) && !(SR & SR_ERL)) generate_exception(EXCEPTION_INTERRUPT, 0); } @@ -1778,13 +1784,17 @@ void mips3_device::handle_cop0(uint32_t op) case 0x10: /* RFE */ invalid_instruction(op); break; case 0x18: /* ERET logerror("ERET\n"); */ m_core->pc = m_core->cpr[0][COP0_EPC]; SR &= ~SR_EXL; check_irqs(); m_lld_value ^= 0xffffffff; m_ll_value ^= 0xffffffff; break; case 0x20: /* WAIT */ break; - default: invalid_instruction(op); break; + default: handle_extra_cop0(op); break; } break; default: invalid_instruction(op); break; } } +void mips3_device::handle_extra_cop0(uint32_t op) +{ + invalid_instruction(op); +} /*************************************************************************** @@ -2097,12 +2107,6 @@ void mips3_device::handle_cop1_fr0(uint32_t op) FDVALD_FR0 = 1.0 / sqrt(FSVALD_FR0); break; - case 0x18: /* R5900 */ - if (m_flavor != MIPS3_TYPE_R5900) - break; - m_core->acc = FSVALS_FR0 + FTVALS_FR0; - break; - case 0x20: if (IS_INTEGRAL(op)) { @@ -2206,13 +2210,17 @@ void mips3_device::handle_cop1_fr0(uint32_t op) break; default: - fprintf(stderr, "cop1 %X\n", op); + handle_extra_cop1(op); break; } break; } } +void mips3_device::handle_extra_cop1(uint32_t op) +{ + invalid_instruction(op); +} void mips3_device::handle_cop1_fr1(uint32_t op) { @@ -3358,9 +3366,42 @@ void r5900le_device::handle_extra_regimm(uint32_t op) } } +void r5900le_device::handle_extra_cop0(uint32_t op) +{ + switch (op & 0x01ffffff) + { + case 0x38: /* EI */ + if ((SR & (SR_EXL | SR_ERL | SR_EDI)) || ((SR & SR_KSU_MASK) == SR_KSU_KERNEL)) + SR |= SR_EIE; + break; + case 0x39: /* DI */ + if ((SR & (SR_EXL | SR_ERL | SR_EDI)) || ((SR & SR_KSU_MASK) == SR_KSU_KERNEL)) + SR &= ~SR_EIE; + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_extra_cop1(uint32_t op) +{ + switch (op & 0x3f) + { + case 0x18: /* ADDA.S */ + m_core->acc = FSVALS_FR0 + FTVALS_FR0; + break; + + case 0x1c: /* MADD.S */ + m_core->acc += FSVALS_FR1 * FTVALS_FR1; + FDVALS_FR1 = m_core->acc; + break; + } +} + void r5900le_device::handle_idt(uint32_t op) { - //const int rs = (op >> 21) & 31; + const int rs = (op >> 21) & 31; //const int rt = (op >> 16) & 31; const int rd = (op >> 11) & 31; @@ -3373,7 +3414,13 @@ void r5900le_device::handle_idt(uint32_t op) printf("Unsupported instruction: MADDU @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); break; case 0x04: /* PLZCW */ - printf("Unsupported instruction: PLZCW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + if (rd) + { + const uint64_t rsval = m_core->r[rs]; + const uint64_t hi = (uint32_t)(count_leading_zeros((uint32_t)(rsval >> 32)) - 1); + const uint64_t lo = (uint32_t)(count_leading_zeros((uint32_t)rsval) - 1); + m_core->r[rd] = (hi << 32) | lo; + } break; case 0x08: /* MMI0 */ handle_mmi0(op); @@ -3387,7 +3434,8 @@ void r5900le_device::handle_idt(uint32_t op) m_core->icount--; break; case 0x11: /* MTHI1 */ - printf("Unsupported instruction: MTHI1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + m_core->rh[REG_HI] = m_core->r[rs]; + m_core->icount--; break; case 0x12: /* MFLO1 */ if (rd) @@ -3395,7 +3443,8 @@ void r5900le_device::handle_idt(uint32_t op) m_core->icount--; break; case 0x13: /* MTLO1 */ - printf("Unsupported instruction: MTLO1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + m_core->rh[REG_LO] = m_core->r[rs]; + m_core->icount--; break; case 0x18: /* MULT1 */ { diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index b896235c85a..cdc6edfaa0d 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -544,6 +544,8 @@ private: virtual void handle_extra_base(uint32_t op); virtual void handle_extra_special(uint32_t op); virtual void handle_extra_regimm(uint32_t op); + virtual void handle_extra_cop0(uint32_t op); + virtual void handle_extra_cop1(uint32_t op); virtual void handle_extra_cop2(uint32_t op); virtual void handle_idt(uint32_t op); virtual void handle_ldc2(uint32_t op); @@ -804,6 +806,8 @@ protected: void handle_extra_base(uint32_t op) override; void handle_extra_special(uint32_t op) override; void handle_extra_regimm(uint32_t op) override; + void handle_extra_cop0(uint32_t op) override; + void handle_extra_cop1(uint32_t op) override; void handle_extra_cop2(uint32_t op) override; void handle_idt(uint32_t op) override; void handle_mmi0(uint32_t op); diff --git a/src/devices/cpu/mips/mips3com.h b/src/devices/cpu/mips/mips3com.h index 9365deff603..96fc9c28b09 100644 --- a/src/devices/cpu/mips/mips3com.h +++ b/src/devices/cpu/mips/mips3com.h @@ -124,7 +124,9 @@ #define SR_IMEX4 0x00004000 #define SR_IMEX5 0x00008000 #define SR_DE 0x00010000 +#define SR_EIE 0x00010000 /* R5900/EE only, Enable IE bit */ #define SR_CE 0x00020000 +#define SR_EDI 0x00020000 /* R5900/EE only, EI/DI instruction enable */ #define SR_CH 0x00040000 #define SR_SR 0x00100000 #define SR_TS 0x00200000 diff --git a/src/devices/cpu/mips/mips3dsm.cpp b/src/devices/cpu/mips/mips3dsm.cpp index c93e8166344..a0bb46456ec 100644 --- a/src/devices/cpu/mips/mips3dsm.cpp +++ b/src/devices/cpu/mips/mips3dsm.cpp @@ -182,6 +182,12 @@ uint32_t mips3_disassembler::dasm_cop0(uint32_t pc, uint32_t op, std::ostream &s return flags; } +uint32_t mips3_disassembler::dasm_extra_cop0(uint32_t pc, uint32_t op, std::ostream &stream) +{ + util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); + return 0; +} + uint32_t mips3_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &stream) { const char *const format_table[] = @@ -258,13 +264,19 @@ uint32_t mips3_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &s case 0x3d: util::stream_format(stream, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break; case 0x3e: util::stream_format(stream, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break; case 0x3f: util::stream_format(stream, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break; - default: util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); break; + default: dasm_extra_cop1(pc, op, stream); break; } break; } return flags; } +uint32_t mips3_disassembler::dasm_extra_cop1(uint32_t pc, uint32_t op, std::ostream &stream) +{ + util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); + return 0; +} + uint32_t mips3_disassembler::dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &stream) { const char *const format3_table[] = @@ -416,6 +428,32 @@ uint32_t mips3_disassembler::dasm_extra_special(uint32_t pc, uint32_t op, std::o return 0; } +uint32_t ee_disassembler::dasm_extra_cop0(uint32_t pc, uint32_t op, std::ostream &stream) +{ + switch (op & 0x01ffffff) + { + case 0x38: util::stream_format(stream, "ei"); break; + case 0x39: util::stream_format(stream, "di"); break; + default: util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); break; + } + return 0; +} + +uint32_t ee_disassembler::dasm_extra_cop1(uint32_t pc, uint32_t op, std::ostream &stream) +{ + const int fd = (op >> 6) & 31; + const int fs = (op >> 11) & 31; + const int ft = (op >> 16) & 31; + + switch (op & 0x3f) + { + case 0x18: util::stream_format(stream, "adda.s %s,%s", cpreg[1][fs], cpreg[1][ft]); break; + case 0x1c: util::stream_format(stream, "madd.s %s,%s,%s", cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break; + default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break; + } + return 0; +} + uint32_t ee_disassembler::dasm_extra_cop2(uint32_t pc, uint32_t op, std::ostream &stream) { const int rd = (op >> 6) & 31; @@ -578,7 +616,7 @@ uint32_t ee_disassembler::dasm_idt(uint32_t pc, uint32_t op, std::ostream &strea else util::stream_format(stream, "maddu %s,%s", reg[rs], reg[rt]); break; - case 0x04: util::stream_format(stream, "plzcw ?"); break; + case 0x04: util::stream_format(stream, "plzcw %s,%s", reg[rd], reg[rs]); break; case 0x08: flags = dasm_mmi0(pc, op, stream); break; case 0x09: flags = dasm_mmi2(pc, op, stream); break; case 0x10: util::stream_format(stream, "mfhi1 %s", reg[rd]); break; diff --git a/src/devices/cpu/mips/mips3dsm.h b/src/devices/cpu/mips/mips3dsm.h index 1edaa69843d..8797a1b00c3 100644 --- a/src/devices/cpu/mips/mips3dsm.h +++ b/src/devices/cpu/mips/mips3dsm.h @@ -33,6 +33,8 @@ protected: virtual uint32_t dasm_extra_base(uint32_t pc, uint32_t op, std::ostream &stream); virtual uint32_t dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream); virtual uint32_t dasm_extra_regimm(uint32_t pc, uint32_t op, std::ostream &stream); + virtual uint32_t dasm_extra_cop0(uint32_t pc, uint32_t op, std::ostream &stream); + virtual uint32_t dasm_extra_cop1(uint32_t pc, uint32_t op, std::ostream &stream); virtual uint32_t dasm_extra_cop2(uint32_t pc, uint32_t op, std::ostream &stream); uint32_t dasm_cop0(uint32_t pc, uint32_t op, std::ostream &stream); uint32_t dasm_cop1(uint32_t pc, uint32_t op, std::ostream &stream); @@ -54,6 +56,8 @@ protected: uint32_t dasm_extra_base(uint32_t pc, uint32_t op, std::ostream &stream) override; uint32_t dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream) override; uint32_t dasm_extra_regimm(uint32_t pc, uint32_t op, std::ostream &stream) override; + uint32_t dasm_extra_cop0(uint32_t pc, uint32_t op, std::ostream &stream) override; + uint32_t dasm_extra_cop1(uint32_t pc, uint32_t op, std::ostream &stream) override; uint32_t dasm_extra_cop2(uint32_t pc, uint32_t op, std::ostream &stream) override; uint32_t dasm_idt(uint32_t pc, uint32_t op, std::ostream &stream) override; uint32_t dasm_mmi(uint32_t pc, uint32_t op, std::ostream &stream); diff --git a/src/devices/cpu/mips/r3000.cpp b/src/devices/cpu/mips/r3000.cpp index 377aebbc854..8c458e5e6bc 100644 --- a/src/devices/cpu/mips/r3000.cpp +++ b/src/devices/cpu/mips/r3000.cpp @@ -1092,6 +1092,7 @@ void r3000_device::execute_run() fflush(stdout); } */ + // instruction fetch m_op = readop(m_pc); diff --git a/src/mame/machine/iopdma.cpp b/src/mame/machine/iopdma.cpp index 1d841555ccb..68b36f8527b 100644 --- a/src/mame/machine/iopdma.cpp +++ b/src/mame/machine/iopdma.cpp @@ -69,6 +69,7 @@ void iop_dma_device::device_reset() m_dicr[0] = 0; m_dicr[1] = 0; m_last_serviced = 0; + m_running_mask = 0; } void iop_dma_device::execute_run() @@ -89,6 +90,9 @@ void iop_dma_device::execute_run() { switch (channel) { + case 10: + transfer_sif0(channel); + break; case 11: transfer_sif1(channel); break; @@ -104,6 +108,53 @@ void iop_dma_device::execute_run() } } +void iop_dma_device::transfer_sif0(uint32_t chan) +{ + channel_t &channel = m_channels[chan]; + const uint32_t count = channel.count(); + if (count) + { + if (m_sif->fifo_depth(0) < ps2_sif_device::MAX_FIFO_DEPTH) + { + const uint32_t addr = channel.addr(); + m_sif->fifo_push(0, m_ram[addr >> 2]); + channel.set_addr(addr + 4); + channel.set_count(count - 1); + } + } + else + { + if (channel.end()) + { + logerror("sif0.end\n"); + transfer_finish(SIF0); + } + else if (m_sif->fifo_depth(0) < ps2_sif_device::MAX_FIFO_DEPTH - 2) + { + const uint32_t tag_addr_bytes = channel.tag_addr(); + const uint32_t tag_addr = tag_addr_bytes >> 2; + const uint32_t iop_hi = m_ram[tag_addr]; + const uint32_t iop_lo = m_ram[tag_addr + 1]; + const uint32_t ee_hi = m_ram[tag_addr + 2]; + const uint32_t ee_lo = m_ram[tag_addr + 3]; + + logerror("%s: following sif0 iop tag, full tag is %08x %08x %08x %08x\n", machine().describe_context(), iop_hi, iop_lo, ee_hi, ee_lo); + channel.set_addr(iop_hi & 0x00ffffff); + channel.set_count(iop_lo + 2); + channel.set_tag_addr(tag_addr_bytes + 0x10); + + m_sif->fifo_push(0, ee_hi); + m_sif->fifo_push(0, ee_lo); + + if (iop_hi & 0xc0000000) + { + logerror("%s: sif0 iop tag end\n", machine().describe_context()); + channel.m_end = true; + } + } + } +} + void iop_dma_device::transfer_sif1(uint32_t chan) { channel_t &channel = m_channels[chan]; @@ -111,8 +162,8 @@ void iop_dma_device::transfer_sif1(uint32_t chan) { if (m_sif->fifo_depth(1)) { - printf("."); - const uint64_t data = m_sif->fifo_pop(1); + const uint32_t data = m_sif->fifo_pop(1); + logerror("%s: sif1 pop value: %08x\n", machine().describe_context(), (uint32_t)data); m_ram[channel.m_addr >> 2] = data; channel.m_addr += 4; @@ -123,37 +174,57 @@ void iop_dma_device::transfer_sif1(uint32_t chan) { if (channel.end()) { - channel.m_ctrl &= ~0x1000000; - channel.m_busy = false; - const uint32_t index = BIT(chan, 3); - const uint8_t subchan = chan & 7; - m_int_ctrl[index].m_status |= (1 << subchan); - m_dicr[index] |= 1 << (subchan + 24); - printf("channel.end\n"); - if (m_int_ctrl[index].m_status & m_int_ctrl[index].m_mask) - { - printf("raising interrupt\n"); - m_intc->raise_interrupt(iop_intc_device::INT_DMA); - } + logerror("sif1.end\n"); + transfer_finish(SIF1); } else if (m_sif->fifo_depth(1) >= 4) { - const uint32_t next_tag = m_sif->fifo_pop(1); - channel.m_addr = next_tag & 0x00ffffff; - channel.m_count = m_sif->fifo_pop(1); - - // ?? - m_sif->fifo_pop(1); - m_sif->fifo_pop(1); + const uint32_t iop_hi = m_sif->fifo_pop(1); + const uint32_t iop_lo = m_sif->fifo_pop(1); + m_sif->fifo_pop(1); // ee_hi - ignored + m_sif->fifo_pop(1); // ee_lo - ignored + logerror("%s: following sif1 iop tag, tag is %08x %08x\n", machine().describe_context(), iop_hi, iop_lo); + channel.set_addr(iop_hi & 0x00ffffff); + channel.set_count(iop_lo); - if (next_tag & 0xc0000000) + if (iop_hi & 0xc0000000) { + logerror("%s: sif1 iop tag end\n", machine().describe_context()); channel.m_end = true; } } } } +void iop_dma_device::transfer_finish(uint32_t chan) +{ + channel_t &channel = m_channels[chan]; + channel.m_ctrl &= ~0x1000000; + channel.m_busy = false; + channel.m_end = false; + const uint32_t index = BIT(chan, 3); + const uint8_t subchan = chan & 7; + m_int_ctrl[index].m_status |= (1 << subchan); + m_dicr[index] |= 1 << (subchan + 24); + + if (m_int_ctrl[index].m_status & m_int_ctrl[index].m_mask) + { + m_intc->raise_interrupt(iop_intc_device::INT_DMA); + if (m_int_ctrl[index].m_enabled) + { + m_dicr[index] |= 0x80000000; + } + else + { + m_dicr[index] &= ~0x80000000; + } + } + else + { + m_dicr[index] &= ~0x80000000; + } +} + READ32_MEMBER(iop_dma_device::bank0_r) { uint32_t ret = 0; @@ -285,7 +356,8 @@ void iop_dma_device::set_dpcr(uint32_t data, uint32_t index) void iop_dma_device::set_dicr(uint32_t data, uint32_t index) { - m_dicr[index] = data; + m_dicr[index] = (m_dicr[index] & (0x7f << 24)) | (data & ~(0x7f << 24)); + m_dicr[index] &= ~(data & (0x7f << 24)); m_int_ctrl[index].m_mask = (data >> 16) & 0x7f; m_int_ctrl[index].m_status &= ~((data >> 24) & 0x7f); m_int_ctrl[index].m_enabled = BIT(data, 23); @@ -294,21 +366,19 @@ void iop_dma_device::set_dicr(uint32_t data, uint32_t index) void iop_dma_device::channel_t::set_pri_ctrl(uint32_t pri_ctrl) { + bool was_enabled = m_enabled; m_enabled = BIT(pri_ctrl, 3); m_priority = pri_ctrl & 7; -} - -void iop_dma_device::channel_t::set_addr(uint32_t addr) -{ - m_addr = addr; + if (!was_enabled && m_enabled) + m_end = false; } void iop_dma_device::channel_t::set_block(uint32_t block, uint32_t mem_mask) { if (mem_mask & 0xffff) - m_count = (uint16_t)block; + m_size = (uint16_t)block; if (mem_mask & 0xffff0000) - m_size = (uint16_t)(block >> 16); + m_count = (uint16_t)(block >> 16); } void iop_dma_device::channel_t::set_ctrl(uint32_t ctrl) @@ -316,8 +386,3 @@ void iop_dma_device::channel_t::set_ctrl(uint32_t ctrl) m_ctrl = ctrl; m_busy = BIT(ctrl, 24); } - -void iop_dma_device::channel_t::set_tag_addr(uint32_t tag_addr) -{ - m_tag_addr = tag_addr; -} diff --git a/src/mame/machine/iopdma.h b/src/mame/machine/iopdma.h index 3e17fb54e9c..c95ec0bb799 100644 --- a/src/mame/machine/iopdma.h +++ b/src/mame/machine/iopdma.h @@ -76,10 +76,11 @@ protected: } void set_pri_ctrl(uint32_t pri_ctrl); - void set_addr(uint32_t addr); + void set_addr(uint32_t addr) { m_addr = addr; } void set_block(uint32_t block, uint32_t mem_mask); + void set_count(uint32_t count) { m_count = count; } void set_ctrl(uint32_t ctrl); - void set_tag_addr(uint32_t tag_addr); + void set_tag_addr(uint32_t tag_addr) { m_tag_addr = tag_addr; } bool enabled() const { return m_enabled; } bool busy() const { return m_busy; } @@ -88,6 +89,7 @@ protected: uint32_t ctrl() const { return m_ctrl; } uint32_t tag_addr() const { return m_tag_addr; } bool end() const { return m_end; } + uint32_t count() const { return m_count; } protected: uint8_t m_priority; @@ -112,7 +114,9 @@ protected: void set_dicr(uint32_t data, uint32_t index); void update_interrupts(); + void transfer_sif0(uint32_t chan); void transfer_sif1(uint32_t chan); + void transfer_finish(uint32_t chan); required_device m_intc; required_shared_ptr m_ram; diff --git a/src/mame/machine/iopintc.cpp b/src/mame/machine/iopintc.cpp index 9b383643d2e..85ff79e0b52 100644 --- a/src/mame/machine/iopintc.cpp +++ b/src/mame/machine/iopintc.cpp @@ -94,5 +94,6 @@ void iop_intc_device::raise_interrupt(uint32_t line) void iop_intc_device::update_interrupts() { bool active = (m_enabled && (m_status & m_mask)); + //printf("iop_intc: %d && (%08x & %08x) = %d\n", m_enabled, m_status, m_mask, active); m_iop->set_input_line(R3000_IRQ0, active ? ASSERT_LINE : CLEAR_LINE); } diff --git a/src/mame/machine/ps2dma.cpp b/src/mame/machine/ps2dma.cpp index d81cca0550d..58624b959f6 100644 --- a/src/mame/machine/ps2dma.cpp +++ b/src/mame/machine/ps2dma.cpp @@ -52,8 +52,11 @@ void ps2_dmac_device::device_start() save_item(NAME(m_channels[channel].m_mode), channel); save_item(NAME(m_channels[channel].m_enabled), channel); save_item(NAME(m_channels[channel].m_end_tag), channel); + save_item(NAME(m_channels[channel].m_end_irq), channel); + save_item(NAME(m_channels[channel].m_ienable), channel); save_item(NAME(m_channels[channel].m_qwc), channel); save_item(NAME(m_channels[channel].m_addr), channel); + save_item(NAME(m_channels[channel].m_tag_addr), channel); } } @@ -91,6 +94,12 @@ void ps2_dmac_device::execute_run() case SIF0: transfer_sif0(); break; + case SIF1: + transfer_sif1(); + break; + default: + logerror("%s: Attempting to service unimplemented DMA channel %d\n", machine().describe_context(), m_last_serviced); + break; } } if (m_last_serviced == 10) @@ -104,37 +113,112 @@ void ps2_dmac_device::transfer_sif0() const uint32_t count = channel.quadword_count(); if (count) { - printf("count\n"); - if (m_sif->fifo_depth(0) > 4) + if (m_sif->fifo_depth(0) >= 4) { - const uint32_t addr = channel.addr(); - for (uint32_t word = 0; word < 4; word++) + logerror("%s: SIF0 depth is %d\n", machine().describe_context(), m_sif->fifo_depth(0)); + uint32_t addr = channel.addr(); + for (int word = 0; word < 4; word++) { - m_ee->space(AS_PROGRAM).write_dword(addr + word, m_sif->fifo_pop(0)); + const uint32_t data = m_sif->fifo_pop(0); + //logerror("%s: SIF0 popping %08x -> %08x\n", machine().describe_context(), data, addr); + m_ee->space(AS_PROGRAM).write_dword(addr, data); + addr += 4; } - channel.set_addr(addr + 0x10); + channel.set_addr(addr); channel.set_quadword_count(count - 1); + logerror("%s: SIF0 remaining count: %08x\n", machine().describe_context(), channel.quadword_count()); } } - else + else if (channel.end_tag()) + { + logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context()); + transfer_finish(SIF0); + } + else if (m_sif->fifo_depth(0) >= 2) { - if (channel.end_tag()) + 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); + channel.set_addr(lo); + channel.set_tag_addr(channel.tag_addr() + 0x10); + channel.set_quadword_count(tag & 0x0000ffff); + channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000)); + + const uint8_t mode = (tag >> 28) & 7; + if ((channel.irq_enable() && BIT(tag, 31)) || mode == ID_END) { - printf("end\n"); - transfer_finish(SIF0); - } - else if (m_sif->fifo_depth(0) >= 2) - { - printf("follow\n"); + channel.set_end_tag(true); } - else + } +} + +void ps2_dmac_device::transfer_sif1() +{ + channel_t &channel = m_channels[SIF1]; + const uint32_t count = channel.quadword_count(); + if (count) + { + //logerror("%s: DMAC SIF1 quadword count: %08x\n", machine().describe_context(), count); + if (m_sif->fifo_depth(1) < (ps2_sif_device::MAX_FIFO_DEPTH - 4)) { + uint32_t addr = channel.addr(); + address_space &space = m_ee->space(AS_PROGRAM); + for (int word = 0; word < 4; word++) + { + const uint32_t data = space.read_dword(addr); + //logerror("%s: DMAC SIF1 Pushing %08x\n", machine().describe_context(), data); + addr += 4; + m_sif->fifo_push(1, data); + } + channel.set_addr(addr); + channel.set_quadword_count(count - 1); } } + else if (channel.end_tag()) + { + 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()); + follow_source_tag(SIF1); + } } -void ps2_dmac_device::follow_tag(uint32_t channel) +void ps2_dmac_device::follow_source_tag(uint32_t chan) { + channel_t &channel = m_channels[chan]; + const uint32_t tag_addr = channel.tag_addr() >> 3; + const uint64_t hi = m_ram[tag_addr]; + const uint64_t lo = m_ram[tag_addr + 1]; + 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); + + channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000)); + channel.set_quadword_count(tag & 0x0000ffff); + const uint32_t id = (tag >> 28) & 7; + const bool irq = BIT(tag, 31); + + switch (id) + { + case ID_REFE: + channel.set_end_tag(true); + // Intentional fall-through + case ID_REF: + channel.set_addr(addr); + channel.set_tag_addr(channel.tag_addr() + 0x10); + break; + default: + logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id); + break; + } + if (irq && channel.irq_enable()) + { + channel.set_end_tag(true); + } } void ps2_dmac_device::transfer_finish(uint32_t chan) @@ -315,17 +399,21 @@ READ32_MEMBER(ps2_dmac_device::channel_r) ret = m_channels[SIF0].quadword_count(); logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; - case 0xc400/8: /* D6_CHCR */ - logerror("%s: dmac_channel_r: D6_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + case 0xc400/8: /* SIF1_CHCR */ + ret = m_channels[SIF1].chcr(); + logerror("%s: dmac_channel_r: SIF1_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; - case 0xc410/8: /* D6_MADR */ - logerror("%s: dmac_channel_r: D6_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + 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); break; - case 0xc420/8: /* D6_QWC */ - logerror("%s: dmac_channel_r: D6_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + 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); break; - case 0xc430/8: /* D6_TADR */ - logerror("%s: dmac_channel_r: D6_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); + case 0xc430/8: /* SIF1_TADR */ + ret = m_channels[SIF1].tag_addr(); + logerror("%s: dmac_channel_r: SIF1_TADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); break; case 0xc800/8: /* D7_CHCR */ logerror("%s: dmac_channel_r: D7_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask); @@ -465,16 +553,21 @@ WRITE32_MEMBER(ps2_dmac_device::channel_w) m_channels[SIF0].set_quadword_count(data); break; case 0xc400/8: /* D6_CHCR */ - logerror("%s: dmac_channel_w: D6_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask); + 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: D6_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: D6_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: D6_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 */ logerror("%s: dmac_channel_w: D7_CHCR = %08x & %08x\n", machine().describe_context(), data, mem_mask); @@ -536,9 +629,14 @@ void ps2_dmac_device::channel_t::set_chcr(uint32_t data) m_chcr = data; m_mode = (data >> 2) & 3; bool was_enabled = m_enabled; + m_ienable = BIT(m_chcr, 7); m_enabled = BIT(m_chcr, 8); if (!was_enabled && m_enabled) { m_end_tag = m_mode == 0; } + else + { + m_end_tag = false; + } } \ No newline at end of file diff --git a/src/mame/machine/ps2dma.h b/src/mame/machine/ps2dma.h index 694b5713a21..c6dea56749c 100644 --- a/src/mame/machine/ps2dma.h +++ b/src/mame/machine/ps2dma.h @@ -34,6 +34,7 @@ public: { VIF0 = 0, VIF1, + GIF, IPU_OUT, IPU_IN, SIF0, @@ -56,13 +57,25 @@ protected: virtual void device_reset() override; virtual void execute_run() override; + enum tag_id + { + ID_REFE = 0, + ID_CNT, + ID_NEXT, + ID_REF, + ID_REFS, + ID_CALL, + ID_RET, + ID_END + }; + class channel_t { friend class ps2_dmac_device; public: channel_t() - : m_chcr(0), m_mode(0), m_enabled(false), m_end_tag(false), m_addr(0), m_qwc(0) + : m_chcr(0), m_mode(0), m_enabled(false), m_end_tag(false), m_end_irq(false), m_ienable(false), m_addr(0), m_qwc(0) { } @@ -70,7 +83,13 @@ protected: uint32_t chcr() const { return m_chcr; } uint32_t mode() const { return m_mode; } bool enabled() const { return m_enabled; } + bool irq_enable() const { return m_ienable; } + bool end_tag() const { return m_end_tag; } + void set_end_tag(bool end_tag) { m_end_tag = end_tag; } + + bool end_irq() const { return m_end_irq; } + void set_end_irq(bool end_irq) { m_end_irq = end_irq; } uint32_t addr() const { return m_addr; } void set_addr(uint32_t addr) { m_addr = addr; } @@ -78,19 +97,26 @@ protected: uint32_t quadword_count() const { return m_qwc; } void set_quadword_count(uint32_t qwc) { m_qwc = qwc; } + uint32_t tag_addr() const { return m_tag_addr; } + void set_tag_addr(uint32_t tag_addr) { m_tag_addr = tag_addr; } + protected: uint32_t m_chcr; uint32_t m_mode; bool m_enabled; bool m_end_tag; + bool m_end_irq; + bool m_ienable; uint32_t m_addr; uint32_t m_qwc; + uint32_t m_tag_addr; }; void transfer_sif0(); + void transfer_sif1(); void transfer_finish(uint32_t chan); - void follow_tag(uint32_t channel); + void follow_source_tag(uint32_t channel); void update_interrupts(); required_device m_ee; diff --git a/src/mame/machine/ps2sif.cpp b/src/mame/machine/ps2sif.cpp index fbe5b3ba9a5..3160103f9b5 100644 --- a/src/mame/machine/ps2sif.cpp +++ b/src/mame/machine/ps2sif.cpp @@ -97,7 +97,7 @@ WRITE32_MEMBER(ps2_sif_device::ee_w) m_sm_flag &= ~data; break; case 8: - logerror("%s: ee_w: SIF control = %08x & %08x\n", machine().describe_context(), data, mem_mask); + logerror("%s: ee_w: SIF set control = %08x & %08x\n", machine().describe_context(), data, mem_mask); if (BIT(data, 8)) m_ctrl |= (1 << 8); else @@ -151,6 +151,10 @@ WRITE32_MEMBER(ps2_sif_device::iop_w) logerror("%s: iop_w: SIF slave->master mailbox (%08x & %08x)\n", machine().describe_context(), data, mem_mask); m_sm_mailbox = data; break; + case 8: + logerror("%s: iop_w: SIF clear master->slave flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask); + m_ms_flag &= ~data; + break; case 12: logerror("%s: iop_w: SIF set slave->master flag (%08x & %08x)\n", machine().describe_context(), data, mem_mask); m_sm_flag |= data; @@ -158,6 +162,11 @@ WRITE32_MEMBER(ps2_sif_device::iop_w) case 16: logerror("%s: iop_w: SIF set control (%08x & %08x)\n", machine().describe_context(), data, mem_mask); m_ctrl ^= data & 0xf0; + if (data & 0x80 || data & 0x20) + { + m_ctrl &= ~0xf000; + m_ctrl |= 0x2000; + } break; default: logerror("%s: iop_w: Unknown write %08x = %08x & %08x\n", machine().describe_context(), 0x1d000000 + (offset << 2), data, mem_mask); @@ -175,8 +184,10 @@ uint32_t ps2_sif_device::fifo_pop(uint32_t channel) { assert(channel < 2); assert(m_fifo_curr[channel] > 0); + uint32_t ret = m_fifo[channel][0]; m_fifo_curr[channel]--; - return m_fifo[channel][m_fifo_curr[channel]]; + memcpy(&m_fifo[channel][0], &m_fifo[channel][1], sizeof(uint32_t) * m_fifo_curr[channel]); + return ret; } void ps2_sif_device::fifo_push(uint32_t channel, uint32_t value) diff --git a/src/mame/machine/ps2sif.h b/src/mame/machine/ps2sif.h index c0c02d30b83..2b1dd978047 100644 --- a/src/mame/machine/ps2sif.h +++ b/src/mame/machine/ps2sif.h @@ -38,6 +38,8 @@ public: void fifo_push(uint32_t channel, uint32_t value); uint32_t fifo_pop(uint32_t channel); + static const size_t MAX_FIFO_DEPTH; + protected: virtual void device_start() override; virtual void device_reset() override; @@ -52,8 +54,6 @@ protected: std::unique_ptr m_fifo[2]; uint32_t m_fifo_curr[2]; - - static const size_t MAX_FIFO_DEPTH; }; DECLARE_DEVICE_TYPE(SONYPS2_SIF, ps2_sif_device) -- cgit v1.2.3