diff --git a/Processors/6809/Perform.hpp b/Processors/6809/Perform.hpp index 522e19539..a217a8927 100644 --- a/Processors/6809/Perform.hpp +++ b/Processors/6809/Perform.hpp @@ -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() += registers.reg(); +} + +template +void add(Registers ®isters, const uint8_t operand) { + const uint8_t source = registers.reg(); + 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(result < operand); + + const uint8_t half = (source & 0xf) + (operand & 0xf) + (with_carry ? registers.cc.carry() : 0); + registers.cc.set(half & 0x10); + + registers.reg() = result; +} + +inline void addd(Registers ®isters, const uint16_t operand) { + const uint16_t source = registers.reg(); + const uint16_t result = source + operand; + + registers.cc.set_nz(result); + registers.cc.set(result < operand); + registers.cc.set_overflow(result, source, operand); +} + +// MARK: - Logical. + template -inline void ld(Registers ®isters, const uint8_t operand) { +void and_(Registers ®isters, const uint8_t operand) { + if constexpr (r == R8::CC) { + registers.reg() = registers.reg() & operand; + } else { + registers.cc.set_nz(registers.reg() &= operand); + registers.cc.set(false); + } +} + +// MARK: - Shifts and rolls. + +// MARK: - Data Transfer. + +template +void ld(Registers ®isters, const uint8_t operand) { registers.reg() = operand; registers.cc.set_nz(operand); registers.cc.set(false); } template -inline void ld(Registers ®isters, const uint16_t operand) { +void ld(Registers ®isters, const uint16_t operand) { registers.reg() = operand; - registers.cc.set_nz(operand >> 8); + registers.cc.set_nz(operand); registers.cc.set(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(registers, uint8_t(operand)); break; + case ADCB: add(registers, uint8_t(operand)); break; + case ADDA: add(registers, uint8_t(operand)); break; + case ADDB: add(registers, uint8_t(operand)); break; + case ADDD: addd(registers, operand); break; + case ANDA: and_(registers, uint8_t(operand)); break; + case ANDB: and_(registers, uint8_t(operand)); break; + case ANDCC: and_(registers, uint8_t(operand)); break; + case LDA: ld(registers, uint8_t(operand)); break; case LDB: ld(registers, uint8_t(operand)); break; diff --git a/Processors/6809/Registers.hpp b/Processors/6809/Registers.hpp index 90a8ba828..1e3c82cd4 100644 --- a/Processors/6809/Registers.hpp +++ b/Processors/6809/Registers.hpp @@ -83,8 +83,26 @@ struct ConditionCodeRegister { ); } - void set_nz(const uint8_t value) { - negative_ = zero_ = value; + template + requires (sizeof(ValueT) <= 2) + void set_nz(const ValueT value) { + if constexpr (std::is_same_v) { + negative_ = zero_ = value; + } else { + negative_ = uint8_t(value >> 8); + zero_ = uint8_t(value | (value >> 8)); + } + } + + template + 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) { + overflow_ = bits; + } else { + overflow_ = uint8_t(bits >> 8); + } } uint8_t carry() const { return carry_; }