mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-08 15:29:09 +00:00
Muddles along to generating functions.
Albeit right now without a body.
This commit is contained in:
parent
10caa1a1fb
commit
cd6ac51aa6
@ -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 *) {
|
template <Operation operation, AddressingMode addressing_mode> void Executor::perform(Executor *) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Executor::Action Executor::action_for(Instruction) {
|
Executor::Action Executor::action_for(Instruction instruction) {
|
||||||
Action action;
|
Action action {
|
||||||
action.perform = &perform<Operation::ADC, AddressingMode::Immediate>;
|
.perform = performer_lookup_.performer(instruction.operation, instruction.addressing_mode)
|
||||||
|
};
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#define Executor_h
|
#define Executor_h
|
||||||
|
|
||||||
#include "Instruction.hpp"
|
#include "Instruction.hpp"
|
||||||
|
#include "Parser.hpp"
|
||||||
|
|
||||||
namespace InstructionSet {
|
namespace InstructionSet {
|
||||||
namespace M50740 {
|
namespace M50740 {
|
||||||
@ -23,7 +24,8 @@ class Executor {
|
|||||||
so using the Executor to enquire of memory and the program counter is sufficient.
|
so using the Executor to enquire of memory and the program counter is sufficient.
|
||||||
*/
|
*/
|
||||||
struct Action {
|
struct Action {
|
||||||
void (* perform)(Executor *) = nullptr;
|
using Performer = void (*)(Executor *);
|
||||||
|
Performer perform = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
Action action_for(Instruction);
|
Action action_for(Instruction);
|
||||||
@ -38,6 +40,40 @@ class Executor {
|
|||||||
Performs @c operation in @c addressing_mode.
|
Performs @c operation in @c addressing_mode.
|
||||||
*/
|
*/
|
||||||
template <Operation operation, AddressingMode addressing_mode> static void perform(Executor *);
|
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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,9 @@ enum class AddressingMode {
|
|||||||
Bit4ZeroPageRelative, Bit5ZeroPageRelative, Bit6ZeroPageRelative, Bit7ZeroPageRelative,
|
Bit4ZeroPageRelative, Bit5ZeroPageRelative, Bit6ZeroPageRelative, Bit7ZeroPageRelative,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr auto MaxAddressingMode = int(AddressingMode::Bit7ZeroPageRelative);
|
||||||
|
static constexpr auto MinAddressingMode = int(AddressingMode::Implied);
|
||||||
|
|
||||||
constexpr int size(AddressingMode mode) {
|
constexpr int size(AddressingMode mode) {
|
||||||
// This is coupled to the AddressingMode list above; be careful!
|
// This is coupled to the AddressingMode list above; be careful!
|
||||||
constexpr int sizes[] = {
|
constexpr int sizes[] = {
|
||||||
@ -58,6 +61,7 @@ constexpr int size(AddressingMode mode) {
|
|||||||
2, 2, 2, 2,
|
2, 2, 2, 2,
|
||||||
2, 2, 2, 2,
|
2, 2, 2, 2,
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(sizes)/sizeof(*sizes) == int(MaxAddressingMode) + 1);
|
||||||
return sizes[int(mode)];
|
return sizes[int(mode)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +103,9 @@ enum class Operation: uint8_t {
|
|||||||
STA, STX, STY,
|
STA, STX, STY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr auto MaxOperation = int(Operation::STY);
|
||||||
|
static constexpr auto MinOperation = int(Operation::BBC);
|
||||||
|
|
||||||
constexpr AccessType access_type(Operation operation) {
|
constexpr AccessType access_type(Operation operation) {
|
||||||
if(operation < Operation::ADC) return AccessType::None;
|
if(operation < Operation::ADC) return AccessType::None;
|
||||||
if(operation < Operation::ASL) return AccessType::Read;
|
if(operation < Operation::ASL) return AccessType::Read;
|
||||||
|
Loading…
Reference in New Issue
Block a user