mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-07 05:30:30 +00:00
Add basic multiply.
This commit is contained in:
parent
60d1b36e9a
commit
487ade56ed
@ -63,9 +63,12 @@ constexpr bool is_comparison(DataProcessingOperation operation) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class Operation {
|
||||
enum class MultiplyOperation {
|
||||
MUL, /// Rd = Rm * Rs
|
||||
MLA, /// Rd = Rm * Rs + Rn
|
||||
};
|
||||
|
||||
enum class Operation {
|
||||
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.
|
||||
|
||||
@ -192,7 +195,12 @@ struct MultiplyFlags {
|
||||
constexpr MultiplyFlags(uint8_t flags) noexcept : flags_(flags) {}
|
||||
|
||||
/// @c true if the status register should be updated; @c false otherwise.
|
||||
constexpr bool set_condition_codes() { return flag_bit<20>(flags_); }
|
||||
constexpr bool set_condition_codes() const { return flag_bit<20>(flags_); }
|
||||
|
||||
/// @returns The operation to apply.
|
||||
constexpr MultiplyOperation operation() const {
|
||||
return flag_bit<21>(flags_) ? MultiplyOperation::MLA : MultiplyOperation::MUL;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t flags_;
|
||||
@ -388,11 +396,7 @@ struct OperationMapper {
|
||||
// This implementation provides only eight bits baked into the template parameters so
|
||||
// an additional dynamic test is required to check whether this is really, really MUL or MLA.
|
||||
if(((instruction >> 4) & 0b1111) == 0b1001) {
|
||||
constexpr bool is_mla = partial & (1 << 21);
|
||||
scheduler.template perform<is_mla ? Operation::MLA : Operation::MUL, i>(
|
||||
condition,
|
||||
Multiply(instruction)
|
||||
);
|
||||
scheduler.template perform<i>(Multiply(instruction));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +274,33 @@ struct Scheduler {
|
||||
}
|
||||
}
|
||||
|
||||
template <Operation, Flags> void perform(Condition, Multiply) {}
|
||||
template <Flags f> void perform(Multiply fields) {
|
||||
constexpr MultiplyFlags flags(f);
|
||||
|
||||
// R15 rules:
|
||||
//
|
||||
// * Rs: no PSR, 8 bytes ahead;
|
||||
// * Rn: with PSR, 8 bytes ahead;
|
||||
// * Rm: with PSR, 12 bytes ahead.
|
||||
|
||||
const uint32_t multiplicand = fields.multiplicand() == 15 ? registers_.pc(8) : registers_.active[fields.multiplicand()];
|
||||
const uint32_t multiplier = fields.multiplier() == 15 ? registers_.pc_status(8) : registers_.active[fields.multiplier()];
|
||||
const uint32_t accumulator =
|
||||
flags.operation() == MultiplyOperation::MUL ? 0 :
|
||||
(fields.multiplicand() == 15 ? registers_.pc_status(12) : registers_.active[fields.accumulator()]);
|
||||
|
||||
const uint32_t result = multiplicand * multiplier + accumulator;
|
||||
|
||||
if constexpr (flags.set_condition_codes()) {
|
||||
registers_.set_nz(result);
|
||||
// V is unaffected; C is undefined.
|
||||
}
|
||||
|
||||
if(fields.destination() != 15) {
|
||||
registers_.active[fields.destination()] = result;
|
||||
}
|
||||
}
|
||||
|
||||
template <Operation, Flags> void perform(Condition, SingleDataTransfer) {}
|
||||
template <Operation, Flags> void perform(Condition, BlockDataTransfer) {}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user