From 1b54e2d6bfe000efa83d96a34f6735e8a8cd9322 Mon Sep 17 00:00:00 2001 From: arbee Date: Sat, 4 Jan 2025 19:34:43 -0500 Subject: cpu/powerpc: More support for the 601's POWER/PPC dual nature, including several POWER instructions. [R. Belmont] apple/macpdm.cpp: Implemented audio DMA IRQs and some minor cleanup. [R. Belmont] --- src/devices/cpu/powerpc/ppc.h | 11 ++- src/devices/cpu/powerpc/ppccom.cpp | 48 ++++++++++- src/devices/cpu/powerpc/ppccom.h | 10 ++- src/devices/cpu/powerpc/ppcdrc.cpp | 161 ++++++++++++++++++++++++++++++++++++- src/devices/cpu/powerpc/ppcfe.cpp | 85 ++++++++++++++++++++ src/mame/apple/macpdm.cpp | 126 +++++++++++++++++------------ 6 files changed, 381 insertions(+), 60 deletions(-) diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h index 905132c0034..ce715b59dc1 100644 --- a/src/devices/cpu/powerpc/ppc.h +++ b/src/devices/cpu/powerpc/ppc.h @@ -79,9 +79,18 @@ enum PPC_R30, PPC_R31, PPC_CR, + PPC_MQ, PPC_LR, PPC_CTR, PPC_XER, + PPC_BAT0U, + PPC_BAT0L, + PPC_BAT1U, + PPC_BAT1L, + PPC_BAT2U, + PPC_BAT2L, + PPC_BAT3U, + PPC_BAT3L, PPC_F0, PPC_F1, @@ -151,7 +160,6 @@ enum PPC_SR15 }; - /* compiler-specific options */ #define PPCDRC_STRICT_VERIFY 0x0001 /* verify all instructions */ #define PPCDRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ @@ -515,6 +523,7 @@ protected: uint32_t m_serial_clock; uint64_t m_tb_zero_cycles; uint64_t m_dec_zero_cycles; + uint64_t m_rtc_zero_cycles; emu_timer * m_decrementer_int_timer; diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp index 68ba52cf509..4e76a3efbb2 100644 --- a/src/devices/cpu/powerpc/ppccom.cpp +++ b/src/devices/cpu/powerpc/ppccom.cpp @@ -281,7 +281,7 @@ mpc8240_device::mpc8240_device(const machine_config &mconfig, const char *tag, d } ppc601_device::ppc601_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ppc_device(mconfig, PPC601, tag, owner, clock, 32, 64, PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT, 0/* no TB */, address_map_constructor()) + : ppc_device(mconfig, PPC601, tag, owner, clock, 32, 64, PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_MFIOC | PPCCAP_601BAT | PPCCAP_LEGACY_POWER, 0 /* no TB */, address_map_constructor()) { } @@ -727,6 +727,7 @@ void ppc_device::device_start() m_cpu_clock = 0; m_tb_zero_cycles = 0; m_dec_zero_cycles = 0; + m_rtc_zero_cycles = 0; m_arg1 = 0; m_fastram_select = 0; @@ -837,6 +838,11 @@ void ppc_device::device_start() state_add(PPC_PC, "PC", m_core->pc).formatstr("%08X"); state_add(PPC_MSR, "MSR", m_core->msr).formatstr("%08X"); state_add(PPC_CR, "CR", m_debugger_temp).callimport().callexport().formatstr("%08X"); + // If the legacy POWER instructions exist, that implies MQ is used and should be shown + if (m_cap & PPCCAP_LEGACY_POWER) + { + state_add(PPC_MQ, "MQ", m_core->spr[SPR601_MQ]).formatstr("%08X"); + } state_add(PPC_LR, "LR", m_core->spr[SPR_LR]).formatstr("%08X"); state_add(PPC_CTR, "CTR", m_core->spr[SPR_CTR]).formatstr("%08X"); state_add(PPC_XER, "XER", m_debugger_temp).callimport().callexport().formatstr("%08X"); @@ -1301,8 +1307,6 @@ uint32_t ppc_device::ppccom_translate_address_internal(int intention, bool debug uint32_t lower = m_core->spr[SPROEA_IBAT0U + 2*batnum + 1]; int privbit = ((intention & TR_USER) == 0) ? 3 : 2; -// printf("bat %d upper = %08x privbit %d\n", batnum, upper, privbit); - // is this pair valid? if (lower & 0x40) { @@ -1639,6 +1643,29 @@ void ppc_device::ppccom_execute_mfspr() } } + /* handle 601 specific SPRs (POWER holdovers) */ + if (m_flavor == PPC_MODEL_601) + { + switch (m_core->param0) + { + case SPR601_PWRDEC: + m_core->param1 = get_decrementer(); + return; + + case SPR601_RTCUR_PWR: + m_core->param1 = (total_cycles() - m_rtc_zero_cycles) / clock(); + return; + + case SPR601_RTCLR_PWR: + { + const uint64_t remainder = (total_cycles() - m_rtc_zero_cycles) % clock(); + const double seconds = remainder / clock(); // get fractional seconds + m_core->param1 = (uint64_t)(seconds * 1'000'000'000); // and convert to nanoseconds + } + return; + } + } + /* handle 602 SPRs */ if (m_flavor == PPC_MODEL_602) { // TODO: Which are read/write only? @@ -1782,6 +1809,21 @@ void ppc_device::ppccom_execute_mtspr() } } + /* handle 601 specific POWER-holdover SPRs */ + if (m_flavor == PPC_MODEL_601) + { + switch (m_core->param0) + { + case SPR601_MQ: + m_core->spr[m_core->param0] = m_core->param1; + return; + + case SPR601_RTCUW_PWR: + m_rtc_zero_cycles = total_cycles(); + break; + } + } + /* handle 602 SPRs */ if (m_flavor == PPC_MODEL_602) { diff --git a/src/devices/cpu/powerpc/ppccom.h b/src/devices/cpu/powerpc/ppccom.h index 00852c48b57..da12935a5cc 100644 --- a/src/devices/cpu/powerpc/ppccom.h +++ b/src/devices/cpu/powerpc/ppccom.h @@ -65,6 +65,7 @@ #define PPCCAP_601BAT 0x80 /* TRUE if we're doing 601-style BATs (unified I/D, different bit layout) */ #define PPCCAP_604_MMU 0x100 /* TRUE if we have 604-class MMU features */ #define PPCCAP_750_TLB 0x200 /* TRUE if we have the extended 740/750 series TLB */ +#define PPCCAP_LEGACY_POWER 0x400 /* TRUE if we support the legacy POWER instructions */ /* exception types */ enum @@ -171,6 +172,14 @@ enum SPR4XX_PBL2 = 0x3fe, /* R/W 403GA 406GA Protection Bound Lower 2 */ SPR4XX_PBU2 = 0x3ff, /* R/W 403GA 406GA Protection Bound Upper 2 */ + /* PowerPC 601 POWER back compatibility SPR indexes */ + SPR601_MQ = 0x000, /* R/W Muliplicand/Quotient for 601 POWER instructions */ + SPR601_RTCUR_PWR = 0x004, /* R Counts up number set in SPR 20 once per second, POWER only */ + SPR601_RTCLR_PWR = 0x005, /* R Number of nanoseconds between the seconds counted in SPR 4 */ + SPR601_PWRDEC = 0x006, /* R Decrementer register mirror for POWER compatibilty */ + SPR601_RTCUW_PWR = 0x014, /* W Seconds counter, set here and read SPR 4 */ + SPR601_RTCLW_PWR = 0x015, /* W Nanoseconds counter, not clear what writing here does */ + /* PowerPC 602 SPR register indexes */ SPR602_TCR = 0x3d8, /* 602 */ SPR602_IBR = 0x3da, /* 602 */ @@ -198,7 +207,6 @@ enum SPR603_HID2 = 0x3f3 /* R/W 603 */ }; - /* PowerPC 4XX DCR register indexes */ enum { diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index 64d19498d12..06da8344592 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles /*************************************************************************** - ppcdrc.c + ppcdrc.cpp Universal machine language-based PowerPC emulator. @@ -1746,12 +1746,12 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta UML_EXH(block, *m_tlb_mismatch, 0); // exh tlb_mismatch,0 } - /* validate our TLB entry at this PC; if we fail, we need to handle it */ - if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION)) + // validate our TLB entry at this PC; if we fail, we need to handle it + // TODO: this code is highly sus based on the PPC architecture manual, but I'll only disable for 601 for now + if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION) && !(m_cap & PPCCAP_601BAT)) { const vtlb_entry *tlbtable = vtlb_table(); - /* if we currently have a valid TLB read entry, we just verify */ if (tlbtable[desc->pc >> 12] != 0) { if (PRINTF_MMU) @@ -2024,6 +2024,23 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler, // muls rd,rd,ra,simm return true; + case 0x9: /* DOZI (POWER) */ + assert(m_cap & PPCCAP_LEGACY_POWER); + + UML_AND(block, I0, op, 0xffff); + UML_CMP(block, R32(G_RA(op)), I0); // cmp ra, I0 + UML_JMPc(block, COND_B, compiler->labelnum); // bae 0: + + UML_XOR(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RD(op))); // xor rd, rd, rd (rd = 0) + UML_JMP(block, compiler->labelnum + 1); // jmp 1: + + UML_LABEL(block, compiler->labelnum++); // 0: + UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), I0); + UML_ADD(block, R32(G_RD(op)), R32(G_RD(op)), 0x1); + + UML_LABEL(block, compiler->labelnum++); // 1: + return true; + case 0x0e: /* ADDI */ UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), (int16_t)G_SIMM(op)); // add rd,ra,simm return true; @@ -2687,6 +2704,13 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false);// return true; + case 0x6b: /* MUL (POWER) */ + assert(m_cap & PPCCAP_LEGACY_POWER); + + UML_MULU(block, SPR32(SPR601_MQ), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulu mq, rd, ra, rb + generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV | XER_SO : 0), false); // + return true; + case 0x1cb: /* DIVWUx */ case 0x3cb: /* DIVWUOx */ UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0 @@ -2714,6 +2738,63 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co UML_LABEL(block, compiler->labelnum++); // 1: return true; + case 0x14b: /* DIV (POWER) */ + assert(m_cap & PPCCAP_LEGACY_POWER); + + UML_SHL(block, I0, R32(G_RB(op)), 32); // I0 = RA << 32 + UML_OR(block, I0, I0, SPR32(SPR601_MQ)); // I0 |= MQ + UML_CMP(block, I0, 0x0); // cmp I0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // bne 0: + + UML_MOV(block, R32(G_RD(op)), 0x0); // mov rd, #0 + if (op & M_OE) + { + UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1 + UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1 + } + if (op & M_RC) + { + UML_MOV(block, CR32(0), 0x2); // CR = EQ + UML_AND(block, CR32(0), CR32(0), ~0x1); + UML_OR(block, CR32(0), CR32(0), XERSO32); + } + + UML_JMP(block, compiler->labelnum + 1); // jmp 1: + + UML_LABEL(block, compiler->labelnum++); // 0: + UML_DIVS(block, R32(G_RD(op)), SPR32(SPR601_MQ), I0, R32(G_RB(op))); // divs rd,mq,I0,rb + generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV | XER_SO : 0), false); // + UML_LABEL(block, compiler->labelnum++); // 1: + return true; + + case 0x16b: /* DIVS (POWER) */ + assert(m_cap & PPCCAP_LEGACY_POWER); + + UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // bne 0: + + UML_MOV(block, R32(G_RD(op)), 0x0); // mov rd, #0 + if (op & M_OE) + { + UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1 + UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1 + } + if (op & M_RC) + { + UML_MOV(block, CR32(0), 0x2); // CR = EQ + UML_AND(block, CR32(0), CR32(0), ~0x1); + UML_OR(block, CR32(0), CR32(0), XERSO32); + } + + UML_JMP(block, compiler->labelnum + 1); // jmp 1: + + UML_LABEL(block, compiler->labelnum++); // 0: + UML_DIVS(block, R32(G_RD(op)), SPR32(SPR601_MQ), R32(G_RA(op)), R32(G_RB(op))); // divs rd,mq,ra,rb + generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false); // + + UML_LABEL(block, compiler->labelnum++); // 1: + return true; + case 0x1eb: /* DIVWx */ case 0x3eb: /* DIVWOx */ UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0 @@ -2767,6 +2848,78 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co UML_LABEL(block, compiler->labelnum++); // 3: return true; + case 0x108: /* DOZ (POWER) */ + assert(m_cap & PPCCAP_LEGACY_POWER); + + UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra, rb + UML_JMPc(block, COND_B, compiler->labelnum); // bae 0: + + UML_XOR(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RD(op))); // xor rd, rd, rd (rd = 0) + UML_JMP(block, compiler->labelnum+1); // jmp 1: + + UML_LABEL(block, compiler->labelnum++); // 0: + UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); + UML_ADD(block, R32(G_RD(op)), R32(G_RD(op)), 0x1); + + UML_LABEL(block, compiler->labelnum++); // 1: + if (op & M_OE) + { + UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1 + UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1 + } + if (op & M_RC) + { + UML_TEST(block, R32(G_RD(op)), ~0); // test rd,~0 + generate_compute_flags(block, desc, op & M_RC, 0, false); // + } + return true; + + case 0x168: /* ABS (POWER) */ + case 0x1e8: /* NABS (POWER) */ + assert(m_cap & PPCCAP_LEGACY_POWER); + + // is rA already the correct sign (positive for ABS, negative for NABS)? + UML_CMP(block, R32(G_RA(op)), 0); + if (op & 0x080) + { + UML_JMPc(block, COND_L, compiler->labelnum); // bl 0: + } + else + { + UML_JMPc(block, COND_GE, compiler->labelnum); // bge 0: + } + + UML_SUB(block, I0, 0, R32(G_RA(op))); // sub 0, ra (make positive) + UML_JMP(block, compiler->labelnum + 1); // jmp 1: + + UML_LABEL(block, compiler->labelnum++); // 0: + UML_MOV(block, I0, R32(G_RA(op))); + + UML_LABEL(block, compiler->labelnum++); // 1: + UML_MOV(block, R32(G_RD(op)), I0); // mov rd, I0 + if (op & M_RC) + { + UML_GETFLGS(block, I0, FLAG_Z | FLAG_V | FLAG_C | FLAG_S); // getflgs i0,zvcs + UML_LOAD(block, I0, m_cmp_cr_table, I0, SIZE_DWORD, SCALE_x4); // load i0,cmp_cr_table,i0,dword + } + if (op & M_OE) + { + UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso] + } + return true; + + case 0x21d: /* MASKIR (POWER) */ + UML_AND(block, I0, R32(G_RS(op)), R32(G_RB(op))); // and i0, rs, rb + UML_XOR(block, I1, R32(G_RB(op)), 0xffffffff); // xor i1, rb, 0xffffffff + UML_AND(block, I1, I1, R32(G_RA(op))); // and i1, i1, ra + UML_OR(block, R32(G_RA(op)), I0, I1); // or ra, i0, i1 + if (op & M_RC) + { + UML_GETFLGS(block, R32(G_RA(op)), FLAG_Z | FLAG_V | FLAG_C | FLAG_S); // getflgs i0,zvcs + UML_LOAD(block, I0, m_cmp_cr_table, I0, SIZE_DWORD, SCALE_x4); // load i0,cmp_cr_table,i0,dword + } + return true; + case 0x01c: /* ANDx */ UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // and ra,rs,rb generate_compute_flags(block, desc, op & M_RC, 0, false); // diff --git a/src/devices/cpu/powerpc/ppcfe.cpp b/src/devices/cpu/powerpc/ppcfe.cpp index 57ec36cd317..1e8fb105ee1 100644 --- a/src/devices/cpu/powerpc/ppcfe.cpp +++ b/src/devices/cpu/powerpc/ppcfe.cpp @@ -119,6 +119,16 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) desc.cycles = 2; // ??? return true; + case 0x09: // DOZI (POWER) + if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER)) + { + return false; + } + + GPR_USED_OR_ZERO(desc, G_RA(op)); + GPR_MODIFIED(desc, G_RD(op)); + return true; + case 0x0e: // ADDI case 0x0f: // ADDIS GPR_USED_OR_ZERO(desc, G_RA(op)); @@ -1156,6 +1166,81 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE; return true; + + case 0x14b: // DIV (POWER) + case 0x16b: // DIVS (POWER) + if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER)) + { + return false; + } + + GPR_USED(desc, G_RA(op)); + GPR_USED(desc, G_RB(op)); + GPR_MODIFIED(desc, G_RD(op)); + XER_OV_MODIFIED(desc); + XER_SO_MODIFIED(desc); + if (op & M_RC) + CR_MODIFIED(desc, 0); + return true; + + case 0x6b: // MUL (POWER) + if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER)) + { + return false; + } + + GPR_USED(desc, G_RA(op)); + GPR_USED(desc, G_RB(op)); + GPR_MODIFIED(desc, G_RD(op)); + XER_OV_MODIFIED(desc); + XER_SO_MODIFIED(desc); + if (op & M_RC) + CR_MODIFIED(desc, 0); + return true; + + case 0x108: // DOZ (POWER) + if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER)) + { + return false; + } + + GPR_USED(desc, G_RA(op)); + GPR_USED(desc, G_RB(op)); + GPR_MODIFIED(desc, G_RD(op)); + XER_OV_MODIFIED(desc); + XER_SO_MODIFIED(desc); + if (op & M_RC) + CR_MODIFIED(desc, 0); + return true; + + case 0x168: // ABS (POWER) + case 0x1e8: // NABS (POWER) + if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER)) + { + return false; + } + + GPR_USED(desc, G_RA(op)); + GPR_USED(desc, G_RB(op)); + GPR_MODIFIED(desc, G_RD(op)); + XER_OV_MODIFIED(desc); + XER_SO_MODIFIED(desc); + if (op & M_RC) + CR_MODIFIED(desc, 0); + return true; + + case 0x21d: // MASKIR (POWER) + if (!(m_ppc.m_cap & PPCCAP_LEGACY_POWER)) + { + return false; + } + + GPR_USED(desc, G_RS(op)); + GPR_USED(desc, G_RB(op)); + GPR_MODIFIED(desc, G_RA(op)); + if (op & M_RC) + CR_MODIFIED(desc, 0); + return true; } return false; diff --git a/src/mame/apple/macpdm.cpp b/src/mame/apple/macpdm.cpp index fdae8a86ed6..bcdfd82f776 100644 --- a/src/mame/apple/macpdm.cpp +++ b/src/mame/apple/macpdm.cpp @@ -26,9 +26,12 @@ namespace { -constexpr auto IO_CLOCK = 31.3344_MHz_XTAL; -constexpr auto ENET_CLOCK = 20_MHz_XTAL; -constexpr auto SOUND_CLOCK = 45.1584_MHz_XTAL; +static constexpr auto IO_CLOCK = 31.3344_MHz_XTAL; +static constexpr auto ENET_CLOCK = 20_MHz_XTAL; +static constexpr auto SOUND_CLOCK = 45.1584_MHz_XTAL; + +static constexpr u8 DMA2_IRQ_SND_IN = 0x01; +static constexpr u8 DMA2_IRQ_SND_OUT = 0x02; class macpdm_state : public driver_device { @@ -62,6 +65,8 @@ private: uint8_t m_irq_control = 0; + uint8_t m_dma_irq_1, m_dma_irq_2; + uint8_t m_via2_ier = 0, m_via2_ifr = 0, m_via2_sier = 0, m_via2_sifr = 0; uint64_t m_dma_scsi_buffer = 0; @@ -121,7 +126,7 @@ private: void fdc_irq(int state); void fdc_drq(int state); - [[maybe_unused]] void sound_irq(int state); + void recalc_dma_irqs(); void scsi_irq(int state); void scsi_drq(int state); @@ -166,8 +171,8 @@ private: uint8_t diag_r(offs_t offset); - uint8_t irq_control_r(); - void irq_control_w(uint8_t data); + uint8_t irq_control_r(offs_t offset); + void irq_control_w(offs_t offset, uint8_t data); void irq_main_set(uint8_t mask, int state); void via2_irq_main_set(uint8_t mask, int state); void via2_irq_slot_set(uint8_t mask, int state); @@ -228,19 +233,20 @@ macpdm_state::macpdm_state(const machine_config &mconfig, device_type type, cons m_macadb(*this, "macadb"), m_ram(*this, RAM_TAG), m_scc(*this, "scc"), - m_scsibus(*this, "scsibus"), - m_ncr53c94(*this, "scsibus:7:ncr53c94"), + m_scsibus(*this, "scsi"), + m_ncr53c94(*this, "scsi:7:ncr53c94"), m_fdc(*this, "fdc"), m_floppy(*this, "fdc:%d", 0U), - m_video(*this, "video") + m_video(*this, "video"), + m_dma_irq_1(0), + m_dma_irq_2(0) { m_cur_floppy = nullptr; } void macpdm_state::driver_init() { - m_maincpu->space().install_ram(0, m_ram->mask(), 0x3000000,m_ram->pointer()); - m_maincpu->space().nop_readwrite(m_ram->size(), 0xffffff, 0x3000000); + m_maincpu->space().install_ram(0, m_ram->mask(), 0, m_ram->pointer()); m_model_id = 0xa55a3011; // 7100 = a55a3012 // 8100 = a55a3013 @@ -281,23 +287,6 @@ void macpdm_state::driver_init() save_item(NAME(m_dma_floppy_offset)); save_item(NAME(m_dma_floppy_byte_count)); save_item(NAME(m_floppy_drq)); - - m_maincpu->space().install_read_tap(0x4000c2e0, 0x4000c2e7, 0, "cuda", [this](offs_t offset, u64 &data, u64 mem_mask) { - if(mem_mask == 0xffff000000000000) { - address_space *space; - offs_t badr = m_maincpu->state_int(PPC_R16); - m_maincpu->translate(AS_PROGRAM, device_memory_interface::TR_READ, badr, space); - logerror("cuda packet %08x : type %02x cmd %02x - %02x %02x %02x %02x bytecnt %04x\n", - badr, - space->read_byte(badr), - space->read_byte(badr+1), - space->read_byte(badr+2), - space->read_byte(badr+3), - space->read_byte(badr+4), - space->read_byte(badr+5), - space->read_word(badr+6)); - } - }); } void macpdm_state::driver_reset() @@ -342,20 +331,35 @@ void macpdm_state::driver_reset() m_video->set_vram_offset(0); } -uint8_t macpdm_state::irq_control_r() +uint8_t macpdm_state::irq_control_r(offs_t offset) { - return m_irq_control; + switch (offset) + { + case 0x0: + return m_irq_control; + + case 0x8: + return m_dma_irq_1; + + case 0xa: + return m_dma_irq_2; + } + + return 0; } -void macpdm_state::irq_control_w(uint8_t data) +void macpdm_state::irq_control_w(offs_t offset, uint8_t data) { - if((m_irq_control ^ data) & 0x40) { - m_irq_control = (m_irq_control & ~0xc0) | (data & 0x40); - m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); - } - if((data & 0xc0) == 0xc0 && (m_irq_control & 0x80)) { - m_irq_control &= 0x7f; - m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); + if (offset == 0) + { + if((m_irq_control ^ data) & 0x40) { + m_irq_control = (m_irq_control & ~0xc0) | (data & 0x40); + m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); + } + if((data & 0xc0) == 0xc0 && (m_irq_control & 0x80)) { + m_irq_control &= 0x7f; + m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); + } } } @@ -652,9 +656,21 @@ void macpdm_state::via1_irq(int state) irq_main_set(0x01, state); } -void macpdm_state::sound_irq(int state) +void macpdm_state::nmi_irq(int state) { - via2_irq_main_set(0x20, state); + irq_main_set(0x20, state); +} + +void macpdm_state::recalc_dma_irqs() +{ + if ((m_dma_irq_1 | m_dma_irq_2) != 0) + { + irq_main_set(0x10, ASSERT_LINE); + } + else + { + irq_main_set(0x10, CLEAR_LINE); + } } void macpdm_state::vblank_irq(int state) @@ -674,12 +690,16 @@ void macpdm_state::slot1_irq(int state) void macpdm_state::sndo_dma_irq(int state) { - // TODO + m_dma_irq_2 &= ~DMA2_IRQ_SND_OUT; + m_dma_irq_2 |= state ? DMA2_IRQ_SND_OUT : 0; + recalc_dma_irqs(); } void macpdm_state::sndi_dma_irq(int state) { - // TODO + m_dma_irq_2 &= ~DMA2_IRQ_SND_IN; + m_dma_irq_2 |= state ? DMA2_IRQ_SND_IN : 0; + recalc_dma_irqs(); } uint32_t macpdm_state::dma_badr_r() @@ -1044,7 +1064,7 @@ void macpdm_state::pdm_map(address_map &map) map(0x50f28000, 0x50f28007).rw(m_video, FUNC(mac_video_sonora_device::vctrl_r), FUNC(mac_video_sonora_device::vctrl_w)); - map(0x50f2a000, 0x50f2a000).rw(FUNC(macpdm_state::irq_control_r), FUNC(macpdm_state::irq_control_w)); + map(0x50f2a000, 0x50f2a00f).rw(FUNC(macpdm_state::irq_control_r), FUNC(macpdm_state::irq_control_w)); map(0x50f2c000, 0x50f2dfff).r(FUNC(macpdm_state::diag_r)); @@ -1082,8 +1102,10 @@ void macpdm_state::macpdm(machine_config &config) { PPC601(config, m_maincpu, 60000000); m_maincpu->set_addrmap(AS_PROGRAM, &macpdm_state::pdm_map); + m_maincpu->ppcdrc_set_options(PPCDRC_COMPATIBLE_OPTIONS); MAC_VIDEO_SONORA(config, m_video); + m_video->set_PDM(); m_video->screen_vblank().set(FUNC(macpdm_state::vblank_irq)); SPEAKER(config, "lspeaker").front_left(); @@ -1099,19 +1121,19 @@ void macpdm_state::macpdm(machine_config &config) m_awacs->add_route(1, "rspeaker", 1.0); NSCSI_BUS(config, m_scsibus); - NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsibus:1", default_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsibus:2", default_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsibus:3").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config( + NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk"); + NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:3").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config( [](device_t *device) { device->subdevice("cdda")->add_route(0, "^^lspeaker", 1.0); device->subdevice("cdda")->add_route(1, "^^rspeaker", 1.0); }); - NSCSI_CONNECTOR(config, "scsibus:4", default_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsibus:5", default_scsi_devices, "harddisk"); - NSCSI_CONNECTOR(config, "scsibus:6", default_scsi_devices, "harddisk"); - NSCSI_CONNECTOR(config, "scsibus:7").option_set("ncr53c94", NCR53C94).machine_config( + NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr53c94", NCR53C94).machine_config( [this] (device_t *device) { auto &ctrl = downcast(*device); @@ -1175,7 +1197,9 @@ void macpdm_state::macpdm(machine_config &config) m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_cuda->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); m_cuda->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); + m_cuda->nmi_callback().set(FUNC(macpdm_state::nmi_irq)); m_macadb->adb_data_callback().set(m_cuda, FUNC(cuda_device::set_adb_line)); + m_macadb->adb_power_callback().set(m_cuda, FUNC(cuda_device::set_adb_power)); config.set_perfect_quantum(m_maincpu); TIMER(config, "beat_60_15").configure_periodic(FUNC(macpdm_state::via1_60_15_timer), attotime::from_double(1/60.15)); -- cgit v1.2.3