1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-23 03:32:32 +00:00

Start drafting an Executor.

This commit is contained in:
Thomas Harte 2022-04-29 17:12:06 -04:00
parent a103f30d51
commit 9359f6477b
5 changed files with 150 additions and 82 deletions

View File

@ -8,10 +8,6 @@
#include "Decoder.hpp"
// TODO: remove this include. It's a temporary hack to get the performer into the automated build
// while I work on this branch.
#include "Perform.hpp"
#include <cassert>
using namespace InstructionSet::M68k;

View File

@ -0,0 +1,41 @@
//
// Executor.cpp
// Clock Signal
//
// Created by Thomas Harte on 29/04/2022.
// Copyright © 2022 Thomas Harte. All rights reserved.
//
#include "Executor.hpp"
using namespace InstructionSet::M68k;
template <Model model, typename BusHandler>
Executor<model, BusHandler>::Executor(BusHandler &handler) : bus_handler_(handler) {
reset();
}
template <Model model, typename BusHandler>
void Executor<model, BusHandler>::reset() {
}
template <Model model, typename BusHandler>
void Executor<model, BusHandler>::run_for_instructions(int count) {
while(count--) {
// TODO: check interrupt level, trace flag.
// Read the next instruction.
const Preinstruction instruction = decoder_.decode(bus_handler_.template read<uint16_t>(program_counter_.l));
const auto instruction_address = program_counter_.l;
program_counter_.l += 2;
// Obtain the appropriate sequence.
Sequence<model> sequence(instruction.operation);
// Perform it.
while(!sequence.empty()) {
const auto step = sequence.pop_front();
}
}
}

View File

@ -0,0 +1,54 @@
//
// Executor.hpp
// Clock Signal
//
// Created by Thomas Harte on 29/04/2022.
// Copyright © 2022 Thomas Harte. All rights reserved.
//
#ifndef InstructionSets_M68k_Executor_hpp
#define InstructionSets_M68k_Executor_hpp
#include "Decoder.hpp"
#include "Instruction.hpp"
#include "Model.hpp"
#include "Perform.hpp"
#include "Sequence.hpp"
#include "Status.hpp"
namespace InstructionSet {
namespace M68k {
struct BusHandler {
template <typename IntT> void write(uint32_t address, IntT value);
template <typename IntT> IntT read(uint32_t address);
};
/// Ties together the decoder, sequencer and performer to provide an executor for 680x0 instruction streams.
/// As is standard for these executors, no bus- or cache-level fidelity to any real 680x0 is attempted. This is
/// simply an executor of 680x0 code.
template <Model model, typename BusHandler> class Executor {
public:
Executor(BusHandler &);
/// Executes the number of instructions specified;
/// other events — such as initial reset or branching
/// to exceptions — may be zero costed, and interrupts
/// will not necessarily take effect immediately when signalled.
void run_for_instructions(int);
private:
BusHandler &bus_handler_;
Predecoder<model> decoder_;
void reset();
// Processor state.
Status status_;
CPU::SlicedInt32 program_counter_;
};
}
}
#endif /* InstructionSets_M68k_Executor_hpp */

View File

