From 0fe09cd1e4ad501ac9da04f4fad3e341c32cb31b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 10 Oct 2020 17:13:16 -0400 Subject: [PATCH] Knocks SBC into producing likely results; disables Lorenz testing. --- .../WolfgangLorenzTests.swift | 10 ++--- .../Implementation/65816Implementation.hpp | 43 +++++++++++++++---- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift index 8246bc658..8107a4154 100644 --- a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift +++ b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift @@ -220,12 +220,10 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { func testFlagManipulation65816() { testFlagManipulation(processor: .processor65816) } - func testADC65816() { - runTest("adc", suffixes: ["b", "z", "zx", "a", "ax", "ay", "ix", "iy"], processor: .processor65816) - } - func testSBC65816() { - runTest("sbc", suffixes: ["b", "z", "zx", "a", "ax", "ay", "ix", "iy"], processor: .processor65816) - } + /* + ADC and SBC tests don't apply, as the 65816 follows the 65C02 in setting flags based on the outcome of decimal + results, whereas Lorenzz's tests expect the original 6502 behaviour of setting flags based an intermediate value. + */ // MARK: - Collections diff --git a/Processors/65816/Implementation/65816Implementation.hpp b/Processors/65816/Implementation/65816Implementation.hpp index 490ef6a67..87f945e1d 100644 --- a/Processors/65816/Implementation/65816Implementation.hpp +++ b/Processors/65816/Implementation/65816Implementation.hpp @@ -715,6 +715,34 @@ template void Processor::run_for(const Cycles #undef cp case SBC: + if(flags_.decimal) { + // I've yet to manage to find a rational way to map this to an ADC, + // hence the yucky repetition of code here. + const uint16_t a = a_.full & m_masks_[1]; + unsigned int result = 0; + unsigned int borrow = flags_.carry ^ 1; + +#define nibble(mask, adjustment, carry) \ + result += (a & mask) - (data_buffer_.value & mask) - borrow; \ + if(result > mask) result -= adjustment;\ + borrow = (result > mask) ? carry : 0; \ + result &= (carry - 1); + + nibble(0x000f, 0x0006, 0x00010); + nibble(0x00f0, 0x0060, 0x00100); + nibble(0x0f00, 0x0600, 0x01000); + nibble(0xf000, 0x6000, 0x10000); + +#undef nibble + + flags_.overflow = ~(( (result ^ a_.full) & (result ^ data_buffer_.value) ) >> (1 + m_shift_))&0x40; + flags_.set_nz(result, m_shift_); + flags_.carry = ((borrow >> 16)&1)^1; + LD(a_, result, m_masks_); + + break; + } + data_buffer_.value = ~data_buffer_.value & m_masks_[1]; [[fallthrough]]; @@ -724,18 +752,15 @@ template void Processor::run_for(const Cycles if(flags_.decimal) { result = flags_.carry; - const int nibble_adjustment = (active_instruction_->operation == SBC) ? 0xa : 0x6; - // TODO: this still isn't quite correct for SBC as the limit test is wrong, I think. - -#define nibble(mask, limit, addition, carry) \ +#define nibble(mask, limit, adjustment, carry) \ result += (a & mask) + (data_buffer_.value & mask); \ - if(result >= limit) result = ((result + (addition)) & (carry - 1)) + carry; + if(result >= limit) result = ((result + (adjustment)) & (carry - 1)) + carry; - nibble(0x000f, 0x000a, nibble_adjustment << 0, 0x00010); - nibble(0x00f0, 0x00a0, nibble_adjustment << 4, 0x00100); - nibble(0x0f00, 0x0a00, nibble_adjustment << 8, 0x01000); - nibble(0xf000, 0xa000, nibble_adjustment << 12, 0x10000); + nibble(0x000f, 0x000a, 0x0006, 0x00010); + nibble(0x00f0, 0x00a0, 0x0060, 0x00100); + nibble(0x0f00, 0x0a00, 0x0600, 0x01000); + nibble(0xf000, 0xa000, 0x6000, 0x10000); #undef nibble