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

Implement branch.

This commit is contained in:
Thomas Harte 2024-02-28 11:33:28 -05:00
parent 487ade56ed
commit 645152a1fd
2 changed files with 26 additions and 10 deletions

View File

@ -68,10 +68,12 @@ enum class MultiplyOperation {
MLA, /// Rd = Rm * Rs + Rn
};
enum class Operation {
enum class BranchOperation {
B, /// Add offset to PC; programmer allows for PC being two words ahead.
BL, /// Copy PC and PSR to R14, then branch. Copied PC points to next instruction.
};
enum class Operation {
LDR, /// Read single byte or word from [base + offset], possibly mutating the base.
STR, /// Write a single byte or word to [base + offset], possibly mutating the base.
LDM, /// Read 116 words from [base], possibly mutating it.
@ -137,6 +139,18 @@ protected:
//
// Branch (i.e. B and BL).
//
struct BranchFlags {
constexpr BranchFlags(uint8_t flags) noexcept : flags_(flags) {}
/// @returns The operation to apply.
constexpr BranchOperation operation() const {
return flag_bit<24>(flags_) ? BranchOperation::BL : BranchOperation::B;
}
private:
uint8_t flags_;
};
struct Branch {
constexpr Branch(uint32_t opcode) noexcept : opcode_(opcode) {}
@ -423,11 +437,7 @@ struct OperationMapper {
// Branch and branch with link (B, BL); cf. p.15.
if constexpr (((partial >> 25) & 0b111) == 0b101) {
constexpr bool is_bl = partial & (1 << 24);
scheduler.template perform<is_bl ? Operation::BL : Operation::B>(
condition,
Branch(instruction)
);
scheduler.template perform<i>(Branch(instruction));
return;
}

View File

@ -114,7 +114,7 @@ struct Scheduler {
const bool shift_by_register = !flags.operand2_is_immediate() && fields.shift_count_is_register();
// Write a raw result into the PC proxy if the target is R15; it'll be stored properly later.
uint32_t pc_proxy;
uint32_t pc_proxy = 0;
auto &destination = fields.destination() == 15 ? pc_proxy : registers_.active[fields.destination()];
// "When R15 appears in either of the Rn or Rs positions it will give the value
@ -301,12 +301,18 @@ struct Scheduler {
}
}
template <Flags f> void perform(Branch branch) {
constexpr BranchFlags flags(f);
if constexpr (flags.operation() == BranchOperation::BL) {
registers_.active[14] = registers_.pc(4);
}
registers_.set_pc(registers_.pc(8) + branch.offset());
}
template <Operation, Flags> void perform(Condition, SingleDataTransfer) {}
template <Operation, Flags> void perform(Condition, BlockDataTransfer) {}
template <Operation op> void perform(Condition condition, Branch branch) {
printf("Branch %sif %d; add %08x\n", op == Operation::BL ? "with link " : "", int(condition), branch.offset());
}
template <Operation, Flags> void perform(Condition, CoprocessorRegisterTransfer) {}
template <Flags> void perform(Condition, CoprocessorDataOperation) {}
template<Operation, Flags> void perform(Condition, CoprocessorDataTransfer) {}