diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 24d597caa..5d9de8a77 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -779,8 +779,10 @@ template void Proces case Operation::DIVU: { // An attempt to divide by zero schedules an exception. if(!active_program_->source->halves.low.full) { - // TODO: schedule an exception. - assert(false); + // Schedule a divide-by-zero exception. + active_program_ = nullptr; + active_micro_op_ = exception_micro_ops_; + populate_trap_steps(5, get_status()); break; } @@ -838,8 +840,10 @@ template void Proces case Operation::DIVS: { // An attempt to divide by zero schedules an exception. if(!active_program_->source->halves.low.full) { - // TODO: schedule an exception. - assert(false); + // Schedule a divide-by-zero exception. + active_program_ = nullptr; + active_micro_op_ = exception_micro_ops_; + populate_trap_steps(5, get_status()); break; } @@ -1073,8 +1077,8 @@ template void Proces case Operation::TRAP: { // Select the trap steps as next; the initial microcycle should be 4 cycles long. bus_program = trap_steps_; - bus_program->microcycle.length = HalfCycles(8); populate_trap_steps((decoded_instruction_ & 15) + 32, get_status()); + bus_program->microcycle.length = HalfCycles(8); // The program counter to push is actually one slot ago. program_counter_.full -= 2; @@ -1084,8 +1088,8 @@ template void Proces if(overflow_flag_) { // Select the trap steps as next; the initial microcycle should be 4 cycles long. bus_program = trap_steps_; - bus_program->microcycle.length = HalfCycles(0); populate_trap_steps(7, get_status()); + bus_program->microcycle.length = HalfCycles(0); program_counter_.full -= 4; } } break; @@ -1100,12 +1104,12 @@ template void Proces negative_flag_ = is_under ? 1 : 0; bus_program = trap_steps_; + populate_trap_steps(6, get_status()); if(is_under) { bus_program->microcycle.length = HalfCycles(16); } else { bus_program->microcycle.length = HalfCycles(8); } - populate_trap_steps(6, get_status()); // The program counter to push is two slots ago as whatever was the correct prefetch // to continue without an exception has already happened, just in case. diff --git a/Processors/68000/Implementation/68000Storage.cpp b/Processors/68000/Implementation/68000Storage.cpp index 8b2dcaad3..8e88ce25b 100644 --- a/Processors/68000/Implementation/68000Storage.cpp +++ b/Processors/68000/Implementation/68000Storage.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace CPU { namespace MC68000 { @@ -364,9 +365,33 @@ struct ProcessorStorageConstructor { return size_t(position - storage_.all_bus_steps_.begin()); } +/* + // If the new steps already exist, just return the existing index to them; + // otherwise insert them. A lookup table of steps to start positions within + // all_bus_steps_ is maintained to shorten setup time here + auto potential_locations = locations_by_bus_step_[steps.front()]; + for(auto index: potential_locations) { + if(index + steps.size() >= storage_.all_bus_steps_.size()) continue; + + if(std::equal( + storage_.all_bus_steps_.begin() + ssize_t(index), + storage_.all_bus_steps_.begin() + ssize_t(index + steps.size()), + steps.begin())) { + return index; + } + } + + // Copy to the end, and update potential_locations. const auto start = storage_.all_bus_steps_.size(); std::copy(steps.begin(), steps.end(), std::back_inserter(storage_.all_bus_steps_)); + auto index = start; + for(const auto &step: steps) { + locations_by_bus_step_[step].push_back(index); + ++index; + } + return start; +*/ } /*! @@ -3466,10 +3491,29 @@ struct ProcessorStorageConstructor { } } } + + printf("%lu total steps\n", storage_.all_bus_steps_.size()); } private: ProcessorStorage &storage_; + +/* struct BusStepOrderer { + bool operator()( BusStep const& lhs, BusStep const& rhs ) const { + int action_diff = int(lhs.action) - int(rhs.action); + if(action_diff < 0) { + return true; + } + if(action_diff > 0) { + return false; + } + + return + std::make_tuple(lhs.microcycle.value, lhs.microcycle.address, lhs.microcycle.length, lhs.microcycle.operation) < + std::make_tuple(rhs.microcycle.value, rhs.microcycle.address, rhs.microcycle.length, rhs.microcycle.operation); + } + }; + std::map, BusStepOrderer> locations_by_bus_step_;*/ }; } @@ -3514,7 +3558,9 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() { all_micro_ops_.emplace_back(); // Install operations. + const std::clock_t start = std::clock(); constructor.install_instructions(); + std::cout << "Construction took " << double(std::clock() - start) / double(CLOCKS_PER_SEC / 1000) << "ms" << std::endl; // Realise the special programs as direct pointers. reset_bus_steps_ = &all_bus_steps_[reset_offset]; diff --git a/Processors/68000/Implementation/68000Storage.hpp b/Processors/68000/Implementation/68000Storage.hpp index 3e598be6a..acebfaf78 100644 --- a/Processors/68000/Implementation/68000Storage.hpp +++ b/Processors/68000/Implementation/68000Storage.hpp @@ -421,6 +421,9 @@ class ProcessorStorage { precomputed_addresses_[1] = address_[7].full - 6; precomputed_addresses_[2] = address_[7].full - 4; address_[7].full -= 6; + + // Set the default timing. + trap_steps_->microcycle.length = HalfCycles(8); }