mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Makes some effort at getting into interrupt processing.
This commit is contained in:
parent
f6ac407e4d
commit
2e5c0811e7
@ -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):
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user