From 213e1b58572895b9f93fcfbfd8607925fd49d22c Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 26 Mar 2025 08:38:27 +1100 Subject: [PATCH] cpu/e132xs: Moved interrupt check to the beginning of instruction execution. * Fixes interrupts not being serviced while tracing. * Further improves recompiler performance. * Fixes recompiler interrupt check function calling itself recursively. * Also added debugger exception hook calls to interpreter and recompiler. --- src/devices/cpu/e132xs/e132xs.cpp | 254 ++++++++--------------- src/devices/cpu/e132xs/e132xs.h | 52 +++-- src/devices/cpu/e132xs/e132xsdrc.cpp | 172 +++++++-------- src/devices/cpu/e132xs/e132xsdrc_ops.hxx | 95 ++++++--- src/devices/cpu/e132xs/e132xsop.hxx | 26 +-- 5 files changed, 271 insertions(+), 328 deletions(-) diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index d34e8438c16..cadeb2bc1d6 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -37,7 +37,6 @@ - What actually happens on trying to load memory to PC or SR? - Verify register wrapping with sregf/dregf on hardware - Tracing doesn't work properly - Interrupts are not serviced while tracing DRC does not generate trace exceptions on branch or return - Interpreter does not implement privilege check on setting L flag - DRC does not update ILC and P on some privilege error exceptions @@ -159,7 +158,7 @@ e116t_device::e116t_device(const machine_config &mconfig, const char *tag, devic //------------------------------------------------- e116xt_device::e116xt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : hyperstone_device(mconfig, tag, owner, clock, E116XT, 16, 16, address_map_constructor(FUNC(e116t_device::e116_8k_iram_map), this)) + : hyperstone_device(mconfig, tag, owner, clock, E116XT, 16, 16, address_map_constructor(FUNC(e116xt_device::e116_8k_iram_map), this)) { } @@ -750,8 +749,11 @@ void hyperstone_device::execute_int(uint32_t addr) } /* TODO: mask Parity Error and Extended Overflow exceptions */ -void hyperstone_device::execute_exception(uint32_t addr) +void hyperstone_device::execute_exception(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; @@ -830,161 +832,100 @@ void hyperstone_device::execute_software() template void hyperstone_device::check_interrupts() { - /* Interrupt-Lock flag isn't set */ - if (GET_L || m_core->intblock > 0) + // Interrupt-Lock flag isn't set + if (GET_L) return; - /* quick exit if nothing */ + // quick exit if nothing if (TIMER == NO_TIMER && (ISR & 0x7f) == 0) return; - if (TIMER == NO_TIMER) + // IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt + if (IO3_LINE_STATE && (FCR & 0x00000500) == 0x00000400) { - /* IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt */ - if (IO3_LINE_STATE && (FCR & 0x00000500) == 0x00000400) - { - standard_irq_callback(IRQ_IO3, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_IO3)); - return; - } - - /* INT1 is priority 7; state is in bit 0 of ISR; FCR bit 28 inhibits interrupt */ - if (INT1_LINE_STATE && (FCR & 0x10000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT1, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT1)); - return; - } - - /* INT2 is priority 9; state is in bit 1 of ISR; FCR bit 29 inhibits interrupt */ - if (INT2_LINE_STATE && (FCR & 0x20000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT2, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT2)); - return; - } - - /* INT3 is priority 11; state is in bit 2 of ISR; FCR bit 30 inhibits interrupt */ - if (INT3_LINE_STATE && (FCR & 0x40000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT3, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT3)); - return; - } - - /* INT4 is priority 13; state is in bit 3 of ISR; FCR bit 31 inhibits interrupt */ - if (INT4_LINE_STATE && (FCR & 0x80000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT4, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT4)); - return; - } - - /* IO1 is priority 14; state is in bit 4 of ISR; FCR bit 2 enables input and FCR bit 0 inhibits interrupt */ - if (IO1_LINE_STATE && (FCR & 0x00000005) == 0x00000004) - { - standard_irq_callback(IRQ_IO1, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_IO1)); - return; - } - - /* IO2 is priority 15; state is in bit 5 of ISR; FCR bit 6 enables input and FCR bit 4 inhibits interrupt */ - if (IO2_LINE_STATE && (FCR & 0x00000050) == 0x00000040) - { - standard_irq_callback(IRQ_IO2, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_IO2)); - return; - } + standard_irq_callback(IRQ_IO3, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_IO3)); + return; } - else + + // timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt + if (TIMER && (FCR & 0x00b00000) == 0x00300000) { - /* IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt */ - if (IO3_LINE_STATE && (FCR & 0x00000500) == 0x00000400) - { - standard_irq_callback(IRQ_IO3, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_IO3)); - return; - } + m_core->timer_int_pending = 0; + execute_int(get_trap_addr(TRAPNO_TIMER)); + return; + } - /* timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt */ - if (TIMER && (FCR & 0x00b00000) == 0x00300000) - { - m_core->timer_int_pending = 0; - execute_int(get_trap_addr(TRAPNO_TIMER)); - return; - } + // INT1 is priority 7; state is in bit 0 of ISR; FCR bit 28 inhibits interrupt + if (INT1_LINE_STATE && (FCR & 0x10000000) == 0x00000000) + { + standard_irq_callback(IRQ_INT1, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_INT1)); + return; + } - /* INT1 is priority 7; state is in bit 0 of ISR; FCR bit 28 inhibits interrupt */ - if (INT1_LINE_STATE && (FCR & 0x10000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT1, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT1)); - return; - } + // timer int might be priority 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt + if (TIMER && (FCR & 0x00b00000) == 0x00200000) + { + m_core->timer_int_pending = 0; + execute_int(get_trap_addr(TRAPNO_TIMER)); + return; + } - /* timer int might be priority 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt */ - if (TIMER && (FCR & 0x00b00000) == 0x00200000) - { - m_core->timer_int_pending = 0; - execute_int(get_trap_addr(TRAPNO_TIMER)); - return; - } + // INT2 is priority 9; state is in bit 1 of ISR; FCR bit 29 inhibits interrupt + if (INT2_LINE_STATE && (FCR & 0x20000000) == 0x00000000) + { + standard_irq_callback(IRQ_INT2, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_INT2)); + return; + } - /* INT2 is priority 9; state is in bit 1 of ISR; FCR bit 29 inhibits interrupt */ - if (INT2_LINE_STATE && (FCR & 0x20000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT2, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT2)); - return; - } + // timer int might be priority 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt + if (TIMER && (FCR & 0x00b00000) == 0x00100000) + { + m_core->timer_int_pending = 0; + execute_int(get_trap_addr(TRAPNO_TIMER)); + return; + } - /* timer int might be priority 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt */ - if (TIMER && (FCR & 0x00b00000) == 0x00100000) - { - m_core->timer_int_pending = 0; - execute_int(get_trap_addr(TRAPNO_TIMER)); - return; - } + // INT3 is priority 11; state is in bit 2 of ISR; FCR bit 30 inhibits interrupt + if (INT3_LINE_STATE && (FCR & 0x40000000) == 0x00000000) + { + standard_irq_callback(IRQ_INT3, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_INT3)); + return; + } - /* INT3 is priority 11; state is in bit 2 of ISR; FCR bit 30 inhibits interrupt */ - if (INT3_LINE_STATE && (FCR & 0x40000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT3, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT3)); - return; - } + // timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt + if (TIMER && (FCR & 0x00b00000) == 0x00000000) + { + m_core->timer_int_pending = 0; + execute_int(get_trap_addr(TRAPNO_TIMER)); + return; + } - /* timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt */ - if (TIMER && (FCR & 0x00b00000) == 0x00000000) - { - m_core->timer_int_pending = 0; - execute_int(get_trap_addr(TRAPNO_TIMER)); - return; - } + // INT4 is priority 13; state is in bit 3 of ISR; FCR bit 31 inhibits interrupt + if (INT4_LINE_STATE && (FCR & 0x80000000) == 0x00000000) + { + standard_irq_callback(IRQ_INT4, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_INT4)); + return; + } - /* INT4 is priority 13; state is in bit 3 of ISR; FCR bit 31 inhibits interrupt */ - if (INT4_LINE_STATE && (FCR & 0x80000000) == 0x00000000) - { - standard_irq_callback(IRQ_INT4, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_INT4)); - return; - } + // IO1 is priority 14; state is in bit 4 of ISR; FCR bit 2 enables input and FCR bit 0 inhibits interrupt + if (IO1_LINE_STATE && (FCR & 0x00000005) == 0x00000004) + { + standard_irq_callback(IRQ_IO1, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_IO1)); + return; + } - /* IO1 is priority 14; state is in bit 4 of ISR; FCR bit 2 enables input and FCR bit 0 inhibits interrupt */ - if (IO1_LINE_STATE && (FCR & 0x00000005) == 0x00000004) - { - standard_irq_callback(IRQ_IO1, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_IO1)); - return; - } - - /* IO2 is priority 15; state is in bit 5 of ISR; FCR bit 6 enables input and FCR bit 4 inhibits interrupt */ - if (IO2_LINE_STATE && (FCR & 0x00000050) == 0x00000040) - { - standard_irq_callback(IRQ_IO2, m_core->global_regs[0]); - execute_int(get_trap_addr(TRAPNO_IO2)); - return; - } + // IO2 is priority 15; state is in bit 5 of ISR; FCR bit 6 enables input and FCR bit 4 inhibits interrupt + if (IO2_LINE_STATE && (FCR & 0x00000050) == 0x00000040) + { + standard_irq_callback(IRQ_IO2, m_core->global_regs[0]); + execute_int(get_trap_addr(TRAPNO_IO2)); + return; } } @@ -1603,17 +1544,9 @@ void hyperstone_device::execute_run() return; } - if (m_core->intblock < 0) - m_core->intblock = 0; - if (!m_instruction_length_valid) SET_ILC(get_instruction_length(m_pr16(PC))); - if (m_core->timer_int_pending) - check_interrupts(); - else - check_interrupts(); - while (m_core->icount > 0) { #if E132XS_LOG_INTERPRETER_REGS @@ -1622,6 +1555,15 @@ void hyperstone_device::execute_run() debugger_instruction_hook(PC); + if (--m_core->intblock <= 0) + { + m_core->intblock = 0; + if (m_core->timer_int_pending) + check_interrupts(); + else + check_interrupts(); + } + OP = m_pr16(PC); PC += 2; @@ -1898,19 +1840,7 @@ void hyperstone_device::execute_run() } if (GET_T && GET_P && !m_core->delay_slot) /* Not in a Delayed Branch instructions */ - { - uint32_t addr = get_trap_addr(TRAPNO_TRACE_EXCEPTION); - execute_exception(addr); - } - - if (--m_core->intblock <= 0) - { - m_core->intblock = 0; - if (m_core->timer_int_pending) - check_interrupts(); - else - check_interrupts(); - } + execute_exception(TRAPNO_TRACE_EXCEPTION); } } diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 65527d5010a..f6b9daf0f8e 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -118,27 +118,6 @@ class hyperstone_device : public cpu_device, public hyperstone_disassembler::con public: virtual ~hyperstone_device() override; - inline void ccfunc_unimplemented(); - inline void ccfunc_print(); - inline void ccfunc_total_cycles(); - inline void ccfunc_standard_irq_callback(); - -#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS - void dump_registers(); -#endif - void update_timer_prescale(); - void compute_tr(); - void adjust_timer_interrupt(); - - void e116_16k_iram_map(address_map &map) ATTR_COLD; - void e116_4k_iram_map(address_map &map) ATTR_COLD; - void e116_8k_iram_map(address_map &map) ATTR_COLD; - void e132_16k_iram_map(address_map &map) ATTR_COLD; - void e132_4k_iram_map(address_map &map) ATTR_COLD; - void e132_8k_iram_map(address_map &map) ATTR_COLD; - - static uint32_t imm_length(uint16_t op); - protected: // compilation boundaries -- how far back/forward does the analysis extend? enum : u32 @@ -277,28 +256,44 @@ protected: hyperstone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, uint32_t prg_data_width, uint32_t io_data_width, address_map_constructor internal_map); - // device-level overrides + // device_t implementation virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; virtual void device_stop() override ATTR_COLD; - // device_execute_interface overrides + // device_execute_interface implementation virtual uint32_t execute_min_cycles() const noexcept override; virtual uint32_t execute_max_cycles() const noexcept override; virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; - // device_memory_interface overrides + // device_memory_interface implementation virtual space_config_vector memory_space_config() const override; - // device_disasm_interface overrides + // device_disasm_interface implementation virtual std::unique_ptr create_disassembler() override; virtual u8 get_fp() const override; virtual bool get_h() const override; - // device_state_interface overrides + // device_state_interface implementation virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; +#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS + void dump_registers(); +#endif + void update_timer_prescale(); + void compute_tr(); + void adjust_timer_interrupt(); + + void e116_16k_iram_map(address_map &map) ATTR_COLD; + void e116_4k_iram_map(address_map &map) ATTR_COLD; + void e116_8k_iram_map(address_map &map) ATTR_COLD; + void e132_16k_iram_map(address_map &map) ATTR_COLD; + void e132_4k_iram_map(address_map &map) ATTR_COLD; + void e132_8k_iram_map(address_map &map) ATTR_COLD; + + static uint32_t imm_length(uint16_t op); + // address spaces const address_space_config m_program_config; const address_space_config m_io_config; @@ -353,7 +348,7 @@ private: void hyperstone_br(); void execute_trap(uint32_t addr); void execute_int(uint32_t addr); - void execute_exception(uint32_t addr); + void execute_exception(uint8_t trapno); void execute_software(); template uint64_t get_double_word(uint8_t dst_code, uint8_t dstf_code) const; @@ -467,6 +462,7 @@ private: /* internal compiler state */ struct compiler_state; + struct c_funcs; void execute_run_drc(); void flush_drc_cache(); @@ -480,7 +476,7 @@ private: 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_update_cycles(drcuml_block &block, bool check_interrupts = true); + 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); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); diff --git a/src/devices/cpu/e132xs/e132xsdrc.cpp b/src/devices/cpu/e132xs/e132xsdrc.cpp index e5d3ba50206..a6bd669db51 100644 --- a/src/devices/cpu/e132xs/e132xsdrc.cpp +++ b/src/devices/cpu/e132xs/e132xsdrc.cpp @@ -18,6 +18,67 @@ struct hyperstone_device::compiler_state }; +/*************************************************************************** + C FUNCTION CALLBACKS +***************************************************************************/ + +struct hyperstone_device::c_funcs +{ + + static void unimplemented(void *param) + { + auto &that = *reinterpret_cast(param); + fatalerror("PC=%08X: Unimplemented op %08X\n", that.PC, that.m_core->arg0); + } + + static void print(void *param) + { + auto &that = *reinterpret_cast(param); + printf("%c: %08x\n", (char)that.m_core->arg0, that.m_core->arg1); + } + + static void standard_irq_callback(void *param) + { + auto &that = *reinterpret_cast(param); + that.standard_irq_callback(that.m_core->arg0, that.m_core->global_regs[0]); + } + + static void debugger_exception_hook(void *param) + { + auto &that = *reinterpret_cast(param); + that.debugger_exception_hook(int32_t(that.m_core->arg0)); + } + + static void adjust_timer_interrupt(void *param) + { + reinterpret_cast(param)->adjust_timer_interrupt(); + } + + static void compute_tr(void *param) + { + reinterpret_cast(param)->compute_tr(); + } + + static void update_timer_prescale(void *param) + { + reinterpret_cast(param)->update_timer_prescale(); + } + +#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS + static void dump_registers(void *param) + { + reinterpret_cast(param)->dump_registers(); + } +#endif + + static void total_cycles(void *param) + { + auto &that = *reinterpret_cast(param); + that.m_core->numcycles = that.total_cycles(); + } +}; + + #define DRC_PC uml::mem(&m_core->global_regs[0]) #define DRC_SR uml::mem(&m_core->global_regs[1]) @@ -49,84 +110,6 @@ void hyperstone_device::execute_run_drc() } -/*************************************************************************** - C FUNCTION CALLBACKS -***************************************************************************/ - -/*------------------------------------------------- - cfunc_unimplemented - handler for - unimplemented opcdes --------------------------------------------------*/ - -inline void hyperstone_device::ccfunc_unimplemented() -{ - fatalerror("PC=%08X: Unimplemented op %08X\n", PC, m_core->arg0); -} - -inline void hyperstone_device::ccfunc_print() -{ - printf("%c: %08x\n", (char)m_core->arg0, m_core->arg1); -} - -inline void hyperstone_device::ccfunc_standard_irq_callback() -{ - standard_irq_callback(m_core->arg0, m_core->global_regs[0]); -} - -static void cfunc_unimplemented(void *param) -{ - ((hyperstone_device *)param)->ccfunc_unimplemented(); -} - -static void cfunc_adjust_timer_interrupt(void *param) -{ - ((hyperstone_device *)param)->adjust_timer_interrupt(); -} - -static void cfunc_compute_tr(void *param) -{ - ((hyperstone_device *)param)->compute_tr(); -} - -static void cfunc_update_timer_prescale(void *param) -{ - ((hyperstone_device *)param)->update_timer_prescale(); -} - -static void cfunc_standard_irq_callback(void *param) -{ - ((hyperstone_device *)param)->ccfunc_standard_irq_callback(); -} - -#if 0 -static void cfunc_print(void *param) -{ - ((hyperstone_device *)param)->ccfunc_print(); -} -#endif - -#if E132XS_LOG_DRC_REGS -static void cfunc_dump_registers(void *param) -{ - ((hyperstone_device *)param)->dump_registers(); -} -#endif - -/*------------------------------------------------- - cfunc_total_cycles - compute the total number - of cycles executed so far --------------------------------------------------*/ - -void hyperstone_device::ccfunc_total_cycles() -{ - m_core->numcycles = total_cycles(); -} - -static void cfunc_total_cycles(void *param) -{ - ((hyperstone_device *)param)->ccfunc_total_cycles(); -} - /*************************************************************************** CACHE MANAGEMENT ***************************************************************************/ @@ -278,7 +261,6 @@ void hyperstone_device::code_compile_block(uint8_t mode, offs_t pc) UML_LABEL(block, seqhead->pc | 0x80000000); UML_MOV(block, I7, 0); - UML_CALLH(block, *m_interrupt_checks); /* iterate over instructions in the sequence and compile them */ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) @@ -350,6 +332,11 @@ void hyperstone_device::static_generate_exception(drcuml_block &block, uml::code 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 @@ -392,8 +379,6 @@ void hyperstone_device::static_generate_interrupt_checks(drcuml_block &block, um const int dispatch_int = label++; const int done_int = label++; - UML_CMP(block, mem(&m_core->intblock), 0); - UML_JMPc(block, uml::COND_G, done_int); UML_TEST(block, DRC_SR, L_MASK); UML_JMPc(block, uml::COND_NZ, done_int); @@ -413,7 +398,7 @@ void hyperstone_device::static_generate_interrupt_checks(drcuml_block &block, um UML_JMP(block, done_int); UML_LABEL(block, take_int); - UML_CALLC(block, cfunc_standard_irq_callback, this); + UML_CALLC(block, &c_funcs::standard_irq_callback, this); UML_JMP(block, dispatch_int); UML_LABEL(block, take_timer); @@ -638,17 +623,8 @@ void hyperstone_device::generate_interrupt_checks(drcuml_block &block, uml::code an exception if out -------------------------------------------------*/ -void hyperstone_device::generate_update_cycles(drcuml_block &block, bool check_interrupts) +void hyperstone_device::generate_update_cycles(drcuml_block &block) { - // clobbers I0 - - UML_SUB(block, I0, mem(&m_core->intblock), 1); - UML_MOVc(block, uml::COND_S, I0, 0); - UML_MOV(block, mem(&m_core->intblock), I0); - - if (check_interrupts) - UML_CALLH(block, *m_interrupt_checks); - UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I7); UML_MOV(block, I7, 0); UML_CALLHc(block, uml::COND_LE, *m_out_of_cycles); @@ -754,7 +730,7 @@ void hyperstone_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, void hyperstone_device::generate_branch(drcuml_block &block, uml::parameter mode, uml::parameter targetpc, const opcode_desc *desc, bool update_cycles) { - // clobbers I0, I1, I2, I3 and I4 if update_cycles is true + // 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); @@ -792,7 +768,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi UML_MAPVAR(block, MAPVAR_PC, expc); #if E132XS_LOG_DRC_REGS - UML_CALLC(block, cfunc_dump_registers, this); + UML_CALLC(block, &c_funcs::dump_registers, this); #endif // if we are debugging, call the debugger @@ -802,6 +778,12 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi UML_DEBUG(block, desc->pc); } + // check for pending interrupts + UML_SUB(block, I0, mem(&m_core->intblock), 1); + UML_MOVc(block, uml::COND_S, I0, 0); + UML_MOV(block, mem(&m_core->intblock), I0); + UML_CALLHc(block, uml::COND_LE, *m_interrupt_checks); + if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) { // compile the instruction @@ -809,7 +791,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi { UML_MOV(block, DRC_PC, desc->pc); UML_MOV(block, mem(&m_core->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_unimplemented, this); + UML_CALLC(block, &c_funcs::unimplemented, this); } } } diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index 9aea04ccf62..331d61a764f 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -157,10 +157,10 @@ void hyperstone_device::generate_set_global_register(drcuml_block &block, compil UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); UML_TEST(block, I5, 0x80000000); UML_JMPc(block, uml::COND_NZ, skip_compute_tr); - UML_CALLC(block, cfunc_compute_tr, this); - UML_CALLC(block, cfunc_update_timer_prescale, this); + UML_CALLC(block, &c_funcs::compute_tr, this); + UML_CALLC(block, &c_funcs::update_timer_prescale, this); UML_LABEL(block, skip_compute_tr); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); } else if (dst_code == TCR_REGISTER) { @@ -169,16 +169,16 @@ void hyperstone_device::generate_set_global_register(drcuml_block &block, compil UML_CMP(block, I6, I5); UML_JMPc(block, uml::COND_E, done); UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); UML_LABEL(block, done); } else if (dst_code == TR_REGISTER) { UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); UML_MOV(block, mem(&m_core->tr_base_value), I5); - UML_CALLC(block, cfunc_total_cycles, this); + UML_CALLC(block, &c_funcs::total_cycles, this); UML_DMOV(block, mem(&m_core->tr_base_cycles), mem(&m_core->numcycles)); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); } else if (dst_code == ISR_REGISTER) { @@ -191,7 +191,7 @@ void hyperstone_device::generate_set_global_register(drcuml_block &block, compil UML_XOR(block, I6, I6, I5); UML_TEST(block, I6, 0x80000000); UML_JMPc(block, uml::COND_Z, skip_adjust_timer); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); UML_LABEL(block, skip_adjust_timer); UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); } @@ -291,10 +291,10 @@ void hyperstone_device::generate_set_global_register_high(drcuml_block &block, c UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); UML_TEST(block, src, 0x80000000); UML_JMPc(block, uml::COND_NZ, skip_compute_tr); - UML_CALLC(block, cfunc_compute_tr, this); - UML_CALLC(block, cfunc_update_timer_prescale, this); + UML_CALLC(block, &c_funcs::compute_tr, this); + UML_CALLC(block, &c_funcs::update_timer_prescale, this); UML_LABEL(block, skip_compute_tr); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); } break; case TCR_REGISTER: // G22 Timer Compare Register @@ -304,16 +304,16 @@ void hyperstone_device::generate_set_global_register_high(drcuml_block &block, c UML_CMP(block, I6, src); UML_JMPc(block, uml::COND_E, done); UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); UML_LABEL(block, done); } break; case TR_REGISTER: // G23 Timer Register UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); UML_MOV(block, mem(&m_core->tr_base_value), src); - UML_CALLC(block, cfunc_total_cycles, this); + UML_CALLC(block, &c_funcs::total_cycles, this); UML_DMOV(block, mem(&m_core->tr_base_cycles), mem(&m_core->numcycles)); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); break; case ISR_REGISTER: // G25 Input Status Register (read-only) break; @@ -324,7 +324,7 @@ void hyperstone_device::generate_set_global_register_high(drcuml_block &block, c UML_XOR(block, I6, I6, src); UML_TEST(block, I6, 0x80000000); UML_JMPc(block, uml::COND_Z, skip_adjust_timer); - UML_CALLC(block, cfunc_adjust_timer_interrupt, this); + UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); UML_LABEL(block, skip_adjust_timer); UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); } @@ -387,7 +387,19 @@ void hyperstone_device::generate_set_dst(drcuml_block &block, compiler_state &co if (code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + if (src.is_int_register() && (desc->targetpc == BRANCH_TARGET_DYNAMIC)) + { + UML_AND(block, src, src, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, src, desc); + } + else if (src.is_immediate() && (desc->targetpc == BRANCH_TARGET_DYNAMIC)) + { + generate_branch(block, compiler.m_mode, src.immediate() & ~uint32_t(1), desc); + } + else + { + generate_branch(block, compiler.m_mode, desc->targetpc, desc); + } } } else @@ -489,7 +501,7 @@ void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block, uml: UML_STORE(block, (void *)m_core->local_regs, I3, I4, SIZE_DWORD, SCALE_x4); UML_MOV(block, DRC_PC, I0); // branch to exception handler - generate_branch(block, 1, DRC_PC, nullptr, true); // T cleared and S set - mode will always be 1 + generate_branch(block, 1, uml::I0, nullptr, true); // 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) @@ -581,7 +593,7 @@ void hyperstone_device::generate_software(drcuml_block &block, compiler_state &c UML_ROLINS(block, I0, I4, FP_SHIFT, FP_MASK); // SET_FP(reg) UML_MOV(block, DRC_SR, I0); - generate_branch(block, compiler.m_mode & 0x1, desc->targetpc, desc); // T cleared - only keep S in bit zero of mode + generate_branch(block, compiler.m_mode & 0x1, uml::I5, desc); // T cleared - only keep S in bit zero of mode } @@ -1138,7 +1150,7 @@ void hyperstone_device::generate_get_global_register(drcuml_block &block, compil UML_CMP(block, mem(&m_core->icount), I2); UML_MOVc(block, uml::COND_BE, I2, 0); UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I2); - UML_CALLC(block, cfunc_compute_tr, this); + UML_CALLC(block, &c_funcs::compute_tr, this); UML_MOV(block, I5, mem(&m_core->tr_result)); UML_JMP(block, done); @@ -1207,7 +1219,8 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil if (dst_code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + UML_AND(block, I5, I5, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I5, desc); } UML_JMP(block, done); @@ -1637,7 +1650,7 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi if (dst_code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + generate_branch(block, compiler.m_mode, src & ~uint32_t(1), desc); } UML_JMP(block, done); @@ -2584,7 +2597,10 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp { generate_set_global_register_low(block, compiler, src_code, uml::I1); if (src_code == PC_REGISTER) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -2603,7 +2619,10 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp { generate_set_global_register_low(block, compiler, src_code, uml::I1); if (src_code == PC_REGISTER) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -2624,8 +2643,11 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp if (SRC_GLOBAL) { generate_set_global_register_low(block, compiler, src_code, uml::I1); - if (src_code == 0) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + if (src_code == PC_REGISTER) + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -2651,7 +2673,10 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp { generate_set_global_register_low(block, compiler, src_code, uml::I1); if (src_code == PC_REGISTER) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -2668,7 +2693,10 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp { generate_set_global_register_low(block, compiler, src_code, uml::I1); if (src_code == PC_REGISTER) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -2701,7 +2729,10 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp { generate_set_global_register_low(block, compiler, src_code, uml::I1); if (src_code == 0) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -2720,7 +2751,10 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp { generate_set_global_register_low(block, compiler, src_code, uml::I1); if (src_code == PC_REGISTER) - generate_branch(block, compiler.m_mode, desc->targetpc, desc); + { + UML_AND(block, I1, I1, ~uint32_t(1)); + generate_branch(block, compiler.m_mode, uml::I1, desc); + } } else { @@ -4029,11 +4063,12 @@ void hyperstone_device::generate_call(drcuml_block &block, compiler_state &compi UML_ROLINS(block, DRC_SR, 6, FL_SHIFT, FL_MASK); UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); - UML_ADD(block, DRC_PC, I2, extra_s & ~1); + UML_ADD(block, I2, I2, extra_s & ~uint32_t(1)); + UML_MOV(block, DRC_PC, I2); UML_MOV(block, mem(&m_core->intblock), 2); - generate_branch(block, compiler.m_mode, desc->targetpc, nullptr); + generate_branch(block, compiler.m_mode, uml::I2, nullptr); //TODO: add interrupt locks, errors, .... } diff --git a/src/devices/cpu/e132xs/e132xsop.hxx b/src/devices/cpu/e132xs/e132xsop.hxx index bbefe6df611..ce8254f389a 100644 --- a/src/devices/cpu/e132xs/e132xsop.hxx +++ b/src/devices/cpu/e132xs/e132xsop.hxx @@ -37,13 +37,13 @@ void hyperstone_device::hyperstone_chk() if (SRC_GLOBAL && (src_code == SR_REGISTER)) { if (dreg == 0) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } else { const uint32_t sreg = (SRC_GLOBAL ? m_core->global_regs : m_core->local_regs)[src_code]; if ((SRC_GLOBAL && (src_code == PC_REGISTER)) ? (dreg >= sreg) : (dreg > sreg)) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } m_core->icount -= m_core->clock_cycles_1; @@ -81,7 +81,7 @@ void hyperstone_device::hyperstone_movd() const uint32_t new_s = SR & S_MASK; const uint32_t new_l = SR & L_MASK; if ((!old_s && new_s) || (!new_s && !old_l && new_l)) - execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR)); + execute_exception(TRAPNO_PRIVILEGE_ERROR); for (int difference = util::sext(GET_FP - ((SP & 0x1fc) >> 2), 7); difference < 0; difference++) { @@ -157,7 +157,7 @@ void hyperstone_device::hyperstone_divsu() //Z -> undefined //N -> undefined SR |= V_MASK; - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } else { @@ -214,7 +214,7 @@ void hyperstone_device::hyperstone_xm() if (sub_type < 4) { if ((SRC_GLOBAL && ((src_code == PC_REGISTER)) ? (sreg >= extra_u) : (sreg > extra_u))) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } m_core->icount -= m_core->clock_cycles_1; @@ -304,7 +304,7 @@ void hyperstone_device::hyperstone_sums() m_core->icount -= m_core->clock_cycles_1; if ((SR & V_MASK) && src_code != SR_REGISTER) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } @@ -347,7 +347,7 @@ void hyperstone_device::hyperstone_mov() SR &= ~H_MASK; if (DST_GLOBAL && h && !(SR & S_MASK)) { - execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR)); + execute_exception(TRAPNO_PRIVILEGE_ERROR); } else { @@ -449,7 +449,7 @@ void hyperstone_device::hyperstone_adds() m_core->icount -= m_core->clock_cycles_1; if (SR & V_MASK) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } @@ -667,7 +667,7 @@ void hyperstone_device::hyperstone_subs() m_core->icount -= m_core->clock_cycles_1; if (SR & V_MASK) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } @@ -802,7 +802,7 @@ void hyperstone_device::hyperstone_negs() m_core->icount -= m_core->clock_cycles_1; if (GET_V) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } @@ -854,7 +854,7 @@ void hyperstone_device::hyperstone_movi() SR &= ~H_MASK; if (DST_GLOBAL && h && !(SR & S_MASK)) { - execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR)); + execute_exception(TRAPNO_PRIVILEGE_ERROR); } else { @@ -981,7 +981,7 @@ void hyperstone_device::hyperstone_addsi() m_core->icount -= m_core->clock_cycles_1; if (SR & V_MASK) - execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR)); + execute_exception(TRAPNO_RANGE_ERROR); } @@ -2559,7 +2559,7 @@ void hyperstone_device::hyperstone_frame() while (difference < 0); if (tmp_flag) - execute_exception(get_trap_addr(TRAPNO_FRAME_ERROR)); + execute_exception(TRAPNO_FRAME_ERROR); } // TODO: More than 1 cycle!