Emulator: Fix ADC/CP/DEC/SBC/SUB opcode: 0x8e, 0xbe, 0x35, 0x93, 0x96
Most of these were broken on the carry and half-carry calculation.
This commit is contained in:
+31
-17
@@ -343,16 +343,18 @@ void CPU::adc8()
|
|||||||
// ADC A,r8, flags: Z 0 H C
|
// ADC A,r8, flags: Z 0 H C
|
||||||
m_wait_cycles += 4;
|
m_wait_cycles += 4;
|
||||||
|
|
||||||
|
uint32_t old_carry = m_cf != 0;
|
||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
m_nf = 0;
|
m_nf = 0;
|
||||||
m_hf = isCarry(m_a, register_, 0x10);
|
m_hf = isCarry(m_a, register_, old_carry, 0xf);
|
||||||
m_cf = isCarry(m_a, register_, 0x100);
|
m_cf = isCarry(m_a, register_, old_carry, 0xff);
|
||||||
|
|
||||||
// Add the value in r8 plus the carry flag to A
|
// 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
|
// Zero flag
|
||||||
m_zf = m_a == 0;
|
m_zf = (m_a == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
@@ -484,9 +486,8 @@ void CPU::cp()
|
|||||||
// Zero flag
|
// Zero flag
|
||||||
m_zf = ((m_a - register_) & 0xff) == 0;
|
m_zf = ((m_a - register_) & 0xff) == 0;
|
||||||
m_nf = 1;
|
m_nf = 1;
|
||||||
// Note: for subtraction between two positive numbers the carry result is flipped!
|
m_hf = isCarrySubtraction(m_a, register_, 0xf);
|
||||||
m_hf = !isCarry(m_a, register_, 0x10);
|
m_cf = isCarrySubtraction(m_a, register_, 0xff);
|
||||||
m_cf = !isCarry(m_a, register_, 0x100);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
@@ -586,13 +587,13 @@ void CPU::dec8()
|
|||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
m_nf = 1;
|
m_nf = 1;
|
||||||
m_hf = isCarry(register_, -1, 0x10);
|
m_hf = isCarrySubtraction(register_, 1, 0xf);
|
||||||
|
|
||||||
// Decrement value in register r8 by 1
|
// Decrement value in register r8 by 1
|
||||||
register_ = (register_ - 1) & 0xff;
|
register_ = (register_ - 1) & 0xff;
|
||||||
|
|
||||||
// Zero flag
|
// Zero flag
|
||||||
m_zf = register_ == 0;
|
m_zf = (register_ == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
@@ -712,15 +713,14 @@ void CPU::sbc8()
|
|||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
m_nf = 1;
|
m_nf = 1;
|
||||||
// Note: for subtraction between two positive numbers the carry result is flipped!
|
m_hf = isCarrySubtraction(m_a, register_, old_carry, 0xf);
|
||||||
m_hf = !isCarry(m_a, register_, 0x10);
|
m_cf = isCarrySubtraction(m_a, register_, old_carry, 0xff);
|
||||||
m_cf = !isCarry(m_a, (register_ + (old_carry) ? 1 : 0), 0x100);
|
|
||||||
|
|
||||||
// Subtract the value in r8 and the carry flag from A
|
// 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
|
// Zero flag
|
||||||
m_zf = m_a == 0;
|
m_zf = (m_a == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t opcode = pcRead();
|
uint8_t opcode = pcRead();
|
||||||
@@ -759,9 +759,8 @@ void CPU::sub8()
|
|||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
m_nf = 1;
|
m_nf = 1;
|
||||||
// Note: for subtraction between two positive numbers the carry result is flipped!
|
m_hf = isCarrySubtraction(m_a, register_, 0xf);
|
||||||
m_hf = !isCarry(m_a, register_, 0x10);
|
m_cf = isCarrySubtraction(m_a, register_, 0xff);
|
||||||
m_cf = !isCarry(m_a, register_, 0x100);
|
|
||||||
|
|
||||||
// Subtract the value in r8 from A
|
// Subtract the value in r8 from A
|
||||||
m_a = (m_a - register_) & 0xff;
|
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;
|
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<CPU>::parse(Parser& parser)
|
void Formatter<CPU>::parse(Parser& parser)
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ private:
|
|||||||
uint32_t ffRead(uint32_t address);
|
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 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
|
// Registers
|
||||||
uint32_t m_a { 0 }; // Accumulator
|
uint32_t m_a { 0 }; // Accumulator
|
||||||
|
|||||||
Reference in New Issue
Block a user