1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

A theoretical 68000 could now perform its /RESET. That's all though.

This commit is contained in:
Thomas Harte 2019-03-10 17:42:13 -04:00
parent de56d48b2f
commit 98aa597510
4 changed files with 54 additions and 35 deletions

View File

@ -52,6 +52,9 @@ struct Microcycle {
static const int LowerData = 1 << 2;
static const int ReadWrite = 1 << 3; // Set = read; unset = write.
static const int IsData = 1 << 4; // i.e. this is FC0.
static const int IsProgram = 1 << 5; // i.e. this is FC1.
int operation = 0;
HalfCycles length = HalfCycles(2);
@ -72,29 +75,13 @@ struct Microcycle {
*/
class BusHandler {
public:
static const int Data = 1 << 0;
static const int Program = 1 << 1;
static const int Supervisor = 1 << 2;
static const int Interrupt = Data | Program | Supervisor;
/*!
Provides the bus handler with a single Microcycle to 'perform', along with the
contents of the FC0, FC1 and FC2 lines by way of processor_status. The symbols
above, Data, Program, Supervisor and Interrupt can be used to help to decode the
processor status if desired; in summary:
Provides the bus handler with a single Microcycle to 'perform'.
If all three bits are set, this is an interrupt acknowledgement.
If the data bit is set, the 68000 is fetching data.
If the program bit is set, the 68000 is fetching instructions.
It the supervisor bit is set, the 68000 is currently in supervisor mode.
Neither program nor data being set has an undefined meaning. As does both program
and data being set, but this not being an interrupt.
FC0 and FC1 are provided inside the microcycle as the IsData and IsProgram
flags; FC2 is provided here as is_supervisor it'll be either 0 or 1.
*/
HalfCycles perform_bus_operation(const Microcycle &cycle, int processor_status) {
HalfCycles perform_bus_operation(const Microcycle &cycle, int is_supervisor) {
return HalfCycles(0);
}
@ -106,7 +93,7 @@ class BusHandler {
class ProcessorBase: public ProcessorStorage {
};
template <class T> class Processor: public ProcessorBase {
template <class T, bool dtack_is_implicit> class Processor: public ProcessorBase {
public:
void run_for(const Cycles cycles);

View File

@ -6,5 +6,43 @@
// Copyright © 2019 Thomas Harte. All rights reserved.
//
template <class T> void Processor<T>::run_for(Cycles cycles) {
template <class T, bool dtack_is_implicit> void Processor<T, dtack_is_implicit>::run_for(Cycles cycles) {
// TODO: obey the 'cycles' count.
while(true) {
// Check whether the program is exhausted.
if(active_program_->action == Step::Action::ScheduleNextProgram) {
std::cerr << "68000 Abilities exhausted" << std::endl;
return;
}
// The program is not exhausted, so perform the microcycle.
// Check for DTack if this isn't being treated implicitly.
if(!dtack_is_implicit) {
if(active_program_->microcycle.operation & (Microcycle::UpperData | Microcycle::LowerData) && !dtack_) {
// TODO: perform wait state.
continue;
}
}
// Perform the microcycle.
bus_handler_.perform_bus_operation(active_program_->microcycle, is_supervisor_);
// Perform the post-hoc action.
switch(active_program_->action) {
default:
std::cerr << "Unimplemented 68000 action: " << int(active_program_->action) << std::endl;
return;
break;
case Step::Action::None: break;
case Step::Action::IncrementEffectiveAddress: effective_address_ += 2; break;
case Step::Action::IncrementProgramCounter: program_counter_.full += 2; break;
case Step::Action::AdvancePrefetch:
prefetch_queue_[0] = prefetch_queue_[1];
break;
}
}
}

View File

@ -16,6 +16,7 @@ ProcessorStorage::ProcessorStorage() {
// Set initial state. Largely TODO.
active_program_ = reset_program_.data();
effective_address_ = 0;
is_supervisor_ = 1;
}
// TODO: allow actions to be specified, of course.
@ -49,7 +50,7 @@ std::vector<ProcessorStorage::Step> ProcessorStorage::assemble_program(const cha
case 'F': // Fetch SSP MSW.
case 'f': // Fetch SSP LSW.
step.microcycle.length = HalfCycles(5);
step.microcycle.operation = Microcycle::Address | Microcycle::ReadWrite;
step.microcycle.operation = Microcycle::Address | Microcycle::ReadWrite | Microcycle::IsProgram; // IsProgram is a guess.
step.microcycle.address = &effective_address_;
step.microcycle.value = isupper(access_pattern[1]) ? &stack_pointers_[1].halves.high : &stack_pointers_[1].halves.low;
steps.push_back(step);
@ -65,7 +66,7 @@ std::vector<ProcessorStorage::Step> ProcessorStorage::assemble_program(const cha
case 'V': // Fetch exception vector low.
case 'v': // Fetch exception vector high.
step.microcycle.length = HalfCycles(5);
step.microcycle.operation = Microcycle::Address | Microcycle::ReadWrite;
step.microcycle.operation = Microcycle::Address | Microcycle::ReadWrite | Microcycle::IsProgram; // IsProgram is a guess.
step.microcycle.address = &effective_address_;
step.microcycle.value = isupper(access_pattern[1]) ? &program_counter_.halves.high : &program_counter_.halves.low;
steps.push_back(step);
@ -80,7 +81,7 @@ std::vector<ProcessorStorage::Step> ProcessorStorage::assemble_program(const cha
case 'p': // Fetch from the program counter into the prefetch queue.
step.microcycle.length = HalfCycles(5);
step.microcycle.operation = Microcycle::Address | Microcycle::ReadWrite;
step.microcycle.operation = Microcycle::Address | Microcycle::ReadWrite | Microcycle::IsProgram;
step.microcycle.address = &program_counter_.full;
step.microcycle.value = &prefetch_queue_[1];
step.action = Step::Action::AdvancePrefetch;

View File

@ -20,11 +20,10 @@ class ProcessorStorage {
RegisterPair32 program_counter_;
RegisterPair16 prefetch_queue_[2];
bool dtack_ = true;
enum class State {
Reset,
Normal
};
// Various status bits.
int is_supervisor_;
// Generic sources and targets for memory operations.
uint32_t effective_address_;
@ -64,12 +63,6 @@ class ProcessorStorage {
Step *active_program_ = nullptr;
private:
enum class DataSize {
Byte, Word, LongWord
};
enum class AddressingMode {
};
/*!
Produces a vector of Steps that implement the described program.