diff options
Diffstat (limited to 'src/devices/cpu/powerpc/ppcdrc.cpp')
-rw-r--r-- | src/devices/cpu/powerpc/ppcdrc.cpp | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index 6c98830bb96..741e75f9cc2 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 } } @@ -1922,8 +1942,11 @@ void ppc_device::generate_branch(drcuml_block *block, compiler_state *compiler, } else { - generate_update_cycles(block, &compiler_temp, mem(srcptr), true); // <subtract cycles> - UML_HASHJMP(block, m_core->mode, mem(srcptr), *m_nocode); // hashjmp <mode>,<rsreg>,nocode + generate_update_cycles(block, &compiler_temp, mem(srcptr), true); // <subtract cycles> + + /* clear two LSBs of the target address to prevent branching to an invalid address */ + UML_AND(block, I0, mem(srcptr), 0xFFFFFFFC); // and i0, 0xFFFFFFFC + UML_HASHJMP(block, m_core->mode, I0, *m_nocode); // hashjmp <mode>,i0,nocode } /* update the label */ |