diff options
Diffstat (limited to 'src/emu/diexec.h')
-rw-r--r-- | src/emu/diexec.h | 117 |
1 files changed, 54 insertions, 63 deletions
diff --git a/src/emu/diexec.h b/src/emu/diexec.h index 663cc6ddb1c..1e8303287e8 100644 --- a/src/emu/diexec.h +++ b/src/emu/diexec.h @@ -7,6 +7,7 @@ Device execution interfaces. ***************************************************************************/ + #ifndef MAME_EMU_DIEXEC_H #define MAME_EMU_DIEXEC_H @@ -108,81 +109,67 @@ public: u32 max_cycles() const { return execute_max_cycles(); } attotime cycles_to_attotime(u64 cycles) const { return device().clocks_to_attotime(cycles_to_clocks(cycles)); } u64 attotime_to_cycles(const attotime &duration) const { return clocks_to_cycles(device().attotime_to_clocks(duration)); } - u32 input_lines() const { return execute_input_lines(); } u32 default_irq_vector(int linenum) const { return execute_default_irq_vector(linenum); } bool input_edge_triggered(int linenum) const { return execute_input_edge_triggered(linenum); } // inline configuration helpers void set_disable() { m_disabled = true; } - template <typename Object> void set_vblank_int(Object &&cb, const char *tag) - { - m_vblank_interrupt = std::forward<Object>(cb); - m_vblank_interrupt_screen = tag; - } - void set_vblank_int(device_interrupt_delegate callback, const char *tag) + + template <typename... T> void set_vblank_int(const char *tag, T &&... args) { - m_vblank_interrupt = callback; + m_vblank_interrupt.set(std::forward<T>(args)...); m_vblank_interrupt_screen = tag; } - template <class FunctionClass> void set_vblank_int(const char *tag, const char *devname, void (FunctionClass::*callback)(device_t &), const char *name) - { - set_vblank_int(device_interrupt_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr)), tag); - } - template <class FunctionClass> void set_vblank_int(const char *tag, void (FunctionClass::*callback)(device_t &), const char *name) + void remove_vblank_int() { - set_vblank_int(device_interrupt_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)), tag); + m_vblank_interrupt = device_interrupt_delegate(*this); + m_vblank_interrupt_screen = nullptr; } - template <typename Object> void set_periodic_int(Object &&cb, const attotime &rate) + template <typename F> void set_periodic_int(F &&cb, const char *name, const attotime &rate) { - m_timed_interrupt = std::forward<Object>(cb); + m_timed_interrupt.set(std::forward<F>(cb), name); m_timed_interrupt_period = rate; } - void set_periodic_int(device_interrupt_delegate callback, const attotime &rate) + template <typename T, typename F> void set_periodic_int(T &&target, F &&cb, const char *name, const attotime &rate) { - m_timed_interrupt = callback; + m_timed_interrupt.set(std::forward<T>(target), std::forward<F>(cb), name); m_timed_interrupt_period = rate; } - template <class FunctionClass> void set_periodic_int(const char *devname, void (FunctionClass::*callback)(device_t &), const char *name, const attotime &rate) - { - set_periodic_int(device_interrupt_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr)), rate); - } - template <class FunctionClass> void set_periodic_int(void (FunctionClass::*callback)(device_t &), const char *name, const attotime &rate) + void remove_periodic_int() { - set_periodic_int(device_interrupt_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)), rate); + m_timed_interrupt = device_interrupt_delegate(*this); + m_timed_interrupt_period = attotime(); } - template <typename Object> void set_irq_acknowledge_callback(Object &&cb) { m_driver_irq = std::forward<Object>(cb); } - void set_irq_acknowledge_callback(device_irq_acknowledge_delegate callback) { m_driver_irq = callback; } - template <class FunctionClass> void set_irq_acknowledge_callback(const char *devname, int (FunctionClass::*callback)(device_t &, int), const char *name) + template <typename... T> void set_irq_acknowledge_callback(T &&... args) { - set_irq_acknowledge_callback(device_irq_acknowledge_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr))); + m_driver_irq.set(std::forward<T>(args)...); } - template <class FunctionClass> void set_irq_acknowledge_callback(int (FunctionClass::*callback)(device_t &, int), const char *name) + void remove_irq_acknowledge_callback() { - set_irq_acknowledge_callback(device_irq_acknowledge_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr))); + m_driver_irq = device_irq_acknowledge_delegate(*this); } // execution management - device_scheduler &scheduler() const { assert(m_scheduler != nullptr); return *m_scheduler; } - bool executing() const { return scheduler().currently_executing() == this; } - s32 cycles_remaining() const { return executing() ? *m_icountptr : 0; } // cycles remaining in this timeslice - void eat_cycles(int cycles) { if (executing()) *m_icountptr = (cycles > *m_icountptr) ? 0 : (*m_icountptr - cycles); } - void adjust_icount(int delta) { if (executing()) *m_icountptr += delta; } - void abort_timeslice(); + device_scheduler &scheduler() const noexcept { assert(m_scheduler != nullptr); return *m_scheduler; } + bool executing() const noexcept { return scheduler().currently_executing() == this; } + s32 cycles_remaining() const noexcept { return executing() ? *m_icountptr : 0; } // cycles remaining in this timeslice + void eat_cycles(int cycles) noexcept { if (executing()) *m_icountptr = (cycles > *m_icountptr) ? 0 : (*m_icountptr - cycles); } + void adjust_icount(int delta) noexcept { if (executing()) *m_icountptr += delta; } + void abort_timeslice() noexcept; // input and interrupt management - void set_input_line(int linenum, int state) { m_input[linenum].set_state_synced(state); } - void set_input_line_vector(int linenum, int vector) { m_input[linenum].set_vector(vector); } - void set_input_line_and_vector(int linenum, int state, int vector) { m_input[linenum].set_state_synced(state, vector); } - int input_state(int linenum) const { return m_input[linenum].m_curstate; } + void set_input_line(int linenum, int state) { assert(device().started()); m_input[linenum].set_state_synced(state); } + void set_input_line_vector(int linenum, int vector) { assert(device().started()); m_input[linenum].set_vector(vector); } + void set_input_line_and_vector(int linenum, int state, int vector) { assert(device().started()); m_input[linenum].set_state_synced(state, vector); } + int input_line_state(int linenum) const { assert(device().started()); return m_input[linenum].m_curstate; } void pulse_input_line(int irqline, const attotime &duration); - void pulse_input_line_and_vector(int irqline, int vector, const attotime &duration); // suspend/resume void suspend(u32 reason, bool eatcycles); void resume(u32 reason); - bool suspended(u32 reason = SUSPEND_ANY_REASON) const { return (m_nextsuspend & reason) != 0; } + bool suspended(u32 reason = SUSPEND_ANY_REASON) const noexcept { return (m_nextsuspend & reason) != 0; } void yield() { suspend(SUSPEND_REASON_TIMESLICE, false); } void spin() { suspend(SUSPEND_REASON_TIMESLICE, true); } void spin_until_trigger(int trigid) { suspend_until_trigger(trigid, true); } @@ -195,31 +182,28 @@ public: void signal_interrupt_trigger() { trigger(m_inttrigger); } // time and cycle accounting - attotime local_time() const; - u64 total_cycles() const; + attotime local_time() const noexcept; + u64 total_cycles() const noexcept; // required operation overrides void run() { execute_run(); } - // deliberately ambiguous functions; if you have the execute interface - // just use it + // deliberately ambiguous functions; if you have the execute interface just use it device_execute_interface &execute() { return *this; } protected: // clock and cycle information getters - virtual u64 execute_clocks_to_cycles(u64 clocks) const; - virtual u64 execute_cycles_to_clocks(u64 cycles) const; - virtual u32 execute_min_cycles() const; - virtual u32 execute_max_cycles() const; + virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept; + virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept; + virtual u32 execute_min_cycles() const noexcept; + virtual u32 execute_max_cycles() const noexcept; // input line information getters - virtual u32 execute_input_lines() const; - virtual u32 execute_default_irq_vector(int linenum) const; - virtual bool execute_input_edge_triggered(int linenum) const; + virtual u32 execute_default_irq_vector(int linenum) const noexcept; + virtual bool execute_input_edge_triggered(int linenum) const noexcept; // optional operation overrides virtual void execute_run() = 0; - virtual void execute_burn(s32 cycles); virtual void execute_set_input(int linenum, int state); // interface-level overrides @@ -228,13 +212,11 @@ protected: virtual void interface_post_start() override; virtual void interface_pre_reset() override; virtual void interface_post_reset() override; - virtual void interface_clock_changed() override; + virtual void interface_clock_changed(bool sync_on_new_clock_domain) override; // for use by devcpu for now... - int current_input_state(unsigned i) const { return m_input[i].m_curstate; } void set_icountptr(int &icount) { assert(!m_icountptr); m_icountptr = &icount; } - IRQ_CALLBACK_MEMBER(standard_irq_callback_member); - int standard_irq_callback(int irqline); + int standard_irq_callback(int irqline, offs_t pc); // debugger hooks bool debugger_enabled() const { return bool(device().machine().debug_flags & DEBUG_FLAG_ENABLED); } @@ -255,16 +237,22 @@ protected: device().debug()->privilege_hook(); } + void debugger_wait_hook() + { + if (device().machine().debug_flags & DEBUG_FLAG_CALL_HOOK) + device().debug()->wait_hook(); + } + private: // internal information about the state of inputs class device_input { - static const int USE_STORED_VECTOR = 0xff000000; + static constexpr int USE_STORED_VECTOR = 0xff000000; public: device_input(); - void start(device_execute_interface *execute, int linenum); + void start(device_execute_interface &execute, int linenum); void reset(); void set_state_synced(int state, int vector = USE_STORED_VECTOR); @@ -316,7 +304,9 @@ private: // cycle counting and executing profile_type m_profiler; // profiler tag +protected: // TODO: decide whether to bring up the wait-state methods int * m_icountptr; // pointer to the icount +private: int m_cycles_running; // number of cycles we are executing int m_cycles_stolen; // number of cycles we artificially stole @@ -329,15 +319,16 @@ private: s32 m_inttrigger; // interrupt trigger index // clock and timing information -protected: // FIXME: MIPS3 accesses m_totalcycles directly from execute_burn - devise a better solution u64 m_totalcycles; // total device cycles executed -private: attotime m_localtime; // local time, relative to the timer system's global time s32 m_divisor; // 32-bit attoseconds_per_cycle divisor u8 m_divshift; // right shift amount to fit the divisor into 32 bits u32 m_cycles_per_second; // cycles per second, adjusted for multipliers attoseconds_t m_attoseconds_per_cycle; // attoseconds per adjusted clock cycle + emu_timer * m_spin_end_timer; // timer for triggering the end of spin_until_time + emu_timer * m_pulse_end_timers[MAX_INPUT_LINES]; // timer for ending input-line pulses + // callbacks TIMER_CALLBACK_MEMBER(timed_trigger_callback) { trigger(param); } @@ -354,6 +345,6 @@ public: }; // iterator -typedef device_interface_iterator<device_execute_interface> execute_interface_iterator; +typedef device_interface_enumerator<device_execute_interface> execute_interface_enumerator; #endif // MAME_EMU_DIEXEC_H |