1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Muddles along to generating functions.

Albeit right now without a body.
This commit is contained in:
Thomas Harte 2021-01-16 21:45:44 -05:00
parent 10caa1a1fb
commit cd6ac51aa6
3 changed files with 48 additions and 4 deletions

View File

@ -16,8 +16,9 @@ template <Operation operation> void Executor::perform(uint8_t *operand [[maybe_u
template <Operation operation, AddressingMode addressing_mode> void Executor::perform(Executor *) {
}
Executor::Action Executor::action_for(Instruction) {
Action action;
action.perform = &perform<Operation::ADC, AddressingMode::Immediate>;
Executor::Action Executor::action_for(Instruction instruction) {
Action action {
.perform = performer_lookup_.performer(instruction.operation, instruction.addressing_mode)
};
return action;
}

View File

@ -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 <Operation operation, AddressingMode addressing_mode> static void perform(Executor *);
/*!
Provides dynamic lookup of @c perform(Executor*).
*/
class PerformerLookup {
public:
PerformerLookup() {
fill<int(MinOperation), int(MinAddressingMode)>(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<int operation, int addressing_mode> void fill_operation(Action::Performer *target) {
*target = &Executor::perform<Operation(operation), AddressingMode(addressing_mode)>;
if constexpr (addressing_mode+1 < MaxAddressingMode) {
fill<operation, addressing_mode+1>(target + 1);
}
}
template<int operation, int addressing_mode> void fill(Action::Performer *target) {
fill_operation<operation, addressing_mode>(target);
target += MaxOperation - MinOperation;
if constexpr (operation+1 < MaxOperation) {
fill<operation+1, addressing_mode>(target);
}
}
};
inline static PerformerLookup performer_lookup_;
};
}

View File

@ -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;