diff options
author | 2025-03-26 17:58:40 +1100 | |
---|---|---|
committer | 2025-03-26 17:58:40 +1100 | |
commit | 9fd89a456e9610a4d55a4b2210d45f0c20633ef0 (patch) | |
tree | 395254023290696fe5e8cc0316eb2696d3e44912 /src | |
parent | 221f40f1b15b652bea634d61e4fe066829ef1e81 (diff) |
cpu/e132xs: Call debugger exception hook for TRAP instructions.
Also made cycle counts a bit more consistent between interpreter and
recompiler for exceptions and traps.
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/e132xs/e132xs.cpp | 10 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xs.h | 4 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xsdrc.cpp | 45 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xsdrc_ops.hxx | 30 |
4 files changed, 36 insertions, 53 deletions
diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index cadeb2bc1d6..c98c5f0801b 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -707,8 +707,11 @@ void hyperstone_device::hyperstone_br() m_core->icount -= m_core->clock_cycles_2; } -void hyperstone_device::execute_trap(uint32_t addr) +void hyperstone_device::execute_trap(uint8_t trapno) { + debugger_exception_hook(int(unsigned(trapno))); + + const uint32_t addr = get_trap_addr(trapno); const uint8_t reg = GET_FP + GET_FL; SET_ILC(m_instruction_length); const uint32_t oldSR = SR; @@ -1424,18 +1427,17 @@ void hyperstone_device::hyperstone_trap() check_delay_PC(); const uint8_t trapno = (m_op & 0xfc) >> 2; - const uint32_t addr = get_trap_addr(trapno); const uint8_t code = ((m_op & 0x300) >> 6) | (m_op & 0x03); if (trap_if_set[code]) { if (SR & conditions[code]) - execute_trap(addr); + execute_trap(trapno); } else { if (!(SR & conditions[code])) - execute_trap(addr); + execute_trap(trapno); } } diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index f6b9daf0f8e..da374ece776 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -346,7 +346,7 @@ private: void ignore_pcrel(); void hyperstone_br(); - void execute_trap(uint32_t addr); + void execute_trap(uint8_t trapno); void execute_int(uint32_t addr); void execute_exception(uint8_t trapno); void execute_software(); @@ -475,7 +475,7 @@ private: void static_generate_exception(drcuml_block &block, uml::code_label &label); void static_generate_interrupt_checks(drcuml_block &block, uml::code_label &label); void generate_interrupt_checks(drcuml_block &block, uml::code_label &labelnum, bool with_timer, int take_int, int take_timer); - void generate_branch(drcuml_block &block, uml::parameter mode, uml::parameter targetpc, const opcode_desc *desc, bool update_cycles = true); + void generate_branch(drcuml_block &block, uml::parameter mode, uml::parameter targetpc, const opcode_desc *desc); void generate_update_cycles(drcuml_block &block); void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); diff --git a/src/devices/cpu/e132xs/e132xsdrc.cpp b/src/devices/cpu/e132xs/e132xsdrc.cpp index a6bd669db51..1684b4221b9 100644 --- a/src/devices/cpu/e132xs/e132xsdrc.cpp +++ b/src/devices/cpu/e132xs/e132xsdrc.cpp @@ -327,44 +327,12 @@ static inline void alloc_handle(drcuml_state &drcuml, uml::code_handle *&handlep void hyperstone_device::static_generate_exception(drcuml_block &block, uml::code_label &label) { - /* add a global entry for this */ + // add a global entry for this alloc_handle(*m_drcuml, m_exception, "exception"); UML_HANDLE(block, *m_exception); - UML_GETEXP(block, I0); // I0 = exception code - if (machine().debug_flags & DEBUG_FLAG_ENABLED) - { - UML_MOV(block, mem(&m_core->arg0), I0); // let the debugger know - UML_CALLC(block, &c_funcs::debugger_exception_hook, this); - } - generate_get_trap_addr(block, label, uml::I0); // I0 = target PC - - UML_MOV(block, I4, DRC_SR); // I4 = old SR - - UML_MOV(block, I1, I4); // I1 = SR to be updated - UML_ROLAND(block, I3, I4, 32 - FP_SHIFT, 0x7f); // I3 = old FP - UML_ROLAND(block, I2, I4, 32 - FL_SHIFT, 0xf); // I2 = old FL - UML_MOVc(block, uml::COND_Z, I2, 16); // convert FL == 0 to 16 - UML_ADD(block, I3, I3, I2); // I3 = updated FP - - UML_SHL(block, I2, I3, FP_SHIFT); // I2 = updated FP:... - UML_OR(block, I2, I2, (2 << FL_SHIFT) | S_MASK | L_MASK); // I2 = updated FP:FL:..:S:..T:L:..:M:.. - UML_ROLINS(block, I1, I2, 0, FP_MASK | FL_MASK | S_MASK | T_MASK | L_MASK | M_MASK); - UML_MOV(block, DRC_SR, I1); // store updated SR - - UML_AND(block, I3, I3, 0x3f); // save old PC at updated (FP)^ - UML_AND(block, I2, DRC_PC, ~uint32_t(1)); - UML_ROLINS(block, I2, I4, 32 - S_SHIFT, 1); - UML_STORE(block, (void *)m_core->local_regs, I3, I2, SIZE_DWORD, SCALE_x4); - UML_ADD(block, I3, I3, 1); // save old SR at updated (FP + 1)^ - UML_AND(block, I3, I3, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I3, I4, SIZE_DWORD, SCALE_x4); - - UML_MOV(block, DRC_PC, I0); // branch to exception handler - UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), 2); - UML_CALLHc(block, uml::COND_S, *m_out_of_cycles); - - UML_HASHJMP(block, 1, I0, *m_nocode); // T cleared and S set - mode will always be 1 + UML_GETEXP(block, I0); + generate_trap_exception_or_int<IS_EXCEPTION>(block, label, uml::I0); } @@ -728,17 +696,16 @@ void hyperstone_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, generate_branch ------------------------------------------------------------------*/ -void hyperstone_device::generate_branch(drcuml_block &block, uml::parameter mode, uml::parameter targetpc, const opcode_desc *desc, bool update_cycles) +void hyperstone_device::generate_branch(drcuml_block &block, uml::parameter mode, uml::parameter targetpc, const opcode_desc *desc) { // clobbers I0 and I1 if mode is BRANCH_TARGET_DYNAMIC if (desc) UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); - if (update_cycles) - generate_update_cycles(block); + generate_update_cycles(block); - /* update the cycles and jump through the hash table to the target */ + // update the cycles and jump through the hash table to the target const uml::parameter pc = (targetpc != BRANCH_TARGET_DYNAMIC) ? targetpc : DRC_PC; const uml::parameter m = (mode != BRANCH_TARGET_DYNAMIC) ? mode : uml::I0; if (mode == BRANCH_TARGET_DYNAMIC) diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index 331d61a764f..84388714cc2 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -471,11 +471,20 @@ void hyperstone_device::generate_update_flags_addsubs(drcuml_block &block, compi template <hyperstone_device::trap_exception_or_int TYPE> void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block, uml::code_label &label, uml::parameter trapno) { - // expects exception handler address in I0 and cycles in I7 (updated) + // expects cycles in I7 (updated) // clobbers I0, I1, I2, I3 and I4 + const uint32_t set_flags = (TYPE == IS_INT) ? (S_MASK | L_MASK | I_MASK) : (S_MASK | L_MASK); + const uint32_t clear_flags = T_MASK | M_MASK; + const uint32_t update_sr = FP_MASK | FL_MASK | set_flags | clear_flags; + UML_ADD(block, I7, I7, mem(&m_core->clock_cycles_2)); + if ((TYPE != IS_INT) && (machine().debug_flags & DEBUG_FLAG_ENABLED)) + { + UML_MOV(block, mem(&m_core->arg0), trapno); // let the debugger know + UML_CALLC(block, &c_funcs::debugger_exception_hook, this); + } generate_get_trap_addr(block, label, trapno); // I0 = target PC UML_MOV(block, I4, DRC_SR); // I4 = old SR @@ -487,9 +496,8 @@ void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block, uml: UML_ADD(block, I3, I3, I2); // I3 = updated FP UML_SHL(block, I2, I3, FP_SHIFT); // I2 = updated FP:... - UML_OR(block, I2, I2, ((TYPE != IS_TRAP) ? 2 : 6) << FL_SHIFT); // I2 = updated FP:FL:... - UML_ROLINS(block, I1, I2, 0, FP_MASK | FL_MASK | M_MASK | T_MASK);// update FP and FL, clear M and T, set S and L, set I for INT - UML_OR(block, I1, I1, (TYPE == IS_INT) ? (S_MASK | L_MASK | I_MASK) : (S_MASK | L_MASK)); + UML_OR(block, I2, I2, (((TYPE != IS_TRAP) ? 2 : 6) << FL_SHIFT) | set_flags); + UML_ROLINS(block, I1, I2, 0, update_sr); // update SR value UML_MOV(block, DRC_SR, I1); // store updated SR UML_AND(block, I3, I3, 0x3f); // save old PC at updated (FP)^ @@ -500,8 +508,10 @@ void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block, uml: UML_AND(block, I3, I3, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I3, I4, SIZE_DWORD, SCALE_x4); + UML_ADD(block, I7, I7, mem(&m_core->clock_cycles_2)); // assume exception dispatch takes two cycles UML_MOV(block, DRC_PC, I0); // branch to exception handler - generate_branch(block, 1, uml::I0, nullptr, true); // T cleared and S set - mode will always be 1 + + generate_branch(block, 1, uml::I0, nullptr); // T cleared and S set - mode will always be 1 } void hyperstone_device::generate_int(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t addr) @@ -1003,6 +1013,7 @@ void hyperstone_device::generate_xm(drcuml_block &block, compiler_state &compile UML_SHL(block, I0, I1, sub_type & 3); + // FIXME: exception before branch generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true); if (sub_type < 4) @@ -1102,6 +1113,7 @@ void hyperstone_device::generate_sums(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); + // FIXME: exception before branch generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true); generate_trap_on_overflow(block, compiler, desc, uml::I2); } @@ -1290,6 +1302,7 @@ void hyperstone_device::generate_adds(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); + // FIXME: exception before branch generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false); generate_trap_on_overflow(block, compiler, desc, uml::I2); } @@ -1403,6 +1416,7 @@ void hyperstone_device::generate_subs(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); + // FIXME: exception before branch generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false); generate_trap_on_overflow(block, compiler, desc, uml::I2); } @@ -1493,6 +1507,7 @@ void hyperstone_device::generate_negs(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); + // FIXME: exception before branch generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true); if (!SRC_GLOBAL || (src_code != SR_REGISTER)) // negating carry cannot result in overflow @@ -4086,12 +4101,11 @@ void hyperstone_device::generate_trap_op(drcuml_block &block, compiler_state &co }; const uint16_t op = desc->opptr.w[0]; - - generate_check_delay_pc(block, compiler, desc); - const uint8_t trapno = (op & 0xfc) >> 2; const uint8_t code = ((op & 0x300) >> 6) | (op & 0x03); + generate_check_delay_pc(block, compiler, desc); + UML_TEST(block, DRC_SR, conditions[code]); const int skip_trap = compiler.m_labelnum++; |