1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-10 23:31:24 +00:00

Require overt acknowledgement of meaning.

This commit is contained in:
Thomas Harte 2025-01-28 17:42:26 -05:00
parent 53a3e88d16
commit 01ddc24c02
5 changed files with 38 additions and 32 deletions

View File

@ -152,8 +152,8 @@ struct Executor {
if constexpr (flags.set_condition_codes()) {
// "For a subtraction, including the comparison instruction CMP, C is set to 0 if
// the subtraction produced a borrow (that is, an unsigned underflow), and to 1 otherwise."
registers_.set_c(!Numeric::carried_out<false, 31>(lhs, rhs, conditions));
registers_.set_v(Numeric::overflow<false>(lhs, rhs, conditions));
registers_.set_c(!Numeric::carried_out<Numeric::Operation::Subtract, 31>(lhs, rhs, conditions));
registers_.set_v(Numeric::overflow<Numeric::Operation::Subtract>(lhs, rhs, conditions));
}
if constexpr (!is_comparison(flags.operation())) {
@ -185,8 +185,8 @@ struct Executor {
}
if constexpr (flags.set_condition_codes()) {
registers_.set_c(Numeric::carried_out<true, 31>(operand1, operand2, conditions));
registers_.set_v(Numeric::overflow<true>(operand1, operand2, conditions));
registers_.set_c(Numeric::carried_out<Numeric::Operation::Add, 31>(operand1, operand2, conditions));
registers_.set_v(Numeric::overflow<Numeric::Operation::Add>(operand1, operand2, conditions));
}
if constexpr (!is_comparison(flags.operation())) {

View File

@ -28,11 +28,12 @@ namespace Primitive {
/// Performs an add or subtract (as per @c is_add) between @c source and @c destination,
/// updating @c status. @c is_extend indicates whether this is an extend operation (e.g. ADDX)
/// or a plain one (e.g. ADD).
template <bool is_add, bool is_extend, typename IntT>
template <Numeric::Operation operation, bool is_extend, typename IntT>
static void add_sub(const IntT source, IntT &destination, Status &status) {
static_assert(!std::numeric_limits<IntT>::is_signed);
IntT result = is_add ?
constexpr bool is_add = operation == Numeric::Operation::Add;
IntT result = is_add ?
destination + source :
destination - source;
status.carry_flag = is_add ? result < destination : result > destination;
@ -59,7 +60,7 @@ static void add_sub(const IntT source, IntT &destination, Status &status) {
status.zero_result = Status::FlagT(result);
}
status.set_negative(result);
status.overflow_flag = Numeric::overflow<is_add>(destination, source, result);
status.overflow_flag = Numeric::overflow<operation>(destination, source, result);
destination = result;
}
@ -121,7 +122,7 @@ void compare(const IntT source, const IntT destination, Status &status) {
const IntT result = destination - source;
status.carry_flag = result > destination;
status.set_neg_zero(result);
status.overflow_flag = Numeric::overflow<false>(destination, source, result);
status.overflow_flag = Numeric::overflow<Numeric::Operation::Subtract>(destination, source, result);
}
/// @returns the name of the bit to be used as a mask for BCLR, BCHG, BSET or BTST for
@ -279,7 +280,7 @@ template <bool is_extend, typename IntT> void negative(IntT &source, Status &sta
}
status.extend_flag = status.carry_flag = result; // i.e. any value other than 0 will result in carry.
status.set_negative(result);
status.overflow_flag = Numeric::overflow<false>(IntT(0), source, result);
status.overflow_flag = Numeric::overflow<Numeric::Operation::Subtract>(IntT(0), source, result);
source = result;
}
@ -551,20 +552,20 @@ template <
// ADD and ADDA add two quantities, the latter sign extending and without setting any flags;
// ADDQ and SUBQ act as ADD and SUB, but taking the second argument from the instruction code.
case Operation::ADDb: Primitive::add_sub<true, false>(src.b, dest.b, status); break;
case Operation::SUBb: Primitive::add_sub<false, false>(src.b, dest.b, status); break;
case Operation::ADDXb: Primitive::add_sub<true, true>(src.b, dest.b, status); break;
case Operation::SUBXb: Primitive::add_sub<false, true>(src.b, dest.b, status); break;
case Operation::ADDb: Primitive::add_sub<Numeric::Operation::Add, false>(src.b, dest.b, status); break;
case Operation::SUBb: Primitive::add_sub<Numeric::Operation::Subtract, false>(src.b, dest.b, status); break;
case Operation::ADDXb: Primitive::add_sub<Numeric::Operation::Add, true>(src.b, dest.b, status); break;
case Operation::SUBXb: Primitive::add_sub<Numeric::Operation::Subtract, true>(src.b, dest.b, status); break;
case Operation::ADDw: Primitive::add_sub<true, false>(src.w, dest.w, status); break;
case Operation::SUBw: Primitive::add_sub<false, false>(src.w, dest.w, status); break;
case Operation::ADDXw: Primitive::add_sub<true, true>(src.w, dest.w, status); break;
case Operation::SUBXw: Primitive::add_sub<false, true>(src.w, dest.w, status); break;
case Operation::ADDw: Primitive::add_sub<Numeric::Operation::Add, false>(src.w, dest.w, status); break;
case Operation::SUBw: Primitive::add_sub<Numeric::Operation::Subtract, false>(src.w, dest.w, status); break;
case Operation::ADDXw: Primitive::add_sub<Numeric::Operation::Add, true>(src.w, dest.w, status); break;
case Operation::SUBXw: Primitive::add_sub<Numeric::Operation::Subtract, true>(src.w, dest.w, status); break;
case Operation::ADDl: Primitive::add_sub<true, false>(src.l, dest.l, status); break;
case Operation::SUBl: Primitive::add_sub<false, false>(src.l, dest.l, status); break;
case Operation::ADDXl: Primitive::add_sub<true, true>(src.l, dest.l, status); break;
case Operation::SUBXl: Primitive::add_sub<false, true>(src.l, dest.l, status); break;
case Operation::ADDl: Primitive::add_sub<Numeric::Operation::Add, false>(src.l, dest.l, status); break;
case Operation::SUBl: Primitive::add_sub<Numeric::Operation::Subtract, false>(src.l, dest.l, status); break;
case Operation::ADDXl: Primitive::add_sub<Numeric::Operation::Add, true>(src.l, dest.l, status); break;
case Operation::SUBXl: Primitive::add_sub<Numeric::Operation::Subtract, true>(src.l, dest.l, status); break;
case Operation::ADDAw: dest.l += u_extend16(src.w); break;
case Operation::ADDAl: dest.l += src.l; break;

View File

@ -31,11 +31,11 @@ void add(
const IntT result = destination + source + (with_carry ? context.flags.template carry_bit<IntT>() : 0);
context.flags.template set_from<Flag::Carry>(
Numeric::carried_out<true, Numeric::bit_size<IntT>() - 1>(destination, source, result));
Numeric::carried_out<Numeric::Operation::Add, Numeric::bit_size<IntT>() - 1>(destination, source, result));
context.flags.template set_from<Flag::AuxiliaryCarry>(
Numeric::carried_in<4>(destination, source, result));
context.flags.template set_from<Flag::Overflow>(
Numeric::overflow<true, IntT>(destination, source, result));
Numeric::overflow<Numeric::Operation::Add, IntT>(destination, source, result));
context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);
@ -57,11 +57,11 @@ void sub(
const IntT result = destination - source - (with_borrow ? context.flags.template carry_bit<IntT>() : 0);
context.flags.template set_from<Flag::Carry>(
Numeric::carried_out<false, Numeric::bit_size<IntT>() - 1>(destination, source, result));
Numeric::carried_out<Numeric::Operation::Subtract, Numeric::bit_size<IntT>() - 1>(destination, source, result));
context.flags.template set_from<Flag::AuxiliaryCarry>(
Numeric::carried_in<4>(destination, source, result));
context.flags.template set_from<Flag::Overflow>(
Numeric::overflow<false, IntT>(destination, source, result));
Numeric::overflow<Numeric::Operation::Subtract, IntT>(destination, source, result));
context.flags.template set_from<IntT, Flag::Zero, Flag::Sign, Flag::ParityOdd>(result);

