From bced77dec95faea0a2adaa3de09dd1cb48b5ae92 Mon Sep 17 00:00:00 2001 From: 987123879113 <63495610+987123879113@users.noreply.github.com> Date: Mon, 28 Aug 2023 02:54:20 +0900 Subject: -cpu/powerpc: Don't overwrite RA in lmw instruction. (#11512) * For 4xx series and 601, skip over the register update. * For any other flavor, raise an illegal instruction exception. -konami/stingnet: Added ATA CS1 to address map, and removed comment about crash which has been fixed. --- src/devices/cpu/powerpc/ppcdrc.cpp | 25 ++++++++++++++++++++----- src/devices/cpu/powerpc/ppcfe.cpp | 17 +++++++++++++++-- src/mame/konami/stingnet.cpp | 6 +----- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index b1f2a2a2568..1905e1eb1d6 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -2256,12 +2256,27 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler, case 0x2e: /* LMW */ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) UML_MOV(block, mem(&m_core->tempaddr), R32Z(G_RA(op))); // mov [tempaddr],ra - for (int regnum = G_RD(op); regnum < 32; regnum++) + + if (G_RD(op) <= G_RA(op) && !(m_cap & PPCCAP_4XX) && m_flavor != PPC_MODEL_601) + { + // RA being in the range is an invalid form + // 403 and 405 manual allows writes where regnum != RA || regnum == 31, regnum == RA is skipped + // 601 user manual lists no special rules for R31 being valid but regnum == RA is skipped + // 603 and above just says it's an invalid form + // tropchnc (403GA) is known to use this behavior + UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000 + } + else { - UML_ADD(block, I0, mem(&m_core->tempaddr), (int16_t)G_SIMM(op) + 4 * (regnum - G_RD(op))); - // add i0,[tempaddr],simm + 4*(regnum-rd) - UML_CALLH(block, *m_read32align[m_core->mode]); // callh read32align - UML_MOV(block, R32(regnum), I0); // mov regnum,i0 + for (int regnum = G_RD(op); regnum < 32; regnum++) + { + UML_ADD(block, I0, mem(&m_core->tempaddr), (int16_t)G_SIMM(op) + 4 * (regnum - G_RD(op))); + // add i0,[tempaddr],simm + 4*(regnum-rd) + UML_CALLH(block, *m_read32align[m_core->mode]); // callh read32align + + if (regnum != G_RA(op) || ((m_cap & PPCCAP_4XX) && regnum == 31)) + UML_MOV(block, R32(regnum), I0); // mov regnum,i0 + } } generate_update_cycles(block, compiler, desc->pc + 4, true); // return true; diff --git a/src/devices/cpu/powerpc/ppcfe.cpp b/src/devices/cpu/powerpc/ppcfe.cpp index bbb8b4ff4f0..f4abd4a9004 100644 --- a/src/devices/cpu/powerpc/ppcfe.cpp +++ b/src/devices/cpu/powerpc/ppcfe.cpp @@ -289,8 +289,21 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x2e: // LMW GPR_USED_OR_ZERO(desc, G_RA(op)); - for (regnum = G_RD(op); regnum < 32; regnum++) - GPR_MODIFIED(desc, regnum); + + if (G_RD(op) <= G_RA(op) && !(m_ppc.m_cap & PPCCAP_4XX) && !is_601_class()) + { + // Undefined invalid form that has different behavior between CPUs + // See ppcdrc.cpp for a more detailed explanation + desc.flags |= OPFLAG_INVALID_OPCODE; + } + else + { + for (regnum = G_RD(op); regnum < 32; regnum++) + { + if (regnum != G_RA(op) || ((m_ppc.m_cap & PPCCAP_4XX) && regnum == 31)) + GPR_MODIFIED(desc, regnum); + } + } desc.flags |= OPFLAG_READS_MEMORY; desc.cycles = 32 - G_RD(op); return true; diff --git a/src/mame/konami/stingnet.cpp b/src/mame/konami/stingnet.cpp index b9465b380ed..49ca89ca635 100755 --- a/src/mame/konami/stingnet.cpp +++ b/src/mame/konami/stingnet.cpp @@ -15,11 +15,6 @@ GC965 Magic Timer Poker GC966 Joker Time GC967 Egyptian Slot - - TODO: With VBL IRQs working, the deferred function to load the first stage boot from the CD-ROM is jumped to - at 0xFFFA9578 but it immediately hits an alignment fault trying to store a 32-bit word to a 16-bit aligned - address. (Does the 403 maybe not have that exception? The PPC architecture docs indicate it's not a requirement - for all implementations. Or is this an early security failure?). */ #include "emu.h" @@ -94,6 +89,7 @@ void stingnet_state::main_map(address_map &map) map(0x71000000, 0x71000007).noprw(); // TODO: what is going on here? map(0x71000010, 0x71000013).ram(); map(0x72000000, 0x7200000f).rw(m_ata, FUNC(ata_interface_device::cs0_r), FUNC(ata_interface_device::cs0_w)); + map(0x72000010, 0x7200001f).rw(m_ata, FUNC(ata_interface_device::cs1_r), FUNC(ata_interface_device::cs1_w)); map(0x73000000, 0x730000ff).rw(m_gcu, FUNC(k057714_device::read), FUNC(k057714_device::write)); map(0x7ff00000, 0x7ff7ffff).mirror(0x00080000).rom().region("program", 0); } -- cgit v1.2.3