mirror of
https://github.com/holub/mame
synced 2025-10-07 17:27:06 +03:00
-ps2sony: Various DMA and SIF bug fixes, initial OSDSYS ELF transfers to IOP now, but EE and IOP hang immediately thereafter. nw
This commit is contained in:
parent
8fe31f857d
commit
f3ccd1f7f2
@ -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 */
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -1092,6 +1092,7 @@ void r3000_device::execute_run()
|
||||
fflush(stdout);
|
||||
}
|
||||
*/
|
||||
|
||||
// instruction fetch
|
||||
m_op = readop(m_pc);
|
||||
|
||||
|
@ -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);
|
||||
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);
|
||||
|
||||
// ??
|
||||
m_sif->fifo_pop(1);
|
||||
m_sif->fifo_pop(1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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<iop_intc_device> m_intc;
|
||||
required_shared_ptr<uint32_t> m_ram;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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())
|
||||
{
|
||||
if (channel.end_tag())
|
||||
{
|
||||
printf("end\n");
|
||||
transfer_finish(SIF0);
|
||||
}
|
||||
else if (m_sif->fifo_depth(0) >= 2)
|
||||
{
|
||||
printf("follow\n");
|
||||
}
|
||||
else
|
||||
logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context());
|
||||
transfer_finish(SIF0);
|
||||
}
|
||||
else if (m_sif->fifo_depth(0) >= 2)
|
||||
{
|
||||
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)
|
||||
{
|
||||
channel.set_end_tag(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ps2_dmac_device::follow_tag(uint32_t channel)
|
||||
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_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;
|
||||
}
|
||||
}
|
@ -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<cpu_device> m_ee;
|
||||
|
@ -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)
|
||||
|
@ -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<uint32_t[]> m_fifo[2];
|
||||
uint32_t m_fifo_curr[2];
|
||||
|
||||
static const size_t MAX_FIFO_DEPTH;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SONYPS2_SIF, ps2_sif_device)
|
||||
|
Loading…
Reference in New Issue
Block a user