diff options
Diffstat (limited to 'src/devices/cpu/unsp/unspdrc.cpp')
-rw-r--r-- | src/devices/cpu/unsp/unspdrc.cpp | 58 |
1 files changed, 26 insertions, 32 deletions
diff --git a/src/devices/cpu/unsp/unspdrc.cpp b/src/devices/cpu/unsp/unspdrc.cpp index 6a12a58a762..32011522c2e 100644 --- a/src/devices/cpu/unsp/unspdrc.cpp +++ b/src/devices/cpu/unsp/unspdrc.cpp @@ -414,19 +414,13 @@ void unsp_device::static_generate_trigger_fiq() alloc_handle(*m_drcuml, m_trigger_fiq, "trigger_fiq"); UML_HANDLE(block, *m_trigger_fiq); - UML_OR(block, I0, mem(&m_core->m_fiq), mem(&m_core->m_irq)); - UML_TEST(block, I0, 1); - UML_RETc(block, uml::COND_NZ); - UML_TEST(block, mem(&m_core->m_enable_fiq), 1); UML_RETc(block, uml::COND_Z); - UML_MOV(block, mem(&m_core->m_fiq), 1); + UML_TEST(block, mem(&m_core->m_fiq), 1); + UML_RETc(block, uml::COND_NZ); - UML_MOV(block, I0, mem(&m_core->m_sb)); - UML_MOV(block, I1, mem(&m_core->m_irq)); - UML_STORE(block, (void*)m_core->m_saved_sb, I1, I0, SIZE_DWORD, SCALE_x4); - UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[2])); + UML_MOV(block, mem(&m_core->m_fiq), 1); UML_MOV(block, I0, mem(&m_core->m_r[REG_SP])); @@ -455,21 +449,34 @@ void unsp_device::static_generate_trigger_irq() /* begin generating */ drcuml_block &block(m_drcuml->begin_block(256)); + uml::code_label skip_ine = 1; + /* generate a hash jump via the current mode and PC */ alloc_handle(*m_drcuml, m_trigger_irq, "trigger_irq"); UML_HANDLE(block, *m_trigger_irq); - UML_OR(block, I0, mem(&m_core->m_fiq), mem(&m_core->m_irq)); - UML_TEST(block, I0, 1); + // If INE is 0 and IRQ is 1, abort + UML_XOR(block, I1, mem(&m_core->m_irq), 1); + UML_AND(block, I1, I1, mem(&m_core->m_ine)); UML_RETc(block, uml::COND_NZ); - UML_TEST(block, mem(&m_core->m_enable_irq), 1); - UML_RETc(block, uml::COND_Z); + // If INE is 0 and IRQ is 0, we have a valid IRQ + UML_TEST(block, mem(&m_core->m_ine), 1); + UML_JMPc(block, uml::COND_Z, skip_ine); + + // If INE is 1 and IRQ line is < PRI, abort + UML_CMP(block, I0, mem(&m_core->m_pri)); + UML_RETc(block, uml::COND_LE); + + // Update our current interrupt priority + UML_MOV(block, mem(&m_core->m_pri), I0); + + UML_LABEL(block, skip_ine); UML_MOV(block, mem(&m_core->m_irq), 1); - UML_MOV(block, mem(&m_core->m_saved_sb[0]), mem(&m_core->m_sb)); - UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[1])); + UML_TEST(block, mem(&m_core->m_enable_irq), 1); + UML_RETc(block, uml::COND_Z); UML_MOV(block, I0, mem(&m_core->m_r[REG_SP])); UML_MOV(block, I1, mem(&m_core->m_r[REG_PC])); @@ -707,8 +714,6 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const uint8_t lower_op = (op1 << 4) | op0; uml::code_label skip_branch = compiler.m_labelnum++; - uml::code_label clear_fiq = compiler.m_labelnum++; - uml::code_label clear_irq = compiler.m_labelnum++; uml::code_label reti_done = compiler.m_labelnum++; uml::code_label mul_opa_nohi = compiler.m_labelnum++; uml::code_label mul_opb_nohi = compiler.m_labelnum++; @@ -849,24 +854,13 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff); UML_TEST(block, mem(&m_core->m_fiq), 1); - UML_JMPc(block, uml::COND_NZ, clear_fiq); - UML_TEST(block, mem(&m_core->m_irq), 1); - UML_JMPc(block, uml::COND_NZ, clear_irq); - UML_JMP(block, reti_done); + UML_MOVc(block, uml::COND_NZ, mem(&m_core->m_fiq), 0); + UML_JMPc(block, uml::COND_NZ, reti_done); - UML_LABEL(block, clear_fiq); - UML_MOV(block, mem(&m_core->m_fiq), 0); - UML_MOV(block, mem(&m_core->m_saved_sb[2]), mem(&m_core->m_sb)); - UML_LOAD(block, mem(&m_core->m_sb), (void*)m_core->m_saved_sb, mem(&m_core->m_irq), SIZE_DWORD, SCALE_x4); - UML_JMP(block, reti_done); - - UML_LABEL(block, clear_irq); - UML_MOV(block, mem(&m_core->m_irq), 0); - UML_MOV(block, mem(&m_core->m_saved_sb[1]), mem(&m_core->m_sb)); - UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[0])); + UML_TEST(block, mem(&m_core->m_irq), 1); + UML_MOVc(block, uml::COND_NZ, mem(&m_core->m_irq), 0); UML_LABEL(block, reti_done); - UML_MOV(block, mem(&m_core->m_curirq), 0); generate_branch(block, compiler, desc); } else // pop |