1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-16 18:30:32 +00:00

Made an attempt to reduce cost of the most-likely path.

This commit is contained in:
Thomas Harte 2016-06-28 18:46:00 -04:00
parent b0dae01e8f
commit 6e698e908e

View File

@ -455,11 +455,17 @@ template <class T> class Processor {
int _cycles_left_to_run; int _cycles_left_to_run;
bool _ready_line_is_enabled; enum InterruptRequestFlags: uint8_t {
bool _reset_line_is_enabled; Reset = 0x80,
bool _irq_line_is_enabled, _irq_request_history[2]; IRQ = 0x40,
bool _nmi_line_is_enabled; NMI = 0x20,
};
uint8_t _interrupt_requests;
bool _ready_is_active; bool _ready_is_active;
bool _ready_line_is_enabled;
bool _irq_line_is_enabled, _irq_request_history;
/*! /*!
Gets the program representing an RST response. Gets the program representing an RST response.
@ -528,8 +534,8 @@ template <class T> class Processor {
_scheduledPrograms{nullptr, nullptr, nullptr, nullptr}, _scheduledPrograms{nullptr, nullptr, nullptr, nullptr},
_interruptFlag(Flag::Interrupt), _interruptFlag(Flag::Interrupt),
_s(0), _s(0),
_nextBusOperation(BusOperation::None) _nextBusOperation(BusOperation::None),
_interrupt_requests(0)
{ {
// only the interrupt flag is defined upon reset but get_flags isn't going to // only the interrupt flag is defined upon reset but get_flags isn't going to
// mask the other flags so we need to do that, at least // mask the other flags so we need to do that, at least
@ -576,13 +582,15 @@ template <class T> class Processor {
#define checkSchedule(op) \ #define checkSchedule(op) \
if(!_scheduledPrograms[scheduleProgramsReadPointer]) {\ if(!_scheduledPrograms[scheduleProgramsReadPointer]) {\
scheduleProgramsReadPointer = _scheduleProgramsWritePointer = scheduleProgramProgramCounter = 0;\ scheduleProgramsReadPointer = _scheduleProgramsWritePointer = scheduleProgramProgramCounter = 0;\
if(_reset_line_is_enabled) {\ if(_interrupt_requests) {\
schedule_program(get_reset_program());\ if(_interrupt_requests & InterruptRequestFlags::Reset) {\
} else if(_nmi_line_is_enabled) {\ schedule_program(get_reset_program());\
_nmi_line_is_enabled = false;\ } else if(_interrupt_requests & InterruptRequestFlags::NMI) {\
schedule_program(get_nmi_program());\ _interrupt_requests &= ~InterruptRequestFlags::NMI;\
} else if(_irq_request_history[0]) {\ schedule_program(get_nmi_program());\
schedule_program(get_irq_program());\ } else if(_interrupt_requests & InterruptRequestFlags::IRQ) {\
schedule_program(get_irq_program());\
} \
} else {\ } else {\
schedule_program(fetch_decode_execute);\ schedule_program(fetch_decode_execute);\
}\ }\
@ -602,8 +610,8 @@ template <class T> class Processor {
while (!_ready_is_active && number_of_cycles > 0) { while (!_ready_is_active && number_of_cycles > 0) {
if(nextBusOperation != BusOperation::None) { if(nextBusOperation != BusOperation::None) {
_irq_request_history[0] = _irq_request_history[1]; _interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::IRQ) | (_irq_request_history ? InterruptRequestFlags::IRQ : 0);
_irq_request_history[1] = _irq_line_is_enabled && !_interruptFlag; _irq_request_history = _irq_line_is_enabled && !_interruptFlag;
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(nextBusOperation, busAddress, busValue); number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(nextBusOperation, busAddress, busValue);
nextBusOperation = BusOperation::None; nextBusOperation = BusOperation::None;
} }
@ -1171,7 +1179,7 @@ template <class T> class Processor {
*/ */
inline void set_reset_line(bool active) inline void set_reset_line(bool active)
{ {
_reset_line_is_enabled = active; _interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::Reset) | (active ? InterruptRequestFlags::Reset : 0);
} }
/*! /*!
@ -1181,7 +1189,7 @@ template <class T> class Processor {
*/ */
inline bool get_reset_line() inline bool get_reset_line()
{ {
return _reset_line_is_enabled; return !!(_interrupt_requests & InterruptRequestFlags::Reset);
} }
/*! /*!
@ -1202,7 +1210,7 @@ template <class T> class Processor {
inline void set_nmi_line(bool active) inline void set_nmi_line(bool active)
{ {
// NMI is edge triggered, not level // NMI is edge triggered, not level
_nmi_line_is_enabled |= active; _interrupt_requests |= (active ? InterruptRequestFlags::NMI : 0);
} }
/*! /*!