1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Makes some effort at getting into interrupt processing.

This commit is contained in:
Thomas Harte 2019-05-01 15:26:36 -04:00
parent f6ac407e4d
commit 2e5c0811e7
2 changed files with 69 additions and 48 deletions

View File

@ -54,45 +54,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
*/
switch(execution_state_) {
default:
break;
case ExecutionState::Stopped:
// If an interrupt (TODO: or reset) has finally arrived that will be serviced,
// exit the STOP.
if(bus_interrupt_level_ > interrupt_level_) {
// TODO: schedule interrupt right here.
execution_state_ = ExecutionState::Executing;
break;
}
// Otherwise continue being stopped.
cycles_run_for +=
stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue;
case ExecutionState::WaitingForDTack:
// If DTack or bus error has been signalled, stop waiting.
if(dtack_ || bus_error_) {
execution_state_ = ExecutionState::Executing;
break;
}
// Otherwise, signal another cycle of wait.
cycles_run_for +=
dtack_cycle_.length +
bus_handler_.perform_bus_operation(dtack_cycle_, is_supervisor_);
continue;
case ExecutionState::Halted:
if(!halt_) break;
cycles_run_for +=
stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue;
}
case ExecutionState::Executing:
// Check for entry into the halted state.
if(halt_ && active_step_[0].microcycle.operation & Microcycle::NewAddress) {
execution_state_ = ExecutionState::Halted;
@ -113,7 +75,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
}
// Check for bus error.
if(bus_error_) {
if(bus_error_ && !is_starting_interrupt_) {
active_program_ = nullptr;
active_micro_op_ = long_exception_micro_ops_;
active_step_ = active_micro_op_->bus_program;
@ -137,6 +99,55 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
cycles_run_for +=
active_step_->microcycle.length +
bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_);
break;
case ExecutionState::Stopped:
// If an interrupt (TODO: or reset) has finally arrived that will be serviced,
// exit the STOP.
if(bus_interrupt_level_ > interrupt_level_) {
// TODO: schedule interrupt right here.
execution_state_ = ExecutionState::BeginInterrupt;
continue;
}
// Otherwise continue being stopped.
cycles_run_for +=
stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue;
case ExecutionState::WaitingForDTack:
// If DTack or bus error has been signalled, stop waiting.
if(dtack_ || bus_error_) {
execution_state_ = ExecutionState::Executing;
continue;
}
// Otherwise, signal another cycle of wait.
cycles_run_for +=
dtack_cycle_.length +
bus_handler_.perform_bus_operation(dtack_cycle_, is_supervisor_);
continue;
case ExecutionState::Halted:
if(!halt_) {
execution_state_ = ExecutionState::Executing;
continue;
}
cycles_run_for +=
stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue;
case ExecutionState::BeginInterrupt:
active_program_ = nullptr;
active_micro_op_ = interrupt_micro_ops_;
execution_state_ = ExecutionState::Executing;
is_starting_interrupt_ = true;
break;
}
#ifdef LOG_TRACE
if(!(active_step_->microcycle.operation & Microcycle::IsProgram)) {
@ -195,7 +206,10 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
// Either the micro-operations for this instruction have been exhausted, or
// no instruction was ongoing. Either way, do a standard instruction operation.
// TODO: is an interrupt pending?
if(bus_interrupt_level_ > interrupt_level_) {
execution_state_ = ExecutionState::BeginInterrupt;
break;
}
if(trace_flag_) {
// The user has set the trace bit in the status register.
@ -1805,6 +1819,9 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
// Otherwise, the vector is whatever we were just told it is.
effective_address_[0].full = source_bus_data_[0].halves.low.halves.low << 4;
// Let bus error go back to causing exceptions.
is_starting_interrupt_ = false;
break;
case int(MicroOp::Action::CopyNextWord):

View File

@ -35,7 +35,10 @@ class ProcessorStorage {
/// Occurs at the end of the current bus cycle after detection of the HALT input, continuing until
/// HALT is no longer signalled.
Halted
Halted,
/// Signals a transition from some other straight directly to cueing up an interrupt.
BeginInterrupt,
} execution_state_ = ExecutionState::Executing;
Microcycle dtack_cycle_;
Microcycle stop_cycle_;
@ -60,6 +63,7 @@ class ProcessorStorage {
bool halt_ = false;
int accepted_interrupt_level_ = 0;
bool is_starting_interrupt_ = false;
// Generic sources and targets for memory operations;
// by convention: [0] = source, [1] = destination.