View File

@ -12,11 +12,16 @@
namespace Numeric {
enum class Operation {
Add,
Subtract,
};
/// @returns @c true if from @c bit there was:
/// • carry after calculating @c lhs + @c rhs if @c is_add is true; or
/// • borrow after calculating @c lhs - @c rhs if @c is_add is false;
/// producing @c result.
template <bool is_add, int bit, typename IntT> bool carried_out(IntT lhs, IntT rhs, IntT result) {
template <Operation operation, int bit, typename IntT> bool carried_out(IntT lhs, IntT rhs, IntT result) {
// Additive:
//
// 0 and 0 => didn't.
@ -28,11 +33,11 @@ template <bool is_add, int bit, typename IntT> bool carried_out(IntT lhs, IntT r
// 1 and 0 => didn't
// 1 and 1 or 0 and 0 => did if 1.
// 0 and 1 => did.
if constexpr (!is_add) {
if constexpr (operation == Operation::Subtract) {
rhs = ~rhs;
}
const bool carry = IntT(1 << bit) & (lhs | rhs) & ((lhs & rhs) | ~result);
if constexpr (!is_add) {
if constexpr (operation == Operation::Subtract) {
return !carry;
} else {
return carry;
@ -65,12 +70,12 @@ template <typename IntT> constexpr int bit_size() {
/// • @c lhs + @c rhs (if @c is_add is true); or
/// • @c lhs - @c rhs (if @c is_add is false)
/// and the result was @c result. All other bits will be clear.
template <bool is_add, typename IntT>
template <Operation operation, typename IntT>
IntT overflow(IntT lhs, IntT rhs, IntT result) {
const IntT output_changed = result ^ lhs;
const IntT input_differed = lhs ^ rhs;
if constexpr (is_add) {
if constexpr (operation == Operation::Add) {
return top_bit<IntT>() & output_changed & ~input_differed;
} else {
return top_bit<IntT>() & output_changed & input_differed;

View File

@ -368,7 +368,7 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
// All flags are set based only on the decimal result.
flags_.zero_result = result;
flags_.carry = Numeric::carried_out<true, 7>(a_, operand_, result);
flags_.carry = Numeric::carried_out<Numeric::Operation::Add, 7>(a_, operand_, result);
flags_.negative_result = result;
flags_.overflow = (( (result ^ a_) & (result ^ operand_) ) & 0x80) >> 1;
@ -418,7 +418,7 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
if(flags_.decimal && has_decimal_mode(personality)) {
uint8_t result = a_ + operand_ + flags_.carry;
flags_.zero_result = result;
flags_.carry = Numeric::carried_out<true, 7>(a_, operand_, result);
flags_.carry = Numeric::carried_out<Numeric::Operation::Add, 7>(a_, operand_, result);
// General ADC logic:
//