diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h index c51823fb208..b5db869b111 100644 --- a/src/devices/cpu/powerpc/ppc.h +++ b/src/devices/cpu/powerpc/ppc.h @@ -243,6 +243,7 @@ public: void ppccom_tlb_flush(); void ppccom_execute_mfdcr(); void ppccom_execute_mtdcr(); + void ppccom_get_dsisr(); protected: // device-level overrides diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp index 2030489da00..bea641ad95f 100644 --- a/src/devices/cpu/powerpc/ppccom.cpp +++ b/src/devices/cpu/powerpc/ppccom.cpp @@ -1497,6 +1497,27 @@ void ppc_device::ppccom_tlb_flush() OPCODE HANDLING ***************************************************************************/ +/*------------------------------------------------- + ppccom_get_dsisr - gets the DSISR value for a + failing TLB lookup's data access exception. +-------------------------------------------------*/ + +void ppc_device::ppccom_get_dsisr() +{ + int intent = 0; + + if (m_core->param1 & 1) + { + intent = TRANSLATE_WRITE; + } + else + { + intent = TRANSLATE_READ; + } + + m_core->param1 = ppccom_translate_address_internal(intent, m_core->param0); +} + /*------------------------------------------------- ppccom_execute_tlbie - execute a TLBIE instruction diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index 6c98830bb96..58cc8c7dc57 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -642,6 +642,11 @@ static void cfunc_ppccom_execute_mtdcr(void *param) ppc->ppccom_execute_mtdcr(); } +static void cfunc_ppccom_get_dsisr(void *param) +{ + ppc_device *ppc = (ppc_device *)param; + ppc->ppccom_get_dsisr(); +} /*************************************************************************** STATIC CODEGEN @@ -784,7 +789,11 @@ void ppc_device::static_generate_tlb_mismatch() UML_LABEL(block, isi); // isi: if (!(m_cap & PPCCAP_603_MMU)) { - UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param0)); // mov [dsisr],[param0] + // DAR gets the address, DSISR gets the 'reason' flags + UML_MOV(block, SPR32(SPROEA_DAR), mem(&m_core->param0)); // mov [dar],[param0] + m_core->param1 = 0; // always a read here + UML_CALLC(block, (c_function)cfunc_ppccom_get_dsisr, this); // get DSISR to param1 + UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param1)); // move [dsisr], [param1] UML_EXH(block, *m_exception[EXCEPTION_ISI], I0); // exh isi,i0 } else @@ -1389,8 +1398,19 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite /* general case: DSI exception */ else { - UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param0)); // mov [dsisr],[param0] - UML_EXH(block, *m_exception[EXCEPTION_DSI], I0); // exh dsi,i0 + UML_MOV(block, SPR32(SPROEA_DAR), mem(&m_core->param0)); // mov [dar],[param0] + // signal read or write to cfunc to get proper reason back + if (iswrite) + { + m_core->param1 = 1; + } + else + { + m_core->param1 = 0; + } + UML_CALLC(block, (c_function)cfunc_ppccom_get_dsisr, this); // get DSISR to param1 + UML_MOV(block, SPR32(SPROEA_DSISR), mem(&m_core->param1)); // move [dsisr], [param1] + UML_EXH(block, *m_exception[EXCEPTION_DSI], I0); // exh dsi,i0 } }