mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-18 17:06:15 +00:00
Implement branch.
This commit is contained in:
parent
487ade56ed
commit
645152a1fd
@ -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 1–16 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;
|
||||
}
|
||||
|
||||
|
@ -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) {}
|
||||
|
Loading…
Reference in New Issue
Block a user