Start to flesh out operations.
This commit is contained in:
1 parent
21d2ab9179
commit
a9358d3039
2 files changed
+82
-8
No files matched your search
@@ -53,24 +53,68 @@ inline void set(Registers ®isters, const int index, const uint16_t value) {
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Arithmetic.
|
||||
|
||||
inline void abx(Registers ®isters) {
|
||||
registers.reg<R16::X>() += registers.reg<R8::B>();
|
||||
}
|
||||
|
||||
template <R8 r, bool with_carry>
|
||||
void add(Registers ®isters, const uint8_t operand) {
|
||||
const uint8_t source = registers.reg<r>();
|
||||
const uint8_t result = source + operand + (with_carry ? registers.cc.carry() : 0);
|
||||
|
||||
registers.cc.set_nz(result);
|
||||
registers.cc.set_overflow(result, source, operand);
|
||||
registers.cc.set<ConditionCode::Carry>(result < operand);
|
||||
|
||||
const uint8_t half = (source & 0xf) + (operand & 0xf) + (with_carry ? registers.cc.carry() : 0);
|
||||
registers.cc.set<ConditionCode::HalfCarry>(half & 0x10);
|
||||
|
||||
registers.reg<r>() = result;
|
||||
}
|
||||
|
||||
inline void addd(Registers ®isters, const uint16_t operand) {
|
||||
const uint16_t source = registers.reg<R16::D>();
|
||||
const uint16_t result = source + operand;
|
||||
|
||||
registers.cc.set_nz(result);
|
||||
registers.cc.set<ConditionCode::Carry>(result < operand);
|
||||
registers.cc.set_overflow(result, source, operand);
|
||||
}
|
||||
|
||||
// MARK: - Logical.
|
||||
|
||||
template <R8 r>
|
||||
inline void ld(Registers ®isters, const uint8_t operand) {
|
||||
void and_(Registers ®isters, const uint8_t operand) {
|
||||
if constexpr (r == R8::CC) {
|
||||
registers.reg<R8::CC>() = registers.reg<R8::CC>() & operand;
|
||||
} else {
|
||||
registers.cc.set_nz(registers.reg<r>() &= operand);
|
||||
registers.cc.set<ConditionCode::Overflow>(false);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Shifts and rolls.
|
||||
|
||||
// MARK: - Data Transfer.
|
||||
|
||||
template <R8 r>
|
||||
void ld(Registers ®isters, const uint8_t operand) {
|
||||
registers.reg<r>() = operand;
|
||||
registers.cc.set_nz(operand);
|
||||
registers.cc.set<ConditionCode::Overflow>(false);
|
||||
}
|
||||
|
||||
template <R16 r>
|
||||
inline void ld(Registers ®isters, const uint16_t operand) {
|
||||
void ld(Registers ®isters, const uint16_t operand) {
|
||||
registers.reg<r>() = operand;
|
||||
registers.cc.set_nz(operand >> 8);
|
||||
registers.cc.set_nz(operand);
|
||||
registers.cc.set<ConditionCode::Overflow>(false);
|
||||
}
|
||||
|
||||
|
||||
inline void tfr(Registers ®isters, const uint8_t operand) {
|
||||
const auto source = operand >> 4;
|
||||
const auto destination = operand & 0xf;
|
||||
@@ -91,12 +135,24 @@ inline void exg(Registers ®isters, const uint8_t operand) {
|
||||
Implementation::set(registers, top, source_values[1]);
|
||||
}
|
||||
|
||||
inline void perform(const InstructionSet::M6809::Operation operation, Registers ®isters, const uint16_t operand) {
|
||||
// MARK: - Dispatch.
|
||||
|
||||
inline void perform(const InstructionSet::M6809::Operation operation, Registers ®isters, uint16_t &operand) {
|
||||
switch(operation) {
|
||||
using enum InstructionSet::M6809::Operation;
|
||||
|
||||
case None: break;
|
||||
|
||||
case ABX: abx(registers); break;
|
||||
case ADCA: add<R8::A, true>(registers, uint8_t(operand)); break;
|
||||
case ADCB: add<R8::B, true>(registers, uint8_t(operand)); break;
|
||||
case ADDA: add<R8::A, false>(registers, uint8_t(operand)); break;
|
||||
case ADDB: add<R8::B, false>(registers, uint8_t(operand)); break;
|
||||
case ADDD: addd(registers, operand); break;
|
||||
case ANDA: and_<R8::A>(registers, uint8_t(operand)); break;
|
||||
case ANDB: and_<R8::B>(registers, uint8_t(operand)); break;
|
||||
case ANDCC: and_<R8::CC>(registers, uint8_t(operand)); break;
|
||||
|
||||
case LDA: ld<R8::A>(registers, uint8_t(operand)); break;
|
||||
case LDB: ld<R8::B>(registers, uint8_t(operand)); break;
|
||||
|
||||
|
||||
@@ -83,8 +83,26 @@ struct ConditionCodeRegister {
|
||||
);
|
||||
}
|
||||
|
||||
void set_nz(const uint8_t value) {
|
||||
negative_ = zero_ = value;
|
||||
template <std::unsigned_integral ValueT>
|
||||
requires (sizeof(ValueT) <= 2)
|
||||
void set_nz(const ValueT value) {
|
||||
if constexpr (std::is_same_v<ValueT, uint8_t>) {
|
||||
negative_ = zero_ = value;
|
||||
} else {
|
||||
negative_ = uint8_t(value >> 8);
|
||||
zero_ = uint8_t(value | (value >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
template <std::unsigned_integral ValueT>
|
||||
requires (sizeof(ValueT) <= 2)
|
||||
void set_overflow(const ValueT result, const ValueT lhs, const ValueT rhs) {
|
||||
const ValueT bits = (result^lhs) & (result^rhs);
|
||||
if constexpr (std::is_same_v<ValueT, uint8_t>) {
|
||||
overflow_ = bits;
|
||||
} else {
|
||||
overflow_ = uint8_t(bits >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t carry() const { return carry_; }
|
||||
|
||||
Reference in new issue
Block a user