mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Adds support for HALT as an input, and puts some effort into how to calculate E.
This commit is contained in:
parent
f1879c5fbc
commit
92568c90c8
@ -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_;
|
||||
};
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user