diff --git a/src/cpu.cpp b/src/cpu.cpp index aac5b6d..e99e0e8 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -343,16 +343,18 @@ void CPU::adc8() // ADC A,r8, flags: Z 0 H C m_wait_cycles += 4; + uint32_t old_carry = m_cf != 0; + // Set flags m_nf = 0; - m_hf = isCarry(m_a, register_, 0x10); - m_cf = isCarry(m_a, register_, 0x100); + m_hf = isCarry(m_a, register_, old_carry, 0xf); + m_cf = isCarry(m_a, register_, old_carry, 0xff); // Add the value in r8 plus the carry flag to A - m_a = (m_a + register_ + (m_cf) ? 0x1 : 0) & 0xff; + m_a = (m_a + register_ + old_carry) & 0xff; // Zero flag - m_zf = m_a == 0; + m_zf = (m_a == 0); }; uint8_t opcode = pcRead(); @@ -484,9 +486,8 @@ void CPU::cp() // Zero flag m_zf = ((m_a - register_) & 0xff) == 0; m_nf = 1; - // Note: for subtraction between two positive numbers the carry result is flipped! - m_hf = !isCarry(m_a, register_, 0x10); - m_cf = !isCarry(m_a, register_, 0x100); + m_hf = isCarrySubtraction(m_a, register_, 0xf); + m_cf = isCarrySubtraction(m_a, register_, 0xff); }; uint8_t opcode = pcRead(); @@ -586,13 +587,13 @@ void CPU::dec8() // Set flags m_nf = 1; - m_hf = isCarry(register_, -1, 0x10); + m_hf = isCarrySubtraction(register_, 1, 0xf); // Decrement value in register r8 by 1 register_ = (register_ - 1) & 0xff; // Zero flag - m_zf = register_ == 0; + m_zf = (register_ == 0); }; uint8_t opcode = pcRead(); @@ -712,15 +713,14 @@ void CPU::sbc8() // Set flags m_nf = 1; - // Note: for subtraction between two positive numbers the carry result is flipped! - m_hf = !isCarry(m_a, register_, 0x10); - m_cf = !isCarry(m_a, (register_ + (old_carry) ? 1 : 0), 0x100); + m_hf = isCarrySubtraction(m_a, register_, old_carry, 0xf); + m_cf = isCarrySubtraction(m_a, register_, old_carry, 0xff); // Subtract the value in r8 and the carry flag from A - m_a = (m_a - register_ - (old_carry) ? 1 : 0) & 0xff; + m_a = (m_a - register_ - old_carry) & 0xff; // Zero flag - m_zf = m_a == 0; + m_zf = (m_a == 0); }; uint8_t opcode = pcRead(); @@ -759,9 +759,8 @@ void CPU::sub8() // Set flags m_nf = 1; - // Note: for subtraction between two positive numbers the carry result is flipped! - m_hf = !isCarry(m_a, register_, 0x10); - m_cf = !isCarry(m_a, register_, 0x100); + m_hf = isCarrySubtraction(m_a, register_, 0xf); + m_cf = isCarrySubtraction(m_a, register_, 0xff); // Subtract the value in r8 from A m_a = (m_a - register_) & 0xff; @@ -1705,6 +1704,21 @@ bool CPU::isCarry(uint32_t lhs, uint32_t rhs, uint32_t limit_bit) return (lhs ^ rhs ^ (lhs + rhs)) & limit_bit; } +bool CPU::isCarry(uint32_t lhs, uint32_t middle, uint32_t rhs, uint32_t limit_bit) +{ + return (lhs & limit_bit) + (middle & limit_bit) + (rhs & limit_bit) > limit_bit; +} + +bool CPU::isCarrySubtraction(uint32_t lhs, uint32_t rhs, uint32_t limit_bit) +{ + return (lhs & limit_bit) < (rhs & limit_bit); +} + +bool CPU::isCarrySubtraction(uint32_t lhs, uint32_t middle, uint32_t rhs, uint32_t limit_bit) +{ + return (lhs & limit_bit) < (middle & limit_bit) + (rhs & limit_bit); +} + // ----------------------------------------- void Formatter::parse(Parser& parser) diff --git a/src/cpu.h b/src/cpu.h index 6ec3610..5fc1760 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -124,6 +124,9 @@ private: uint32_t ffRead(uint32_t address); bool isCarry(uint32_t lhs, uint32_t rhs, uint32_t limit_bit); + bool isCarry(uint32_t lhs, uint32_t middle, uint32_t rhs, uint32_t limit_bit); + bool isCarrySubtraction(uint32_t lhs, uint32_t rhs, uint32_t limit_bit); + bool isCarrySubtraction(uint32_t lhs, uint32_t middle, uint32_t rhs, uint32_t limit_bit); // Registers uint32_t m_a { 0 }; // Accumulator