@ -243,21 +243,6 @@ template <
dest.l -= src.l;
break;
// BRA: alters the program counter, exclusively via the prefetch queue.
// case Operation::BRA: {
// const int8_t byte_offset = int8_t(prefetch_queue_.halves.high.halves.low);
//
// // A non-zero offset byte branches by just that amount; otherwise use the word
// // after as an offset. In both cases, treat as signed.
// if(byte_offset) {
// program_counter_.l += uint32_t(byte_offset);
// } else {
// program_counter_.l += u_extend16(prefetch_queue_.w);
// }
// program_counter_.l -= 2;
// } break;
// Two BTSTs: set the zero flag according to the value of the destination masked by
// the bit named in the source modulo the operation size.
// case Operation::BTSTb:
@ -309,63 +294,42 @@ template <
//
// Special case: the condition code is 1, which is ordinarily false. In that case this
// is the trailing step of a BSR.
// case Operation::Bcc: {
// // Grab the 8-bit offset.
// const int8_t byte_offset = int8_t(prefetch_queue_.halves.high.halves.low);
//
// // Check whether this is secretly BSR.
// const bool is_bsr = ((decoded_instruction_.l >> 8) & 0xf) == 1;
//
// // Test the conditional, treating 'false' as true.
// const bool should_branch = is_bsr || evaluate_condition(decoded_instruction_.l >> 8);
//
// // Schedule something appropriate, by rewriting the program for this instruction temporarily.
// if(should_branch) {
// if(byte_offset) {
// program_counter_.l += decltype(program_counter_.l)(byte_offset);
// } else {
// program_counter_.l += u_extend16(prefetch_queue_.w);
// }
// program_counter_.l -= 2;
// bus_program = is_bsr ? bsr_bus_steps_ : branch_taken_bus_steps_;
// } else {
// if(byte_offset) {
// bus_program = branch_byte_not_taken_bus_steps_;
// } else {
// bus_program = branch_word_not_taken_bus_steps_;
// }
// }
// } break;
//
// case Operation::DBcc: {
// // Decide what sort of DBcc this is.
// if(!evaluate_condition(decoded_instruction_.l >> 8)) {
// -- src.w;
// const auto target_program_counter = program_counter_.l + u_extend16(prefetch_queue_.w) - 2;
//
// if(src.w == 0xffff) {
// // This DBcc will be ignored as the counter has underflowed.
// // Schedule n np np np and continue. Assumed: the first np
// // is from where the branch would have been if taken?
// bus_program = dbcc_condition_false_no_branch_steps_;
// dbcc_false_address_ = target_program_counter;
// } else {
// // Take the branch. Change PC and schedule n np np.
// bus_program = dbcc_condition_false_branch_steps_;
// program_counter_.l = target_program_counter;
// }
// } else {
// // This DBcc will be ignored as the condition is true;
// // perform nn np np and continue.
// bus_program = dbcc_condition_true_steps_;
// }
// } break;
case Operation::Bccb:
case Operation::Bccw:
case Operation::Bccl: {
// Test the conditional, treating 'false' as true.
const bool should_branch = status.evaluate_condition(flow_controller.decode_conditional());
case Operation::Scc: {
dest.b =
status.evaluate_condition(src.l) ? 0xff : 0x00;
// Schedule something appropriate, by rewriting the program for this instruction temporarily.
if(should_branch) {
flow_controller.add_pc(src.l);
} else {
flow_controller.decline_branch();
}
} break;
case Operation::DBcc:
// Decide what sort of DBcc this is.
if(!status.evaluate_condition(flow_controller.decode_conditional())) {
-- src.w;
if(src.w == 0xffff) {
// This DBcc will be ignored as the counter has underflowed.
flow_controller.decline_branch();
} else {
// Take the branch.
flow_controller.add_pc(dest.l);
}
} else {
// This DBcc will be ignored as the condition is true.
flow_controller.decline_branch();
}
break;
case Operation::Scc:
dest.b = status.evaluate_condition(src.l) ? 0xff : 0x00;
break;
/*
CLRs: store 0 to the destination, set the zero flag, and clear
negative, overflow and carry.
@ -434,13 +398,9 @@ template <
} break;
// JMP: copies EA(0) to the program counter.
// case Operation::JMP:
// flow_controller.set_pc(effective_address_[0]);
// break;
// case Operation::RTS:
// program_counter_ = source_bus_data_;
// break;
case Operation::JMP:
flow_controller.set_pc(flow_controller.effective_address(0));
break;
/*
MOVE.b, MOVE.l and MOVE.w: move the least significant byte or word, or the entire long word,
@ -477,6 +437,10 @@ template <
dest.l = src.l;
break;
case Operation::LEA:
dest.l = flow_controller.effective_address(0);
break;
// case Operation::PEA:
// destination_bus_data_ = effective_address_[0];
// break;
@ -823,8 +787,7 @@ template <
/*
The no-op.
*/
case Operation::NOP:
break;
case Operation::NOP: break;
/*
LINK and UNLINK help with stack frames, allowing a certain
@ -1248,6 +1211,12 @@ template <
// uint8_t(current_status >> 8);
// }
// apply_status(source_bus_data_.l);
// break;
// case Operation::RTE:
// break;
//
// case Operation::RTR:
// break;
/*

View File

@ -894,6 +894,8 @@
4BB4BFB022A42F290069048D /* MacintoshIMG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */; };
4BB4BFB922A4372F0069048D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */; };
4BB4BFBA22A4372F0069048D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */; };
4BB5B99D281C814E00522DA9 /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB5B99B281C805300522DA9 /* Executor.cpp */; };
4BB5B99E281C814F00522DA9 /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB5B99B281C805300522DA9 /* Executor.cpp */; };
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; };
4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; };
4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EA11B587A5100552FC2 /* AppDelegate.swift */; };
@ -1939,6 +1941,8 @@
4BB5B996281B1E3F00522DA9 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = "<group>"; };
4BB5B997281B1F7B00522DA9 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = "<group>"; };
4BB5B99A281B244400522DA9 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = "<group>"; };
4BB5B99B281C805300522DA9 /* Executor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Executor.cpp; sourceTree = "<group>"; };
4BB5B99C281C805300522DA9 /* Executor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Executor.hpp; sourceTree = "<group>"; };
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
4BB697CA1D4B6D3E00248BDF /* TimedEventLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TimedEventLoop.hpp; sourceTree = "<group>"; };
4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommodoreGCR.cpp; path = Encodings/CommodoreGCR.cpp; sourceTree = "<group>"; };
@ -3165,8 +3169,10 @@
isa = PBXGroup;
children = (
4B79629F2819681F008130F9 /* Decoder.cpp */,
4BB5B99B281C805300522DA9 /* Executor.cpp */,
4B7962A4281C2EE3008130F9 /* Sequence.cpp */,
4B79629E2819681F008130F9 /* Decoder.hpp */,
4BB5B99C281C805300522DA9 /* Executor.hpp */,
4B79629C2819681F008130F9 /* Instruction.hpp */,
4B79629D2819681F008130F9 /* Model.hpp */,
4BB5B996281B1E3F00522DA9 /* Perform.hpp */,
@ -5458,6 +5464,7 @@
4B1B88C1202E3DB200B67DFF /* MultiConfigurable.cpp in Sources */,
4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */,
4B8318B322D3E540006DB630 /* Audio.cpp in Sources */,
4BB5B99E281C814F00522DA9 /* Executor.cpp in Sources */,
4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */,
4B89452B201967B4007DE474 /* File.cpp in Sources */,
4B6AAEAC230E40250078E864 /* SCSI.cpp in Sources */,
@ -5708,6 +5715,7 @@
4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */,
4B7BA03723CEB86000B98D9E /* BD500.cpp in Sources */,
4B38F3481F2EC11D00D9235D /* AmstradCPC.cpp in Sources */,
4BB5B99D281C814E00522DA9 /* Executor.cpp in Sources */,
4B8FE2221DA19FB20090D3CE /* MachineController.swift in Sources */,
4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */,
4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */,