From cd6ac51aa68a02d538ddcccf600ff0fef20b08aa Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 16 Jan 2021 21:45:44 -0500 Subject: [PATCH] Muddles along to generating functions. Albeit right now without a body. --- InstructionSets/M50740/Executor.cpp | 7 +++-- InstructionSets/M50740/Executor.hpp | 38 +++++++++++++++++++++++++- InstructionSets/M50740/Instruction.hpp | 7 +++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/InstructionSets/M50740/Executor.cpp b/InstructionSets/M50740/Executor.cpp index 39e0a38b1..71a39913a 100644 --- a/InstructionSets/M50740/Executor.cpp +++ b/InstructionSets/M50740/Executor.cpp @@ -16,8 +16,9 @@ template void Executor::perform(uint8_t *operand [[maybe_u template void Executor::perform(Executor *) { } -Executor::Action Executor::action_for(Instruction) { - Action action; - action.perform = &perform; +Executor::Action Executor::action_for(Instruction instruction) { + Action action { + .perform = performer_lookup_.performer(instruction.operation, instruction.addressing_mode) + }; return action; } diff --git a/InstructionSets/M50740/Executor.hpp b/InstructionSets/M50740/Executor.hpp index c17a5a4cd..b291f1e21 100644 --- a/InstructionSets/M50740/Executor.hpp +++ b/InstructionSets/M50740/Executor.hpp @@ -10,6 +10,7 @@ #define Executor_h #include "Instruction.hpp" +#include "Parser.hpp" namespace InstructionSet { namespace M50740 { @@ -23,7 +24,8 @@ class Executor { so using the Executor to enquire of memory and the program counter is sufficient. */ struct Action { - void (* perform)(Executor *) = nullptr; + using Performer = void (*)(Executor *); + Performer perform = nullptr; }; Action action_for(Instruction); @@ -38,6 +40,40 @@ class Executor { Performs @c operation in @c addressing_mode. */ template static void perform(Executor *); + + /*! + Provides dynamic lookup of @c perform(Executor*). + */ + class PerformerLookup { + public: + PerformerLookup() { + fill(performers); + } + + Action::Performer performer(Operation operation, AddressingMode addressing_mode) { + return performers[int(addressing_mode) * (MaxOperation - MinOperation) + int(operation) - MinOperation]; + } + + private: + Action::Performer performers[(MaxAddressingMode - MinAddressingMode) * (MaxOperation - MinOperation)]; + + template void fill_operation(Action::Performer *target) { + *target = &Executor::perform; + if constexpr (addressing_mode+1 < MaxAddressingMode) { + fill(target + 1); + } + } + + template void fill(Action::Performer *target) { + fill_operation(target); + target += MaxOperation - MinOperation; + if constexpr (operation+1 < MaxOperation) { + fill(target); + } + } + }; + + inline static PerformerLookup performer_lookup_; }; } diff --git a/InstructionSets/M50740/Instruction.hpp b/InstructionSets/M50740/Instruction.hpp index f823c4ee3..93ab2ebe8 100644 --- a/InstructionSets/M50740/Instruction.hpp +++ b/InstructionSets/M50740/Instruction.hpp @@ -38,6 +38,9 @@ enum class AddressingMode { Bit4ZeroPageRelative, Bit5ZeroPageRelative, Bit6ZeroPageRelative, Bit7ZeroPageRelative, }; +static constexpr auto MaxAddressingMode = int(AddressingMode::Bit7ZeroPageRelative); +static constexpr auto MinAddressingMode = int(AddressingMode::Implied); + constexpr int size(AddressingMode mode) { // This is coupled to the AddressingMode list above; be careful! constexpr int sizes[] = { @@ -58,6 +61,7 @@ constexpr int size(AddressingMode mode) { 2, 2, 2, 2, 2, 2, 2, 2, }; + static_assert(sizeof(sizes)/sizeof(*sizes) == int(MaxAddressingMode) + 1); return sizes[int(mode)]; } @@ -99,6 +103,9 @@ enum class Operation: uint8_t { STA, STX, STY, }; +static constexpr auto MaxOperation = int(Operation::STY); +static constexpr auto MinOperation = int(Operation::BBC); + constexpr AccessType access_type(Operation operation) { if(operation < Operation::ADC) return AccessType::None; if(operation < Operation::ASL) return AccessType::Read;