From ac926f50700f0bfb858e4d97e54315fd6672ed0f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 29 Jun 2019 13:31:24 -0400 Subject: [PATCH] Factors BCD out of general arithmetic. --- .../Clock Signal.xcodeproj/project.pbxproj | 4 + .../Clock SignalTests/68000ArithmeticTests.mm | 262 ---------------- .../Mac/Clock SignalTests/68000BCDTests.mm | 291 ++++++++++++++++++ 3 files changed, 295 insertions(+), 262 deletions(-) create mode 100644 OSBindings/Mac/Clock SignalTests/68000BCDTests.mm diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 48ebd7a3d..a19d3bd54 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -308,6 +308,7 @@ 4B98A1CE1FFADEC500ADF63B /* MSX ROMs in Resources */ = {isa = PBXBuildFile; fileRef = 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */; }; 4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; }; 4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; }; + 4B9D0C4B22C7D70A00DE1AD3 /* 68000BCDTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */; }; 4B9F11C92272375400701480 /* qltrace.txt.gz in Resources */ = {isa = PBXBuildFile; fileRef = 4B9F11C82272375400701480 /* qltrace.txt.gz */; }; 4B9F11CA2272433900701480 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B69FB451C4D950F00B5F0AA /* libz.tbd */; }; 4B9F11CC22729B3600701480 /* OPCLOGR2.BIN in Resources */ = {isa = PBXBuildFile; fileRef = 4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */; }; @@ -1067,6 +1068,7 @@ 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "MSX ROMs"; sourceTree = ""; }; 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiSpeaker.cpp; sourceTree = ""; }; 4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = ""; }; + 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000BCDTests.mm; sourceTree = ""; }; 4B9F11C82272375400701480 /* qltrace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = qltrace.txt.gz; sourceTree = ""; }; 4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = OPCLOGR2.BIN; path = "68000 Coverage/OPCLOGR2.BIN"; sourceTree = ""; }; 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Data/ZX8081.cpp; sourceTree = ""; }; @@ -2929,6 +2931,7 @@ 4B85322922778E4200F26553 /* Comparative68000.hpp */, 4B90467222C6FA31000E2074 /* TestRunner68000.hpp */, 4B97ADC722C6FD9B00A22A41 /* 68000ArithmeticTests.mm */, + 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */, 4B90467322C6FADD000E2074 /* 68000BitwiseTests.mm */, 4BD388872239E198002D14B5 /* 68000Tests.mm */, 4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */, @@ -4207,6 +4210,7 @@ 4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */, 4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */, 4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */, + 4B9D0C4B22C7D70A00DE1AD3 /* 68000BCDTests.mm in Sources */, 4B3BA0C31D318AEC005DD7A7 /* C1540Tests.swift in Sources */, 4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */, 4B1414601B58885000E04248 /* WolfgangLorenzTests.swift in Sources */, diff --git a/OSBindings/Mac/Clock SignalTests/68000ArithmeticTests.mm b/OSBindings/Mac/Clock SignalTests/68000ArithmeticTests.mm index 3d639ce06..80162a57e 100644 --- a/OSBindings/Mac/Clock SignalTests/68000ArithmeticTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000ArithmeticTests.mm @@ -26,134 +26,6 @@ _machine.reset(); } -// MARK: ABCD - -- (void)testABCD { - _machine->set_program({ - 0xc302, // ABCD D2, D1 - }); - auto state = _machine->get_processor_state(); - state.data[1] = 0x1234567a; - state.data[2] = 0xf745ff78; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Carry); - XCTAssertEqual(state.data[1], 0x12345658); - XCTAssertEqual(state.data[2], 0xf745ff78); -} - -- (void)testABCDZero { - _machine->set_program({ - 0xc302, // ABCD D2, D1 - }); - auto state = _machine->get_processor_state(); - state.data[1] = 0x12345600; - state.data[2] = 0x12345600; - state.status = Flag::Zero; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Zero); - XCTAssertEqual(state.data[1], 0x12345600); - XCTAssertEqual(state.data[2], 0x12345600); -} - -- (void)testABCDNegative { - _machine->set_program({ - 0xc302, // ABCD D2, D1 - }); - auto state = _machine->get_processor_state(); - state.data[1] = 0x12345645; - state.data[2] = 0x12345654; - state.status = Flag::Zero; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Negative); - XCTAssertEqual(state.data[1], 0x12345699); - XCTAssertEqual(state.data[2], 0x12345654); -} - -- (void)testABCDWithX { - _machine->set_program({ - 0xc302, // ABCD D2, D1 - }); - auto state = _machine->get_processor_state(); - state.data[1] = 0x12345645; - state.data[2] = 0x12345654; - state.status = Flag::Extend; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Carry); - XCTAssertEqual(state.data[1], 0x12345600); - XCTAssertEqual(state.data[2], 0x12345654); -} - -- (void)testABCDOverflow { - _machine->set_program({ - 0xc302, // ABCD D2, D1 - }); - auto state = _machine->get_processor_state(); - state.data[1] = 0x1234563e; - state.data[2] = 0x1234563e; - state.status = Flag::Extend; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Overflow); - XCTAssertEqual(state.data[1], 0x12345683); - XCTAssertEqual(state.data[2], 0x1234563e); -} - -- (void)testABCDPredecDifferent { - _machine->set_program({ - 0xc30a, // ABCD -(A2), -(A1) - }); - *_machine->ram_at(0x3000) = 0xa200; - *_machine->ram_at(0x4000) = 0x1900; - - auto state = _machine->get_processor_state(); - state.address[1] = 0x3001; - state.address[2] = 0x4001; - state.status = Flag::Extend; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Carry); - XCTAssert(state.status & Flag::Extend); - XCTAssertEqual(state.address[1], 0x3000); - XCTAssertEqual(state.address[2], 0x4000); - XCTAssertEqual(*_machine->ram_at(0x3000), 0x2200); - XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900); -} - -- (void)testABCDPredecSame { - _machine->set_program({ - 0xc309, // ABCD -(A1), -(A1) - }); - *_machine->ram_at(0x3000) = 0x19a2; - - auto state = _machine->get_processor_state(); - state.address[1] = 0x3002; - state.status = Flag::Extend; - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssert(state.status & Flag::Carry); - XCTAssert(state.status & Flag::Extend); - XCTAssertEqual(state.address[1], 0x3000); - XCTAssertEqual(*_machine->ram_at(0x3000), 0x22a2); -} - // MARK: ADD - (void)testADDb { @@ -1082,68 +954,6 @@ XCTAssertEqual(74, _machine->get_cycle_count()); } -// MARK: NBCD - -- (void)performNBCDd1:(uint32_t)d1 ccr:(uint8_t)ccr { - _machine->set_program({ - 0x4801 // NBCD D1 - }); - auto state = _machine->get_processor_state(); - state.status |= ccr; - state.data[1] = d1; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - XCTAssertEqual(6, _machine->get_cycle_count()); -} - -- (void)testNBCD_Dn { - [self performNBCDd1:0x7a ccr:0]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x20); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow); -} - -- (void)testNBCD_Dn_extend { - [self performNBCDd1:0x1234567a ccr:Flag::Extend | Flag::Zero]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x1234561f); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow); -} - -- (void)testNBCD_Dn_zero { - [self performNBCDd1:0x12345600 ccr:Flag::Zero]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x12345600); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero); -} - -- (void)testNBCD_Dn_negative { - [self performNBCDd1:0x123456ff ccr:Flag::Extend | Flag::Zero]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x1234569a); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative); -} - -- (void)testNBCD_Dn_XXXw { - _machine->set_program({ - 0x4838, 0x3000 // NBCD ($3000).w - }); - *_machine->ram_at(0x3000) = 0x0100; - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(16, _machine->get_cycle_count()); - XCTAssertEqual(*_machine->ram_at(0x3000), 0x9900); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative); -} - // MARK: NEG - (void)performNEGb:(uint32_t)value { @@ -1350,78 +1160,6 @@ XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry); } -// MARK: SBCD - -- (void)performSBCDd1:(uint32_t)d1 d2:(uint32_t)d2 ccr:(uint8_t)ccr { - _machine->set_program({ - 0x8302 // SBCD D2, D1 - }); - auto state = _machine->get_processor_state(); - state.status |= ccr; - state.data[1] = d1; - state.data[2] = d2; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(6, _machine->get_cycle_count()); - XCTAssertEqual(state.data[2], d2); -} - -- (void)testSBCD_Dn { - [self performSBCDd1:0x12345689 d2:0xf745ff78 ccr:Flag::Zero]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x12345611); - XCTAssertEqual(state.status & Flag::ConditionCodes, 0); -} - -- (void)testSBCD_Dn_zero { - [self performSBCDd1:0x123456ff d2:0xf745ffff ccr:Flag::Zero]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x12345600); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero); -} - -- (void)testSBCD_Dn_negative { - [self performSBCDd1:0x12345634 d2:0xf745ff45 ccr:Flag::Extend]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x12345688); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative); -} - -- (void)testSBCD_Dn_overflow { - [self performSBCDd1:0x123456a9 d2:0xf745ffff ccr:Flag::Extend]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], 0x12345643); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow); -} - -- (void)testSBCD_Dn_PreDec { - _machine->set_program({ - 0x830a // SBCD -(A2), -(A1) - }); - *_machine->ram_at(0x3000) = 0xa200; - *_machine->ram_at(0x4000) = 0x1900; - auto state = _machine->get_processor_state(); - state.address[1] = 0x3001; - state.address[2] = 0x4001; - state.status |= Flag::Extend; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(18, _machine->get_cycle_count()); - XCTAssertEqual(*_machine->ram_at(0x3000), 0x8200); - XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative); -} - // MARK: SUB - (void)performSUBbIMM:(uint16_t)value d2:(uint32_t)d2 { diff --git a/OSBindings/Mac/Clock SignalTests/68000BCDTests.mm b/OSBindings/Mac/Clock SignalTests/68000BCDTests.mm new file mode 100644 index 000000000..318671f6d --- /dev/null +++ b/OSBindings/Mac/Clock SignalTests/68000BCDTests.mm @@ -0,0 +1,291 @@ +// +// 68000BCDTests.m +// Clock SignalTests +// +// Created by Thomas Harte on 29/06/2019. +// +// Largely ported from the tests of the Portable 68k Emulator. +// + +#import + +#include "TestRunner68000.hpp" + +@interface M68000BCDTests : XCTestCase +@end + +@implementation M68000BCDTests { + std::unique_ptr _machine; +} + +- (void)setUp { + _machine.reset(new RAM68000()); +} + +- (void)tearDown { + _machine.reset(); +} + +// MARK: ABCD + +- (void)testABCD { + _machine->set_program({ + 0xc302, // ABCD D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x1234567a; + state.data[2] = 0xf745ff78; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Carry); + XCTAssertEqual(state.data[1], 0x12345658); + XCTAssertEqual(state.data[2], 0xf745ff78); +} + +- (void)testABCDZero { + _machine->set_program({ + 0xc302, // ABCD D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x12345600; + state.data[2] = 0x12345600; + state.status = Flag::Zero; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Zero); + XCTAssertEqual(state.data[1], 0x12345600); + XCTAssertEqual(state.data[2], 0x12345600); +} + +- (void)testABCDNegative { + _machine->set_program({ + 0xc302, // ABCD D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x12345645; + state.data[2] = 0x12345654; + state.status = Flag::Zero; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Negative); + XCTAssertEqual(state.data[1], 0x12345699); + XCTAssertEqual(state.data[2], 0x12345654); +} + +- (void)testABCDWithX { + _machine->set_program({ + 0xc302, // ABCD D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x12345645; + state.data[2] = 0x12345654; + state.status = Flag::Extend; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Carry); + XCTAssertEqual(state.data[1], 0x12345600); + XCTAssertEqual(state.data[2], 0x12345654); +} + +- (void)testABCDOverflow { + _machine->set_program({ + 0xc302, // ABCD D2, D1 + }); + auto state = _machine->get_processor_state(); + state.data[1] = 0x1234563e; + state.data[2] = 0x1234563e; + state.status = Flag::Extend; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Overflow); + XCTAssertEqual(state.data[1], 0x12345683); + XCTAssertEqual(state.data[2], 0x1234563e); +} + +- (void)testABCDPredecDifferent { + _machine->set_program({ + 0xc30a, // ABCD -(A2), -(A1) + }); + *_machine->ram_at(0x3000) = 0xa200; + *_machine->ram_at(0x4000) = 0x1900; + + auto state = _machine->get_processor_state(); + state.address[1] = 0x3001; + state.address[2] = 0x4001; + state.status = Flag::Extend; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Carry); + XCTAssert(state.status & Flag::Extend); + XCTAssertEqual(state.address[1], 0x3000); + XCTAssertEqual(state.address[2], 0x4000); + XCTAssertEqual(*_machine->ram_at(0x3000), 0x2200); + XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900); +} + +- (void)testABCDPredecSame { + _machine->set_program({ + 0xc309, // ABCD -(A1), -(A1) + }); + *_machine->ram_at(0x3000) = 0x19a2; + + auto state = _machine->get_processor_state(); + state.address[1] = 0x3002; + state.status = Flag::Extend; + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssert(state.status & Flag::Carry); + XCTAssert(state.status & Flag::Extend); + XCTAssertEqual(state.address[1], 0x3000); + XCTAssertEqual(*_machine->ram_at(0x3000), 0x22a2); +} + +// MARK: NBCD + +- (void)performNBCDd1:(uint32_t)d1 ccr:(uint8_t)ccr { + _machine->set_program({ + 0x4801 // NBCD D1 + }); + auto state = _machine->get_processor_state(); + state.status |= ccr; + state.data[1] = d1; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + XCTAssertEqual(6, _machine->get_cycle_count()); +} + +- (void)testNBCD_Dn { + [self performNBCDd1:0x7a ccr:0]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x20); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow); +} + +- (void)testNBCD_Dn_extend { + [self performNBCDd1:0x1234567a ccr:Flag::Extend | Flag::Zero]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x1234561f); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow); +} + +- (void)testNBCD_Dn_zero { + [self performNBCDd1:0x12345600 ccr:Flag::Zero]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x12345600); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero); +} + +- (void)testNBCD_Dn_negative { + [self performNBCDd1:0x123456ff ccr:Flag::Extend | Flag::Zero]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x1234569a); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative); +} + +- (void)testNBCD_Dn_XXXw { + _machine->set_program({ + 0x4838, 0x3000 // NBCD ($3000).w + }); + *_machine->ram_at(0x3000) = 0x0100; + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(16, _machine->get_cycle_count()); + XCTAssertEqual(*_machine->ram_at(0x3000), 0x9900); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative); +} + +// MARK: SBCD + +- (void)performSBCDd1:(uint32_t)d1 d2:(uint32_t)d2 ccr:(uint8_t)ccr { + _machine->set_program({ + 0x8302 // SBCD D2, D1 + }); + auto state = _machine->get_processor_state(); + state.status |= ccr; + state.data[1] = d1; + state.data[2] = d2; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(6, _machine->get_cycle_count()); + XCTAssertEqual(state.data[2], d2); +} + +- (void)testSBCD_Dn { + [self performSBCDd1:0x12345689 d2:0xf745ff78 ccr:Flag::Zero]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x12345611); + XCTAssertEqual(state.status & Flag::ConditionCodes, 0); +} + +- (void)testSBCD_Dn_zero { + [self performSBCDd1:0x123456ff d2:0xf745ffff ccr:Flag::Zero]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x12345600); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Zero); +} + +- (void)testSBCD_Dn_negative { + [self performSBCDd1:0x12345634 d2:0xf745ff45 ccr:Flag::Extend]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x12345688); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Negative); +} + +- (void)testSBCD_Dn_overflow { + [self performSBCDd1:0x123456a9 d2:0xf745ffff ccr:Flag::Extend]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], 0x12345643); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Carry | Flag::Overflow); +} + +- (void)testSBCD_Dn_PreDec { + _machine->set_program({ + 0x830a // SBCD -(A2), -(A1) + }); + *_machine->ram_at(0x3000) = 0xa200; + *_machine->ram_at(0x4000) = 0x1900; + auto state = _machine->get_processor_state(); + state.address[1] = 0x3001; + state.address[2] = 0x4001; + state.status |= Flag::Extend; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(18, _machine->get_cycle_count()); + XCTAssertEqual(*_machine->ram_at(0x3000), 0x8200); + XCTAssertEqual(*_machine->ram_at(0x4000), 0x1900); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative); +} + +@end