From 92568c90c84ed2fee5920b86a86e88cf6794335c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 30 Apr 2019 22:07:48 -0400 Subject: [PATCH] Adds support for HALT as an input, and puts some effort into how to calculate E. --- Processors/68000/68000.hpp | 5 +++ .../Implementation/68000Implementation.hpp | 38 +++++++++++++++---- .../68000/Implementation/68000Storage.hpp | 13 ++++++- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Processors/68000/68000.hpp b/Processors/68000/68000.hpp index faca0b082..b4c9364b0 100644 --- a/Processors/68000/68000.hpp +++ b/Processors/68000/68000.hpp @@ -253,6 +253,11 @@ template cla bus_acknowledge_ = bus_acknowledge; } + /// Sets the halt line. + void set_halt(bool halt) { + halt_ = halt; + } + private: T &bus_handler_; }; diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 4b8408a61..11450d2e3 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -43,8 +43,12 @@ ((active_step_->microcycle.operation & Microcycle::Read) ? 0x10 : 0) template void Processor::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 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 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 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 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 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 ProcessorState Processor::get_state() { diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 8c729355c..afa0ce93a 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -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,