1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +00:00

Pull add/sub distinction into templates.

This commit is contained in:
Thomas Harte 2023-10-09 16:40:50 -04:00
parent f74ca8aee1
commit 1cb26cb141
3 changed files with 38 additions and 17 deletions

View File

@ -408,8 +408,8 @@ void adc(IntT &destination, IntT source, Status &status) {
*/
const IntT result = destination + source + status.carry_bit<IntT>();
status.carry = Numeric::carried_out<bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result);
status.carry = Numeric::carried_out<true, bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<true, 4>(destination, source, result);
status.sign = result & top_bit<IntT>();
status.zero = status.parity = result;
status.overflow = overflow<true, IntT>(destination, source, result);
@ -427,8 +427,8 @@ void add(IntT &destination, IntT source, Status &status) {
*/
const IntT result = destination + source;
status.carry = Numeric::carried_out<bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<4>(destination, source, result);
status.carry = Numeric::carried_out<true, bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<true, 4>(destination, source, result);
status.sign = result & top_bit<IntT>();
status.zero = status.parity = result;
status.overflow = overflow<true, IntT>(destination, source, result);
@ -446,8 +446,8 @@ void sbb(IntT &destination, IntT source, Status &status) {
*/
const IntT result = destination - source - status.carry_bit<IntT>();
status.carry = !Numeric::carried_out<bit_size<IntT>() - 1>(destination, IntT(~source), result);
status.auxiliary_carry = !Numeric::carried_in<4>(destination, IntT(~source), result);
status.carry = Numeric::carried_out<false, bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<false, 4>(destination, source, result);
status.sign = result & top_bit<IntT>();
status.zero = status.parity = result;
status.overflow = overflow<false, IntT>(destination, source, result);
@ -465,8 +465,8 @@ void sub(IntT &destination, IntT source, Status &status) {
*/
const IntT result = destination - source;
status.carry = !Numeric::carried_out<bit_size<IntT>() - 1>(destination, IntT(~source), result);
status.auxiliary_carry = !Numeric::carried_in<4>(destination, IntT(~source), result);
status.carry = Numeric::carried_out<false, bit_size<IntT>() - 1>(destination, source, result);
status.auxiliary_carry = Numeric::carried_in<false, 4>(destination, source, result);
status.sign = result & top_bit<IntT>();
status.zero = status.parity = result;
status.overflow = overflow<false, IntT>(destination, source, result);

View File

@ -11,19 +11,40 @@
namespace Numeric {
/// @returns @c true if there was carry out of @c bit when @c source1 and @c source2 were added, producing @c result.
template <int bit, typename IntT> bool carried_out(IntT source1, IntT source2, IntT result) {
/// @returns @c true if there, 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) {
// 0 and 0 => didn't.
// 0 and 1 or 1 and 0 => did if 0.
// 1 and 1 => did.
return IntT(1 << bit) & (source1 | source2) & ((source1 & source2) | ~result);
if constexpr (!is_add) {
rhs = ~rhs;
}
const bool carry = IntT(1 << bit) & (lhs | rhs) & ((lhs & rhs) | ~result);
if constexpr (!is_add) {
return !carry;
} else {
return carry;
}
}
// ~carried_out<>(d, ~s, r)
/// @returns @c true if there was carry into @c bit when @c source1 and @c source2 were added, producing @c result.
template <int bit, typename IntT> bool carried_in(IntT source1, IntT source2, IntT result) {
template <bool is_add, int bit, typename IntT> bool carried_in(IntT lhs, IntT rhs, IntT result) {
// 0 and 0 or 1 and 1 => did if 1
// 0 and 1 or 1 and 0 => did if 0
return IntT(1 << bit) & (source1 ^ source2 ^ result);
if constexpr (!is_add) {
rhs = ~rhs;
}
const bool carry = IntT(1 << bit) & (lhs ^ rhs ^ result);
if constexpr (!is_add) {
return !carry;
} else {
return carry;
}
}
}

View File

@ -327,7 +327,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// All flags are set based only on the decimal result.
flags_.zero_result = result;
flags_.carry = Numeric::carried_out<7>(a_, operand_, result);
flags_.carry = Numeric::carried_out<true, 7>(a_, operand_, result);
flags_.negative_result = result;
flags_.overflow = (( (result ^ a_) & (result ^ operand_) ) & 0x80) >> 1;
@ -343,7 +343,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// on a 6502 additional borrow isn't propagated but on a 65C02 it is.
// This difference affects invalid BCD numbers only — valid numbers will
// never be less than -9 so adding 10 will always generate carry.
if(!Numeric::carried_in<4>(a_, operand_, result)) {
if(!Numeric::carried_in<true, 4>(a_, operand_, result)) {
if constexpr (is_65c02(personality)) {
result += 0xfa;
} else {
@ -377,7 +377,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
if(flags_.decimal && has_decimal_mode(personality)) {
uint8_t result = a_ + operand_ + flags_.carry;
flags_.zero_result = result;
flags_.carry = Numeric::carried_out<7>(a_, operand_, result);
flags_.carry = Numeric::carried_out<true, 7>(a_, operand_, result);
// General ADC logic:
//
@ -390,7 +390,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
//
// So if that carry already happened, fix up the bottom without permitting another;
// otherwise permit the carry to happen (and check whether carry then rippled out of bit 7).
if(Numeric::carried_in<4>(a_, operand_, result)) {
if(Numeric::carried_in<true, 4>(a_, operand_, result)) {
result = (result & 0xf0) | ((result + 0x06) & 0x0f);
} else if((result & 0xf) > 0x9) {
flags_.carry |= result >= 0x100 - 0x6;