diff options
| author | 2023-08-28 02:54:20 +0900 | |
|---|---|---|
| committer | 2023-08-28 03:54:20 +1000 | |
| commit | bced77dec95faea0a2adaa3de09dd1cb48b5ae92 (patch) | |
| tree | 3eb67c6d92715036192174bd2f647f7fed4243ad /src/devices/cpu/powerpc/ppcdrc.cpp | |
| parent | 59e8aef15e24d1e960ae2b4fbeb4974cfa87b52b (diff) | |
-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.
Diffstat (limited to 'src/devices/cpu/powerpc/ppcdrc.cpp')
| -rw-r--r-- | src/devices/cpu/powerpc/ppcdrc.cpp | 25 |
1 files changed, 20 insertions, 5 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); // <update cycles> return true; |
