1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-18 17:06:15 +00:00

Deal with conditionality up front.

This commit is contained in:
Thomas Harte 2024-02-26 21:36:23 -05:00
parent 16e827bb2c
commit 4255283e33
2 changed files with 28 additions and 11 deletions

View File

@ -356,9 +356,21 @@ private:
/// Operation mapper; use the free function @c dispatch as defined below.
struct OperationMapper {
template <int i, typename SchedulerT> void dispatch(uint32_t instruction, SchedulerT &scheduler) {
static Condition condition(uint32_t instruction) {
return Condition(instruction >> 28);
}
template <int i, typename SchedulerT>
static void dispatch(uint32_t instruction, SchedulerT &scheduler) {
// Legacy: grab condition. This'll be eliminated.
// TODO: eliminate.
const auto condition = Condition(instruction >> 28);
// Put the 8-bit segment of instruction back into its proper place;
// this allows all the tests below to be written so as to coordinate
// properly with the data sheet, and since it's all compile-time work
// it doesn't cost anything.
constexpr auto partial = uint32_t(i << 20);
const auto condition = Condition(instruction >> 28);
// Cf. the ARM2 datasheet, p.45. Tests below match its ordering
// other than that 'undefined' is the fallthrough case. More specific
@ -367,10 +379,7 @@ struct OperationMapper {
// Data processing; cf. p.17.
if constexpr (((partial >> 26) & 0b11) == 0b00) {
scheduler.template perform<i>(
condition,
DataProcessing(instruction)
);
scheduler.template perform<i>(DataProcessing(instruction));
return;
}
@ -478,7 +487,7 @@ struct SampleScheduler {
// (1) Condition, indicating the condition code associated with this operation; and
// (2) An operation-specific encapsulation of the operation code for decoding of fields that didn't
// fit into the template parameters.
template <Flags> void perform(Condition, DataProcessing);
template <Flags> void perform(DataProcessing);
template <Operation, Flags> void perform(Condition, Multiply);
template <Operation, Flags> void perform(Condition, SingleDataTransfer);
template <Operation, Flags> void perform(Condition, BlockDataTransfer);
@ -497,6 +506,14 @@ struct SampleScheduler {
/// In lieue of C++20, see the sample definition of SampleScheduler above for the expected interface.
template <typename SchedulerT> void dispatch(uint32_t instruction, SchedulerT &scheduler) {
OperationMapper mapper;
// Test condition.
const auto condition = mapper.condition(instruction);
if(!scheduler.should_schedule(condition)) {
return;
}
// Dispatch body.
Reflection::dispatch(mapper, (instruction >> FlagsStartBit) & 0xff, instruction, scheduler);
}

View File

@ -56,11 +56,11 @@ void shift(ShiftType type, uint32_t &source, uint32_t amount, uint32_t *carry) {
struct Scheduler {
template <Flags f> void perform(Condition condition, DataProcessing fields) {
if(!status.test(condition)) {
return;
}
bool should_schedule(Condition condition) {
return status.test(condition);
}
template <Flags f> void perform(DataProcessing fields) {
// TODO: how does register 15 fit into all of below? As an operand or as a target?
constexpr DataProcessingFlags flags(f);