summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/powerpc/ppcdrc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/powerpc/ppcdrc.cpp')
-rw-r--r--src/devices/cpu/powerpc/ppcdrc.cpp33
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 */