From 19431996cfc4dd94114f9fe1f407e7f4ba5b585e Mon Sep 17 00:00:00 2001 From: Richard Dymond Date: Tue, 13 Aug 2024 17:35:36 -0300 Subject: [PATCH] Fix how 'ADC HL,rr' and 'SBC HL,rr' affect the half-carry flag --- c/csimulator.c | 30 +++++++++++++----------------- skoolkit/simulator.py | 27 +++++++++++++-------------- sphinx/source/changelog.rst | 3 ++- tests/slow_test_simulator.py | 8 ++++---- 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/c/csimulator.c b/c/csimulator.c index 84d0e9e9..fba761bc 100644 --- a/c/csimulator.c +++ b/c/csimulator.c @@ -1218,7 +1218,8 @@ static void adc_hl(CSimulatorObject* self, void* lookup, int args[]) { } #endif unsigned rr = REG(rl) + 256 * REG(rh); - unsigned hl = REG(L) + 256 * REG(H); + unsigned h = REG(H); + unsigned hl = REG(L) + 256 * h; unsigned rr_c = rr + (REG(F) & 1); unsigned result = hl + rr_c; unsigned f = 0; @@ -1229,18 +1230,16 @@ static void adc_hl(CSimulatorObject* self, void* lookup, int args[]) { if (result == 0) { f += 0x40; // .Z...... } - if ((hl % 4096) + (rr_c % 4096) > 0x0FFF) { - f += 0x10; // ...H.... - } + unsigned r_h = result / 256; + f += (h ^ (rr / 256) ^ r_h) & 0x10; // ...H.... if ((hl ^ rr) < 0x8000 && (hl ^ result) > 0x7FFF) { // Augend and addend signs are the same - overflow if their sign // differs from the sign of the result f += 0x04; // .....P.. } - unsigned h = result / 256; - LD(F, f + (h & 0xA8)); + LD(F, f + (r_h & 0xA8)); LD(L, result % 256); - LD(H, h); + LD(H, r_h); INC_R(2); INC_T(15); @@ -2835,11 +2834,12 @@ static void sbc_hl(CSimulatorObject* self, void* lookup, int args[]) { } #endif unsigned rr = REG(rl) + 256 * REG(rh); - unsigned hl = REG(L) + 256 * REG(H); + unsigned h = REG(H); + unsigned hl = REG(L) + 256 * h; unsigned rr_c = rr + (REG(F) & 1); - unsigned result = (hl - rr_c) % 65536; + unsigned result = (hl - rr_c) & 0xFFFF; + unsigned r_h = result / 256; unsigned f = 0; - if (hl < rr_c) { f = 0x03; // ......NC } else { @@ -2848,19 +2848,15 @@ static void sbc_hl(CSimulatorObject* self, void* lookup, int args[]) { if (result == 0) { f += 0x40; // .Z...... } - if (hl % 4096 < rr_c % 4096) { - f += 0x10; // ...H.... - } + f += (h ^ (rr / 256) ^ r_h) & 0x10; // ...H.... if ((hl ^ rr) > 0x7FFF && (hl ^ result) > 0x7FFF) { // Minuend and subtrahend signs are different - overflow if the // minuend's sign differs from the sign of the result f += 0x04; // .....P.. } - - unsigned h = result / 256; - LD(F, f + (h & 0xA8)); + LD(F, f + (r_h & 0xA8)); LD(L, result % 256); - LD(H, h); + LD(H, r_h); INC_R(2); INC_T(15); diff --git a/skoolkit/simulator.py b/skoolkit/simulator.py index c45918d0..a8c2b811 100644 --- a/skoolkit/simulator.py +++ b/skoolkit/simulator.py @@ -250,9 +250,9 @@ def fc_xy(self, registers, memory, size, fc, xyh, xyl, dest=-1): def adc_hl(self, registers, rh, rl): # ADC HL,BC/DE/HL/SP rr = registers[rl] + 256 * registers[rh] - hl = registers[7] + 256 * registers[6] - rr_c = rr + registers[1] % 2 - result = hl + rr_c + h = registers[6] + hl = registers[7] + 256 * h + result = hl + rr + registers[1] % 2 if result > 0xFFFF: result %= 65536 @@ -261,17 +261,16 @@ def adc_hl(self, registers, rh, rl): f = 0 if result == 0: f += 0x40 # .Z...... - if (hl % 4096) + (rr_c % 4096) > 0x0FFF: - f += 0x10 # ...H.... + r_h = result // 256 + f += (h ^ (rr // 256) ^ r_h) & 0x10 # ...H.... if hl ^ rr < 0x8000 and hl ^ result > 0x7FFF: # Augend and addend signs are the same - overflow if their sign # differs from the sign of the result f += 0x04 # .....P.. - h = result // 256 - registers[1] = f + (h & 0xA8) + registers[1] = f + (r_h & 0xA8) registers[7] = result % 256 - registers[6] = h + registers[6] = r_h registers[15] = R2[registers[15]] # R registers[25] += 15 # T-states registers[24] = (registers[24] + 2) % 65536 # PC @@ -966,9 +965,11 @@ def rst(self, registers, memory, addr): def sbc_hl(self, registers, rh, rl): # SBC HL,BC/DE/HL/SP rr = registers[rl] + 256 * registers[rh] - hl = registers[7] + 256 * registers[6] + h = registers[6] + hl = registers[7] + 256 * h rr_c = rr + (registers[1] % 2) result = (hl - rr_c) % 65536 + r_h = result // 256 if hl < rr_c: f = 0x03 # ......NC @@ -976,17 +977,15 @@ def sbc_hl(self, registers, rh, rl): f = 0x02 # ......N. if result == 0: f += 0x40 # .Z...... - if hl % 4096 < rr_c % 4096: - f += 0x10 # ...H.... + f += (h ^ (rr // 256) ^ r_h) & 0x10 # ...H.... if hl ^ rr > 0x7FFF and hl ^ result > 0x7FFF: # Minuend and subtrahend signs are different - overflow if the # minuend's sign differs from the sign of the result f += 0x04 # .....P.. - h = result // 256 - registers[1] = f + (h & 0xA8) + registers[1] = f + (r_h & 0xA8) registers[7] = result % 256 - registers[6] = h + registers[6] = r_h registers[15] = R2[registers[15]] # R registers[25] += 15 # T-states registers[24] = (registers[24] + 2) % 65536 # PC diff --git a/sphinx/source/changelog.rst b/sphinx/source/changelog.rst index ae719df7..028c79b6 100644 --- a/sphinx/source/changelog.rst +++ b/sphinx/source/changelog.rst @@ -3,7 +3,8 @@ Changelog 9.4b1 ----- -* Fixed how the 'ADC A,*' and 'SBC A,*' instructions affect the half-carry flag +* Fixed how the 'ADC A,*', 'SBC A,*', 'ADC HL,rr' and 'SBC HL,rr' instructions + affect the half-carry flag 9.3 (2024-08-10) ---------------- diff --git a/tests/slow_test_simulator.py b/tests/slow_test_simulator.py index 38439df8..79692766 100644 --- a/tests/slow_test_simulator.py +++ b/tests/slow_test_simulator.py @@ -594,19 +594,19 @@ def test_add_hl_rr(self): self._verify(HLRRFTracer(9), '72f5c0ca1f607654448d41ba83f51c52') def test_adc_hl_rr(self): - self._verify(HLRRFTracer(237, 74), '239e29da51c0bef37b131f3e0b1c731c') + self._verify(HLRRFTracer(237, 74), 'd9be5b1c55b9596dfb1369962b22de45') def test_sbc_hl_rr(self): - self._verify(HLRRFTracer(237, 66), '0d97517afe1301cec29656ecd4a8d6aa') + self._verify(HLRRFTracer(237, 66), '7b1dd67c26449c0c6d921b5a95b53b61') def test_add_hl_hl(self): self._verify(HLFTracer(41), 'c1e9d4ef148c912ed4d5ddbd3d761eb4') def test_adc_hl_hl(self): - self._verify(HLFTracer(237, 106), '7540639ced53d305f2ebff71af813cc8') + self._verify(HLFTracer(237, 106), '9cb91b3725b05e904432cef9ae801371') def test_sbc_hl_hl(self): - self._verify(HLFTracer(237, 98), 'b2352766d380075636c4cf0a38a7e7d8') + self._verify(HLFTracer(237, 98), '26f9c69cc72c2509a7156fc1f596d938') class BLKTest(SimulatorTest): def test_ldi(self):