mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-16 16:28:59 +00:00
155 lines
4.4 KiB
C++
155 lines
4.4 KiB
C++
//
|
|
// 68000Storage.hpp
|
|
// Clock Signal
|
|
//
|
|
// Created by Thomas Harte on 08/03/2019.
|
|
// Copyright © 2019 Thomas Harte. All rights reserved.
|
|
//
|
|
|
|
#ifndef MC68000Storage_h
|
|
#define MC68000Storage_h
|
|
|
|
class ProcessorStorage {
|
|
public:
|
|
ProcessorStorage();
|
|
|
|
protected:
|
|
RegisterPair32 data_[8];
|
|
RegisterPair32 address_[8];
|
|
RegisterPair32 program_counter_;
|
|
|
|
RegisterPair32 stack_pointers_[2]; // [0] = user stack pointer; [1] = supervisor; the values from here
|
|
// are copied into/out of address_[7] upon mode switches.
|
|
|
|
RegisterPair16 prefetch_queue_[2];
|
|
bool dtack_ = true;
|
|
|
|
// Various status bits.
|
|
int is_supervisor_;
|
|
uint_fast32_t zero_flag_; // The zero flag is set if this value is zero.
|
|
uint_fast32_t carry_flag_; // The carry flag is set if this value is non-zero.
|
|
uint_fast32_t extend_flag_; // The extend flag is set if this value is non-zero.
|
|
uint_fast32_t overflow_flag_; // The overflow flag is set if this value is non-zero.
|
|
uint_fast32_t negative_flag_; // The negative flag is set if this value is non-zero.
|
|
|
|
// Generic sources and targets for memory operations.
|
|
uint32_t effective_address_;
|
|
RegisterPair32 bus_data_[2];
|
|
|
|
enum class Operation {
|
|
ABCD, SBCD,
|
|
ADD, AND, EOR, OR, SUB,
|
|
|
|
MOVEb, MOVEw, MOVEl
|
|
};
|
|
|
|
/*!
|
|
Bus steps are sequences of things to communicate to the bus.
|
|
Standard behaviour is: (i) perform microcycle; (ii) perform action.
|
|
*/
|
|
struct BusStep {
|
|
Microcycle microcycle;
|
|
enum class Action {
|
|
None,
|
|
|
|
/// Performs effective_address_ += 2.
|
|
IncrementEffectiveAddress,
|
|
|
|
/// Performs program_counter_ += 2.
|
|
IncrementProgramCounter,
|
|
|
|
/// Copies prefetch_queue_[1] to prefetch_queue_[0].
|
|
AdvancePrefetch,
|
|
|
|
/*!
|
|
Terminates an atomic program; if nothing else is pending, schedules the next instruction.
|
|
This action is special in that it usurps any included microcycle. So any Step with this
|
|
as its action acts as an end-of-list sentinel.
|
|
*/
|
|
ScheduleNextProgram
|
|
|
|
} action = Action::None;
|
|
|
|
inline bool operator ==(const BusStep &rhs) const {
|
|
if(action != rhs.action) return false;
|
|
return microcycle == rhs.microcycle;
|
|
}
|
|
|
|
inline bool is_terminal() const {
|
|
return action == Action::ScheduleNextProgram;
|
|
}
|
|
};
|
|
|
|
/*!
|
|
A micro-op is: (i) an action to take; and (ii) a sequence of bus operations
|
|
to perform after taking the action.
|
|
|
|
NOTE: this therefore has the opposite order of behaviour compared to a BusStep,
|
|
the action occurs BEFORE the bus operations, not after.
|
|
|
|
A nullptr bus_program terminates a sequence of micro operations; the is_terminal
|
|
test should be used to query for that. The action on the final operation will
|
|
be performed.
|
|
*/
|
|
struct MicroOp {
|
|
enum class Action {
|
|
None,
|
|
PerformOperation,
|
|
|
|
PredecrementSourceAndDestination1,
|
|
PredecrementSourceAndDestination2,
|
|
PredecrementSourceAndDestination4,
|
|
|
|
SignExtendDestinationWord,
|
|
} action = Action::None;
|
|
BusStep *bus_program = nullptr;
|
|
|
|
MicroOp() {}
|
|
MicroOp(Action action) : action(action) {}
|
|
MicroOp(Action action, BusStep *bus_program) : action(action), bus_program(bus_program) {}
|
|
|
|
inline bool is_terminal() const {
|
|
return bus_program == nullptr;
|
|
}
|
|
};
|
|
|
|
/*!
|
|
A program represents the implementation of a particular opcode, as a sequence
|
|
of micro-ops and, separately, the operation to perform plus whatever other
|
|
fields the operation requires.
|
|
*/
|
|
struct Program {
|
|
MicroOp *micro_operations = nullptr;
|
|
RegisterPair32 *source = nullptr;
|
|
RegisterPair32 *destination = nullptr;
|
|
Operation operation;
|
|
};
|
|
|
|
// Storage for all the sequences of bus steps and micro-ops used throughout
|
|
// the 68000.
|
|
std::vector<BusStep> all_bus_steps_;
|
|
std::vector<MicroOp> all_micro_ops_;
|
|
|
|
// A lookup table from instructions to implementations.
|
|
Program instructions[65536];
|
|
|
|
// Special programs, for exception handlers.
|
|
BusStep *reset_program_;
|
|
|
|
// Current bus step pointer, and outer program pointer.
|
|
Program *active_program_ = nullptr;
|
|
MicroOp *active_micro_op_ = nullptr;
|
|
BusStep *active_step_ = nullptr;
|
|
|
|
/// Copies address_[7] to the proper stack pointer based on current mode.
|
|
void write_back_stack_pointer();
|
|
|
|
/// Sets or clears the supervisor flag, ensuring the stack pointer is properly updated.
|
|
void set_is_supervisor(bool);
|
|
|
|
private:
|
|
friend class ProcessorStorageConstructor;
|
|
};
|
|
|
|
#endif /* MC68000Storage_h */
|