From d9071ee9f1514da57177f2ff3b3fdfd228064e90 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 29 Apr 2019 13:45:53 -0400 Subject: [PATCH] Starts sketching out the asynchronous bus. --- OSBindings/Mac/Clock SignalTests/QLTests.mm | 4 +- Processors/68000/68000.hpp | 18 ++ .../Implementation/68000Implementation.hpp | 161 +++++++++--------- .../68000/Implementation/68000Storage.cpp | 2 +- .../68000/Implementation/68000Storage.hpp | 6 +- 5 files changed, 110 insertions(+), 81 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/QLTests.mm b/OSBindings/Mac/Clock SignalTests/QLTests.mm index 5a3d1a731..0088c5e33 100644 --- a/OSBindings/Mac/Clock SignalTests/QLTests.mm +++ b/OSBindings/Mac/Clock SignalTests/QLTests.mm @@ -60,8 +60,8 @@ class QL: public CPU::MC68000::BusHandler { // Check that the two coincide. if(strcmp(correct_state, local_state)) { fprintf(stderr, "Diverges at line %d\n", line_count); - fprintf(stderr, "Good: %s", correct_state); - fprintf(stderr, "Bad: %s", local_state); + fprintf(stderr, "Good: %s\n", correct_state); + fprintf(stderr, "Bad: %s\n", local_state); assert(false); } } diff --git a/Processors/68000/68000.hpp b/Processors/68000/68000.hpp index 830f0f186..b230c5a69 100644 --- a/Processors/68000/68000.hpp +++ b/Processors/68000/68000.hpp @@ -220,6 +220,24 @@ template cla State get_state(); void set_state(const State &); + /// Sets the DTack line — @c true for active, @c false for inactive. + void set_dtack(bool); + + /// Sets the VPA (valid peripheral address) line — @c true for active, @c false for inactive. + void set_is_peripheral_address(bool); + + /// Sets the bus error line — @c true for active, @c false for inactive. + void set_bus_error(bool); + + /// Sets the interrupt lines, IPL0, IPL1 and IPL2. + void set_interrupt_level(int); + + /// Sets the bus request line. + void set_bus_request(bool); + + /// Sets the bus acknowledge line. + void set_bus_acknowledge(bool); + private: T &bus_handler_; }; diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 5b77d26f0..56fdef9ab 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -39,6 +39,75 @@ template void Processor::run_for(HalfCycles duration) { HalfCycles remaining_duration = duration + half_cycles_left_to_run_; while(remaining_duration > HalfCycles(0)) { + /* + PERFORM THE CURRENT BUS STEP'S MICROCYCLE. + */ + // Check for DTack if this isn't being treated implicitly. + if(active_step_->microcycle.data_select_active()) { + if(!dtack_is_implicit) { + if(active_step_->microcycle.data_select_active() && !dtack_) { + // TODO: perform wait state. + continue; + } + } + + // TODO: synchronous bus. + } else { + // TODO: check for bus error (but here, or when checking for DTACK?) +// if(active_step_->microcycle.operation & MicroCycle::NewAddress) { +// } + } + + // Perform the microcycle. + remaining_duration -= + active_step_->microcycle.length + + bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_); + +#ifdef LOG_TRACE + if(!(active_step_->microcycle.operation & Microcycle::IsProgram)) { + switch(active_step_->microcycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) { + default: break; + + case Microcycle::SelectWord | Microcycle::Read: + printf("[%08x -> %04x] ", *active_step_->microcycle.address, active_step_->microcycle.value->full); + break; + case Microcycle::SelectByte | Microcycle::Read: + printf("[%08x -> %02x] ", *active_step_->microcycle.address, active_step_->microcycle.value->halves.low); + break; + case Microcycle::SelectWord: + printf("{%04x -> %08x} ", active_step_->microcycle.value->full, *active_step_->microcycle.address); + break; + case Microcycle::SelectByte: + printf("{%02x -> %08x} ", active_step_->microcycle.value->halves.low, *active_step_->microcycle.address); + break; + } + } +#endif + + /* + PERFORM THE BUS STEP'S ACTION. + */ + switch(active_step_->action) { + default: + std::cerr << "Unimplemented 68000 bus step action: " << int(active_step_->action) << std::endl; + return; + break; + + case BusStep::Action::None: break; + + case BusStep::Action::IncrementEffectiveAddress0: effective_address_[0].full += 2; break; + case BusStep::Action::IncrementEffectiveAddress1: effective_address_[1].full += 2; break; + case BusStep::Action::DecrementEffectiveAddress0: effective_address_[0].full -= 2; break; + case BusStep::Action::DecrementEffectiveAddress1: effective_address_[1].full -= 2; break; + case BusStep::Action::IncrementProgramCounter: program_counter_.full += 2; break; + + case BusStep::Action::AdvancePrefetch: + prefetch_queue_.halves.high = prefetch_queue_.halves.low; + break; + } + + // Move to the next bus step. + ++ active_step_; /* FIND THE NEXT MICRO-OP IF UNKNOWN. */ @@ -67,22 +136,29 @@ template void Proces #endif decoded_instruction_ = prefetch_queue_.halves.high.full; - if(!instructions[decoded_instruction_].micro_operations) { - // TODO: once all instructions are implemnted, this should be an instruction error. - std::cerr << "68000 Abilities exhausted; can't manage instruction " << std::hex << decoded_instruction_ << " from " << (program_counter_.full - 4) << std::endl; - return; - } else { #ifdef LOG_TRACE - std::cout << std::hex << (program_counter_.full - 4) << ": " << std::setw(4) << decoded_instruction_ << '\t'; + std::cout << std::hex << (program_counter_.full - 4) << ": " << std::setw(4) << decoded_instruction_ << '\t'; #endif - } if(signal_will_perform) { bus_handler_.will_perform(program_counter_.full - 4, decoded_instruction_); } - active_program_ = &instructions[decoded_instruction_]; - active_micro_op_ = active_program_->micro_operations; + if(instructions[decoded_instruction_].micro_operations) { + active_program_ = &instructions[decoded_instruction_]; + active_micro_op_ = active_program_->micro_operations; + } else { + active_program_ = nullptr; + active_micro_op_ = exception_micro_ops_; // TODO. + + // The vector used dependds on whether this is a vanilla unrecognised instruction, or + // one on the A or F lines. + switch(decoded_instruction_ >> 12) { + default: populate_trap_steps(get_status(), 4); break; + case 0xa: populate_trap_steps(get_status(), 10); break; + case 0xf: populate_trap_steps(get_status(), 11); break; + } + } } auto bus_program = active_micro_op_->bus_program; @@ -1775,73 +1851,6 @@ template void Proces } } } - - - /* - PERFORM THE CURRENT BUS STEP'S MICROCYCLE. - */ - // Check for DTack if this isn't being treated implicitly. - if(!dtack_is_implicit) { - if(active_step_->microcycle.data_select_active() && !dtack_) { - // TODO: perform wait state. - continue; - } - } - - // TODO: synchronous bus. - - // TODO: check for bus error. - - // Perform the microcycle. - remaining_duration -= - active_step_->microcycle.length + - bus_handler_.perform_bus_operation(active_step_->microcycle, is_supervisor_); - -#ifdef LOG_TRACE - if(!(active_step_->microcycle.operation & Microcycle::IsProgram)) { - switch(active_step_->microcycle.operation & (Microcycle::SelectWord | Microcycle::SelectByte | Microcycle::Read)) { - default: break; - - case Microcycle::SelectWord | Microcycle::Read: - printf("[%08x -> %04x] ", *active_step_->microcycle.address, active_step_->microcycle.value->full); - break; - case Microcycle::SelectByte | Microcycle::Read: - printf("[%08x -> %02x] ", *active_step_->microcycle.address, active_step_->microcycle.value->halves.low); - break; - case Microcycle::SelectWord: - printf("{%04x -> %08x} ", active_step_->microcycle.value->full, *active_step_->microcycle.address); - break; - case Microcycle::SelectByte: - printf("{%02x -> %08x} ", active_step_->microcycle.value->halves.low, *active_step_->microcycle.address); - break; - } - } -#endif - - /* - PERFORM THE BUS STEP'S ACTION. - */ - switch(active_step_->action) { - default: - std::cerr << "Unimplemented 68000 bus step action: " << int(active_step_->action) << std::endl; - return; - break; - - case BusStep::Action::None: break; - - case BusStep::Action::IncrementEffectiveAddress0: effective_address_[0].full += 2; break; - case BusStep::Action::IncrementEffectiveAddress1: effective_address_[1].full += 2; break; - case BusStep::Action::DecrementEffectiveAddress0: effective_address_[0].full -= 2; break; - case BusStep::Action::DecrementEffectiveAddress1: effective_address_[1].full -= 2; break; - case BusStep::Action::IncrementProgramCounter: program_counter_.full += 2; break; - - case BusStep::Action::AdvancePrefetch: - prefetch_queue_.halves.high = prefetch_queue_.halves.low; - break; - } - - // Move to the next bus step. - ++ active_step_; } half_cycles_left_to_run_ = remaining_duration; diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index d1c23d9be..56d052f1a 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -3535,7 +3535,7 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() { steps[4].microcycle.value = steps[5].microcycle.value = &program_counter_.halves.low; } - // Set initial state. Largely TODO. + // Set initial state. active_step_ = reset_bus_steps_; effective_address_[0] = 0; is_supervisor_ = 1; diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 27ad8a418..5e5db13d7 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -326,8 +326,9 @@ class ProcessorStorage { // A lookup table from instructions to implementations. Program instructions[65536]; - // Special steps for exception handlers. + // Special steps and programs for exception handlers. BusStep *reset_bus_steps_; + MicroOp *exception_micro_ops_; // Special micro-op sequences and storage for conditionals. BusStep *branch_taken_bus_steps_; @@ -397,8 +398,9 @@ class ProcessorStorage { // Fill in the status word value. destination_bus_data_[0].full = status; - // Switch to supervisor mode. + // Switch to supervisor mode, disable the trace bit. set_is_supervisor(true); + trace_flag_ = 0; // Pick a vector. effective_address_[0].full = vector << 2;