mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 00:30:29 +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
|
MLA, /// Rd = Rm * Rs + Rn
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Operation {
|
enum class BranchOperation {
|
||||||
B, /// Add offset to PC; programmer allows for PC being two words ahead.
|
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.
|
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.
|
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.
|
STR, /// Write a single byte or word to [base + offset], possibly mutating the base.
|
||||||
LDM, /// Read 1–16 words from [base], possibly mutating it.
|
LDM, /// Read 1–16 words from [base], possibly mutating it.
|
||||||
@ -137,6 +139,18 @@ protected:
|
|||||||
//
|
//
|
||||||
// Branch (i.e. B and BL).
|
// 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 {
|
struct Branch {
|
||||||
constexpr Branch(uint32_t opcode) noexcept : opcode_(opcode) {}
|
constexpr Branch(uint32_t opcode) noexcept : opcode_(opcode) {}
|
||||||
|
|
||||||
@ -423,11 +437,7 @@ struct OperationMapper {
|
|||||||
|
|
||||||
// Branch and branch with link (B, BL); cf. p.15.
|
// Branch and branch with link (B, BL); cf. p.15.
|
||||||
if constexpr (((partial >> 25) & 0b111) == 0b101) {
|
if constexpr (((partial >> 25) & 0b111) == 0b101) {
|
||||||
constexpr bool is_bl = partial & (1 << 24);
|
scheduler.template perform<i>(Branch(instruction));
|
||||||
scheduler.template perform<is_bl ? Operation::BL : Operation::B>(
|
|
||||||
condition,
|
|
||||||
Branch(instruction)
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ struct Scheduler {
|
|||||||
const bool shift_by_register = !flags.operand2_is_immediate() && fields.shift_count_is_register();
|
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.
|
// 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()];
|
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
|
// "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, SingleDataTransfer) {}
|
||||||
template <Operation, Flags> void perform(Condition, BlockDataTransfer) {}
|
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 <Operation, Flags> void perform(Condition, CoprocessorRegisterTransfer) {}
|
||||||
template <Flags> void perform(Condition, CoprocessorDataOperation) {}
|
template <Flags> void perform(Condition, CoprocessorDataOperation) {}
|
||||||
template<Operation, Flags> void perform(Condition, CoprocessorDataTransfer) {}
|
template<Operation, Flags> void perform(Condition, CoprocessorDataTransfer) {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user