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:
parent
53a3e88d16
commit
01ddc24c02
@ -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())) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user