1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-21 02:17:08 +00:00

Pull out overflow logic, remove 16-bit arithmetic from ADC.

This commit is contained in:
Thomas Harte
2025-10-23 18:23:09 -04:00
parent 5d223bce4c
commit cf93c39881
2 changed files with 19 additions and 26 deletions
+7 -8
View File
@@ -34,10 +34,10 @@ void anc(RegistersT &registers, const uint8_t operand) {
template <Model model, typename RegistersT>
void adc(RegistersT &registers, const uint8_t operand) {
if(!has_decimal_mode(model) || !registers.flags.decimal) {
const uint16_t result = uint16_t(registers.a) + uint16_t(operand) + uint16_t(registers.flags.carry);
registers.flags.overflow = (( (result^registers.a)&(result^operand) )&0x80) >> 1;
registers.flags.set_nz(registers.a = uint8_t(result));
registers.flags.carry = (result >> 8)&1;
const uint8_t result = registers.a + operand + registers.flags.carry;
registers.flags.carry = result < registers.a + registers.flags.carry;
registers.flags.set_v(result, registers.a, operand);
registers.flags.set_nz(registers.a = result);
return;
}
@@ -66,7 +66,7 @@ void adc(RegistersT &registers, const uint8_t operand) {
// 6502 quirk: N and V are set before the full result is computed but
// after the low nibble has been corrected.
registers.flags.negative_result = result;
registers.flags.overflow = (( (result ^ registers.a) & (result ^ operand) ) & 0x80) >> 1;
registers.flags.set_v(result, registers.a, operand);
// i.e. fix high nibble if there was carry out of bit 7 already, or if the
// top nibble is too large (in which case there will be carry after the fix-up).
@@ -92,10 +92,9 @@ void sbc(RegistersT &registers, const uint8_t operand) {
uint8_t result = registers.a + operand_complement + registers.flags.carry;
// All flags are set based only on the decimal result.
registers.flags.zero_result = result;
registers.flags.set_nz(result);
registers.flags.carry = Numeric::carried_out<Numeric::Operation::Add, 7>(registers.a, operand_complement, result);
registers.flags.negative_result = result;
registers.flags.overflow = (( (result ^ registers.a) & (result ^ operand_complement) ) & 0x80) >> 1;
registers.flags.set_v(result, registers.a, operand_complement);
// General SBC logic:
//
+12 -18
View File
@@ -54,24 +54,6 @@ enum Flag: uint8_t {
};
struct Flags {
/// Bit 7 is set if the negative flag is set; otherwise it is clear.
uint8_t negative_result = 0;
/// Non-zero if the zero flag is clear, zero if it is set.
uint8_t zero_result = 0;
/// Contains Flag::Carry.
uint8_t carry = 0;
/// Contains Flag::Decimal.
uint8_t decimal = 0;
/// Contains Flag::Overflow.
uint8_t overflow = 0;
/// Contains Flag::Interrupt, complemented.
uint8_t inverse_interrupt = 0;
/// Sets N and Z flags per the 8-bit value @c value.
void set_nz(const uint8_t value) {
zero_result = negative_result = value;
@@ -93,6 +75,11 @@ struct Flags {
negative_result = uint8_t(value >> shift);
}
void set_v(const uint8_t result, const uint8_t lhs, const uint8_t rhs) {
// TODO: can this be done lazily?
overflow = (( (result^lhs) & (result^rhs) ) & 0x80) >> 1;
}
explicit operator uint8_t() const {
return
carry | overflow | (inverse_interrupt ^ Flag::Interrupt) | (negative_result & 0x80) |
@@ -119,6 +106,13 @@ struct Flags {
auto operator <=> (const Flags &rhs) const {
return static_cast<uint8_t>(*this) <=> static_cast<uint8_t>(rhs);
}
uint8_t negative_result = 0; /// Bit 7 = the negative flag.
uint8_t zero_result = 0; /// Non-zero if the zero flag is clear, zero if it is set.
uint8_t carry = 0; /// Contains Flag::Carry.
uint8_t decimal = 0; /// Contains Flag::Decimal.
uint8_t overflow = 0; /// Contains Flag::Overflow.
uint8_t inverse_interrupt = 0; /// Contains Flag::Interrupt, complemented.
};
struct Registers {