mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-27 22:30:49 +00:00
A theoretical 68000 could now perform its /RESET. That's all though.
This commit is contained in:
parent
de56d48b2f
commit
98aa597510
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user