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:
@@ -34,10 +34,10 @@ void anc(RegistersT ®isters, const uint8_t operand) {
|
||||
template <Model model, typename RegistersT>
|
||||
void adc(RegistersT ®isters, 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 ®isters, 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 ®isters, 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:
|
||||
//
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user