1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-04 17:56:29 +00:00

Adds support for HALT as an input, and puts some effort into how to calculate E.

This commit is contained in:
Thomas Harte 2019-04-30 22:07:48 -04:00
parent f1879c5fbc
commit 92568c90c8
3 changed files with 48 additions and 8 deletions

View File

@ -253,6 +253,11 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform = false> cla
bus_acknowledge_ = bus_acknowledge; bus_acknowledge_ = bus_acknowledge;
} }
/// Sets the halt line.
void set_halt(bool halt) {
halt_ = halt;
}
private: private:
T &bus_handler_; T &bus_handler_;
}; };

View File

@ -43,8 +43,12 @@
((active_step_->microcycle.operation & Microcycle::Read) ? 0x10 : 0) ((active_step_->microcycle.operation & Microcycle::Read) ? 0x10 : 0)
template <class T, bool dtack_is_implicit, bool signal_will_perform> void Processor<T, dtack_is_implicit, signal_will_perform>::run_for(HalfCycles duration) { template <class T, bool dtack_is_implicit, bool signal_will_perform> void Processor<T, dtack_is_implicit, signal_will_perform>::run_for(HalfCycles duration) {
HalfCycles remaining_duration = duration + half_cycles_left_to_run_; const HalfCycles remaining_duration = duration + half_cycles_left_to_run_;
while(remaining_duration > HalfCycles(0)) {
// This loop counts upwards rather than downwards because it simplifies calculation of
// E as and when required.
HalfCycles cycles_run_for;
while(cycles_run_for < remaining_duration) {
/* /*
PERFORM THE CURRENT BUS STEP'S MICROCYCLE. PERFORM THE CURRENT BUS STEP'S MICROCYCLE.
*/ */
@ -56,12 +60,13 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
// If an interrupt (TODO: or reset) has finally arrived that will be serviced, // If an interrupt (TODO: or reset) has finally arrived that will be serviced,
// exit the STOP. // exit the STOP.
if(bus_interrupt_level_ > interrupt_level_) { if(bus_interrupt_level_ > interrupt_level_) {
// TODO: schedule interrupt right here.
execution_state_ = ExecutionState::Executing; execution_state_ = ExecutionState::Executing;
break; break;
} }
// Otherwise continue being stopped. // Otherwise continue being stopped.
remaining_duration -= cycles_run_for +=
stop_cycle_.length + stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_); bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue; continue;
@ -74,13 +79,31 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
} }
// Otherwise, signal another cycle of wait. // Otherwise, signal another cycle of wait.
remaining_duration -= cycles_run_for +=
dtack_cycle_.length + dtack_cycle_.length +
bus_handler_.perform_bus_operation(dtack_cycle_, is_supervisor_); bus_handler_.perform_bus_operation(dtack_cycle_, is_supervisor_);
continue; continue;
case ExecutionState::Halted:
if(!halt_) break;
cycles_run_for +=
stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue;
}
// Check for entry into the halted state.
if(halt_ && active_step_[0].microcycle.operation & Microcycle::NewAddress) {
execution_state_ = ExecutionState::Halted;
continue;
} }
if(active_step_->microcycle.data_select_active()) { if(active_step_->microcycle.data_select_active()) {
// TODO: if valid peripheral address is asserted, substitute a
// synhronous bus access.
// Check whether the processor needs to await DTack.
if(!dtack_is_implicit && !dtack_ && !bus_error_) { if(!dtack_is_implicit && !dtack_ && !bus_error_) {
execution_state_ = ExecutionState::WaitingForDTack; execution_state_ = ExecutionState::WaitingForDTack;
dtack_cycle_ = active_step_->microcycle; dtack_cycle_ = active_step_->microcycle;
@ -89,7 +112,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
continue; continue;
} }
// Check for bus error here. // Check for bus error.
if(bus_error_) { if(bus_error_) {
active_program_ = nullptr; active_program_ = nullptr;
active_micro_op_ = long_exception_micro_ops_; active_micro_op_ = long_exception_micro_ops_;
@ -111,7 +134,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
} }
// Perform the microcycle. // Perform the microcycle.
remaining_duration -= cycles_run_for +=
active_step_->microcycle.length + active_step_->microcycle.length +
bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_); bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_);
@ -1933,7 +1956,8 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
} }
} }
half_cycles_left_to_run_ = remaining_duration; e_clock_phase_ = (e_clock_phase_ + cycles_run_for) % 10;
half_cycles_left_to_run_ = remaining_duration - cycles_run_for;
} }
template <class T, bool dtack_is_implicit, bool signal_will_perform> ProcessorState Processor<T, dtack_is_implicit, signal_will_perform>::get_state() { template <class T, bool dtack_is_implicit, bool signal_will_perform> ProcessorState Processor<T, dtack_is_implicit, signal_will_perform>::get_state() {

View File

@ -24,9 +24,18 @@ class ProcessorStorage {
RegisterPair32 prefetch_queue_; // Each word will go into the low part of the word, then proceed upward. RegisterPair32 prefetch_queue_; // Each word will go into the low part of the word, then proceed upward.
enum class ExecutionState { enum class ExecutionState {
/// The normal mode, this means the 68000 is expending processing effort.
Executing, Executing,
/// The 68000 is in a holding loop, waiting for either DTack or to be notified of a bus error.
WaitingForDTack, WaitingForDTack,
Stopped
/// Occurs after executing a STOP instruction; the processor will idle waiting for an interrupt or reset.
Stopped,
/// Occurs at the end of the current bus cycle after detection of the HALT input, continuing until
/// HALT is no longer signalled.
Halted
} execution_state_ = ExecutionState::Executing; } execution_state_ = ExecutionState::Executing;
Microcycle dtack_cycle_; Microcycle dtack_cycle_;
Microcycle stop_cycle_; Microcycle stop_cycle_;
@ -48,6 +57,7 @@ class ProcessorStorage {
bool bus_error_ = false; bool bus_error_ = false;
bool bus_request_ = false; bool bus_request_ = false;
bool bus_acknowledge_ = false; bool bus_acknowledge_ = false;
bool halt_ = false;
// Generic sources and targets for memory operations; // Generic sources and targets for memory operations;
// by convention: [0] = source, [1] = destination. // by convention: [0] = source, [1] = destination.
@ -56,6 +66,7 @@ class ProcessorStorage {
RegisterPair32 destination_bus_data_[1]; RegisterPair32 destination_bus_data_[1];
HalfCycles half_cycles_left_to_run_; HalfCycles half_cycles_left_to_run_;
HalfCycles e_clock_phase_;
enum class Operation { enum class Operation {
None, None,