mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-19 23:29:05 +00:00
Merge pull request #1006 from TomHarte/Shared68000Tables
Minor 68000 style improvements.
This commit is contained in:
commit
4d9589af7c
@ -332,8 +332,8 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
// should_log = (fetched_pc >= 0x408D66) && (fetched_pc <= 0x408D84);
|
// should_log = (fetched_pc >= 0x408D66) && (fetched_pc <= 0x408D84);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(instructions[decoded_instruction_.full].micro_operations != std::numeric_limits<uint32_t>::max()) {
|
if(instructions[decoded_instruction_.full].micro_operations != Program::NoSuchProgram) {
|
||||||
if((instructions[decoded_instruction_.full].source_dest & 0x80) && !is_supervisor_) {
|
if((instructions[decoded_instruction_.full].requires_supervisor) && !is_supervisor_) {
|
||||||
// A privilege violation has been detected.
|
// A privilege violation has been detected.
|
||||||
active_program_ = nullptr;
|
active_program_ = nullptr;
|
||||||
active_micro_op_ = short_exception_micro_ops_;
|
active_micro_op_ = short_exception_micro_ops_;
|
||||||
@ -387,9 +387,9 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
|||||||
|
|
||||||
#define offset_pointer(x) reinterpret_cast<RegisterPair32 *>(&reinterpret_cast<uint8_t *>(static_cast<ProcessorStorage *>(this))[x])
|
#define offset_pointer(x) reinterpret_cast<RegisterPair32 *>(&reinterpret_cast<uint8_t *>(static_cast<ProcessorStorage *>(this))[x])
|
||||||
#define source() offset_pointer(active_program_->source_offset)
|
#define source() offset_pointer(active_program_->source_offset)
|
||||||
#define source_address() address_[(active_program_->source_dest >> 4) & 7]
|
#define source_address() address_[active_program_->source]
|
||||||
#define destination() offset_pointer(active_program_->destination_offset)
|
#define destination() offset_pointer(active_program_->destination_offset)
|
||||||
#define destination_address() address_[active_program_->source_dest & 7]
|
#define destination_address() address_[active_program_->dest]
|
||||||
|
|
||||||
case int_type(MicroOp::Action::PerformOperation):
|
case int_type(MicroOp::Action::PerformOperation):
|
||||||
#define sub_overflow() ((result ^ destination) & (destination ^ source))
|
#define sub_overflow() ((result ^ destination) & (destination ^ source))
|
||||||
|
@ -3151,9 +3151,11 @@ struct ProcessorStorageConstructor {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
// Finalise micro-op and program pointers.
|
// Finalise micro-op and program pointers.
|
||||||
|
int total_instructions = 0;
|
||||||
for(size_t instruction = 0; instruction < 65536; ++instruction) {
|
for(size_t instruction = 0; instruction < 65536; ++instruction) {
|
||||||
if(micro_op_pointers[instruction] != std::numeric_limits<size_t>::max()) {
|
if(micro_op_pointers[instruction] != std::numeric_limits<size_t>::max()) {
|
||||||
storage_.instructions[instruction].micro_operations = uint32_t(micro_op_pointers[instruction]);
|
storage_.instructions[instruction].micro_operations = uint32_t(micro_op_pointers[instruction]);
|
||||||
|
++total_instructions;
|
||||||
// link_operations(&storage_.all_micro_ops_[micro_op_pointers[instruction]], &arbitrary_base);
|
// link_operations(&storage_.all_micro_ops_[micro_op_pointers[instruction]], &arbitrary_base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3162,8 +3164,10 @@ struct ProcessorStorageConstructor {
|
|||||||
storage_.interrupt_micro_ops_ = &storage_.all_micro_ops_[interrupt_pointer];
|
storage_.interrupt_micro_ops_ = &storage_.all_micro_ops_[interrupt_pointer];
|
||||||
// link_operations(storage_.interrupt_micro_ops_, &arbitrary_base);
|
// link_operations(storage_.interrupt_micro_ops_, &arbitrary_base);
|
||||||
|
|
||||||
std::cout << storage_.all_bus_steps_.size() << " total bus steps" << std::endl;
|
std::cout << total_instructions << " total opcodes" << std::endl;
|
||||||
std::cout << storage_.all_micro_ops_.size() << " total micro ops" << std::endl;
|
std::cout << storage_.all_bus_steps_.size() << " total bus steps; at " << sizeof(BusStep) << " bytes per bus step implies " << storage_.all_bus_steps_.size() * sizeof(BusStep) << " bytes" << std::endl;
|
||||||
|
std::cout << storage_.all_micro_ops_.size() << " total micro ops; at " << sizeof(MicroOp) << " bytes per micro-op implies " << storage_.all_micro_ops_.size() * sizeof(MicroOp) << " bytes" << std::endl;
|
||||||
|
std::cout << "(Microcycles being " << sizeof(Microcycle) << " bytes; ProcessorStorage being " << sizeof(ProcessorStorage) << " bytes, or " << sizeof(ProcessorStorage) - sizeof(ProcessorStorage::instructions) << " bytes without the instructions table)" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -326,22 +326,24 @@ class ProcessorStorage {
|
|||||||
// steps detail appropriately.
|
// steps detail appropriately.
|
||||||
PrepareINTVector,
|
PrepareINTVector,
|
||||||
};
|
};
|
||||||
static constexpr int SourceMask = 1 << 7;
|
static_assert(uint8_t(Action::PrepareINTVector) < 32); // i.e. will fit into five bits.
|
||||||
|
|
||||||
|
static constexpr int SourceMask = 1 << 5;
|
||||||
static constexpr int DestinationMask = 1 << 6;
|
static constexpr int DestinationMask = 1 << 6;
|
||||||
uint8_t action = uint8_t(Action::None);
|
uint8_t action = uint8_t(Action::None); // Requires 7 bits at present; sizeof(Action) + the two flags above.
|
||||||
|
|
||||||
static constexpr uint16_t NoBusProgram = std::numeric_limits<uint16_t>::max();
|
static constexpr uint16_t NoBusProgram = std::numeric_limits<uint16_t>::max();
|
||||||
uint16_t bus_program = NoBusProgram;
|
uint16_t bus_program = NoBusProgram; // Empirically requires 11 bits at present.
|
||||||
|
|
||||||
MicroOp() {}
|
MicroOp(): action(uint8_t(Action::None)), bus_program(NoBusProgram) {}
|
||||||
MicroOp(uint8_t action) : action(action) {}
|
MicroOp(uint8_t action) : action(action), bus_program(NoBusProgram) {}
|
||||||
MicroOp(uint8_t action, uint16_t bus_program) : action(action), bus_program(bus_program) {}
|
MicroOp(uint8_t action, uint16_t bus_program) : action(action), bus_program(bus_program) {}
|
||||||
|
|
||||||
MicroOp(Action action) : MicroOp(uint8_t(action)) {}
|
MicroOp(Action action) : MicroOp(uint8_t(action)) {}
|
||||||
MicroOp(Action action, uint16_t bus_program) : MicroOp(uint8_t(action), bus_program) {}
|
MicroOp(Action action, uint16_t bus_program) : MicroOp(uint8_t(action), bus_program) {}
|
||||||
|
|
||||||
forceinline bool is_terminal() const {
|
forceinline bool is_terminal() const {
|
||||||
return bus_program == std::numeric_limits<uint16_t>::max();
|
return bus_program == NoBusProgram;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,33 +361,48 @@ class ProcessorStorage {
|
|||||||
remaining fields, with no additional padding being inserted by the compiler.
|
remaining fields, with no additional padding being inserted by the compiler.
|
||||||
*/
|
*/
|
||||||
struct Program {
|
struct Program {
|
||||||
|
Program() {
|
||||||
|
// Initialisers for bitfields aren't available until C++20. So, yuck, do it manually.
|
||||||
|
requires_supervisor = 0;
|
||||||
|
source = 0;
|
||||||
|
dest = 0;
|
||||||
|
destination_offset = 0;
|
||||||
|
source_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr uint32_t NoSuchProgram = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
/// The offset into the all_micro_ops_ at which micro-ops for this instruction begin,
|
/// The offset into the all_micro_ops_ at which micro-ops for this instruction begin,
|
||||||
/// or std::numeric_limits<uint32_t>::max() if this is an invalid Program.
|
/// or std::numeric_limits<uint32_t>::max() if this is an invalid Program.
|
||||||
uint32_t micro_operations = std::numeric_limits<uint32_t>::max();
|
uint32_t micro_operations = NoSuchProgram;
|
||||||
/// The overarching operation applied by this program when the moment comes.
|
/// The overarching operation applied by this program when the moment comes.
|
||||||
Operation operation;
|
Operation operation;
|
||||||
/// The number of bytes after the beginning of an instance of ProcessorStorage that the RegisterPair32 containing
|
/// The number of bytes after the beginning of an instance of ProcessorStorage that the RegisterPair32 containing
|
||||||
/// a source value for this operation lies at.
|
/// a source value for this operation lies at.
|
||||||
uint8_t source_offset = 0;
|
uint8_t source_offset: 7;
|
||||||
/// The number of bytes after the beginning of an instance of ProcessorStorage that the RegisterPair32 containing
|
/// The number of bytes after the beginning of an instance of ProcessorStorage that the RegisterPair32 containing
|
||||||
/// a destination value for this operation lies at.
|
/// a destination value for this operation lies at.
|
||||||
uint8_t destination_offset = 0;
|
uint8_t destination_offset: 7;
|
||||||
/// A bitfield comprised of:
|
/// Set if this program requires supervisor mode.
|
||||||
/// b7 = set if this program requires supervisor mode;
|
bool requires_supervisor: 1;
|
||||||
/// b0–b2 = the source address register (for pre-decrement and post-increment actions); and
|
/// The source address register (for pre-decrement and post-increment actions).
|
||||||
/// b4-b6 = destination address register.
|
uint8_t source: 3;
|
||||||
uint8_t source_dest = 0;
|
/// Destination address register.
|
||||||
|
uint8_t dest: 3;
|
||||||
|
|
||||||
void set_source_address([[maybe_unused]] ProcessorStorage &storage, int index) {
|
void set_source_address([[maybe_unused]] ProcessorStorage &storage, int index) {
|
||||||
source_dest = uint8_t((source_dest & 0x0f) | (index << 4));
|
source = uint8_t(index);
|
||||||
|
assert(int(source) == index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_destination_address([[maybe_unused]] ProcessorStorage &storage, int index) {
|
void set_destination_address([[maybe_unused]] ProcessorStorage &storage, int index) {
|
||||||
source_dest = uint8_t((source_dest & 0xf0) | index);
|
dest = uint8_t(index);
|
||||||
|
assert(int(dest) == index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_requires_supervisor(bool requires_supervisor) {
|
void set_requires_supervisor(bool req) {
|
||||||
source_dest = (source_dest & 0x7f) | (requires_supervisor ? 0x80 : 0x00);
|
requires_supervisor = req;
|
||||||
|
assert(requires_supervisor == req);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_source(ProcessorStorage &storage, RegisterPair32 *target) {
|
void set_source(ProcessorStorage &storage, RegisterPair32 *target) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user