1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +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;
}
/// Sets the halt line.
void set_halt(bool halt) {
halt_ = halt;
}
private:
T &bus_handler_;
};

View File

@ -43,8 +43,12 @@
((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) {
HalfCycles remaining_duration = duration + half_cycles_left_to_run_;
while(remaining_duration > HalfCycles(0)) {
const HalfCycles remaining_duration = duration + half_cycles_left_to_run_;
// 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.
*/
@ -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,
// exit the STOP.
if(bus_interrupt_level_ > interrupt_level_) {
// TODO: schedule interrupt right here.
execution_state_ = ExecutionState::Executing;
break;
}
// Otherwise continue being stopped.
remaining_duration -=
cycles_run_for +=
stop_cycle_.length +
bus_handler_.perform_bus_operation(stop_cycle_, is_supervisor_);
continue;
@ -74,13 +79,31 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
}
// Otherwise, signal another cycle of wait.
remaining_duration -=
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;
}
// 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()) {
// 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_) {
execution_state_ = ExecutionState::WaitingForDTack;
dtack_cycle_ = active_step_->microcycle;
@ -89,7 +112,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
continue;
}
// Check for bus error here.
// Check for bus error.
if(bus_error_) {
active_program_ = nullptr;
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.
remaining_duration -=
cycles_run_for +=
active_step_->microcycle.length +
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() {

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.
enum class ExecutionState {
/// The normal mode, this means the 68000 is expending processing effort.
Executing,
/// The 68000 is in a holding loop, waiting for either DTack or to be notified of a bus error.
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;
Microcycle dtack_cycle_;
Microcycle stop_cycle_;
@ -48,6 +57,7 @@ class ProcessorStorage {
bool bus_error_ = false;
bool bus_request_ = false;
bool bus_acknowledge_ = false;
bool halt_ = false;
// Generic sources and targets for memory operations;
// by convention: [0] = source, [1] = destination.
@ -56,6 +66,7 @@ class ProcessorStorage {
RegisterPair32 destination_bus_data_[1];
HalfCycles half_cycles_left_to_run_;
HalfCycles e_clock_phase_;
enum class Operation {
None,