From 6a44c682add98d072bf743ba6188fc47bda3ca51 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 29 Jun 2019 13:47:05 -0400 Subject: [PATCH] Factors out control flow tests. --- .../Clock Signal.xcodeproj/project.pbxproj | 4 + .../68000ControlFlowTests.mm | 507 ++++++++++++++++++ .../Mac/Clock SignalTests/68000Tests.mm | 478 ----------------- 3 files changed, 511 insertions(+), 478 deletions(-) create mode 100644 OSBindings/Mac/Clock SignalTests/68000ControlFlowTests.mm diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index a19d3bd54..5b9397c32 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -309,6 +309,7 @@ 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 */; }; + 4B9D0C4D22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B9D0C4C22C7DA1A00DE1AD3 /* 68000ControlFlowTests.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 */; }; @@ -1069,6 +1070,7 @@ 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 = ""; }; + 4B9D0C4C22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = 68000ControlFlowTests.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 = ""; }; @@ -2933,6 +2935,7 @@ 4B97ADC722C6FD9B00A22A41 /* 68000ArithmeticTests.mm */, 4B9D0C4A22C7D70900DE1AD3 /* 68000BCDTests.mm */, 4B90467322C6FADD000E2074 /* 68000BitwiseTests.mm */, + 4B9D0C4C22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm */, 4BD388872239E198002D14B5 /* 68000Tests.mm */, 4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */, 4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */, @@ -4208,6 +4211,7 @@ 4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */, 4BC751B21D157E61006C31D9 /* 6522Tests.swift in Sources */, 4BFCA12B1ECBE7C400AC40C1 /* ZexallTests.swift in Sources */, + 4B9D0C4D22C7DA1A00DE1AD3 /* 68000ControlFlowTests.mm in Sources */, 4BB2A9AF1E13367E001A5C23 /* CRCTests.mm in Sources */, 4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */, 4B9D0C4B22C7D70A00DE1AD3 /* 68000BCDTests.mm in Sources */, diff --git a/OSBindings/Mac/Clock SignalTests/68000ControlFlowTests.mm b/OSBindings/Mac/Clock SignalTests/68000ControlFlowTests.mm new file mode 100644 index 000000000..c4e8d157c --- /dev/null +++ b/OSBindings/Mac/Clock SignalTests/68000ControlFlowTests.mm @@ -0,0 +1,507 @@ +// +// 68000ControlFlowTests.m +// Clock SignalTests +// +// Created by Thomas Harte on 28/06/2019. +// +// Largely ported from the tests of the Portable 68k Emulator. +// + +#import + +#include "TestRunner68000.hpp" + + +@interface M68000ControlFlowTests : XCTestCase +@end + +@implementation M68000ControlFlowTests { + std::unique_ptr _machine; +} + +- (void)setUp { + _machine.reset(new RAM68000()); +} + +- (void)tearDown { + _machine.reset(); +} + +// MARK: BRA + +- (void)testBRAb { + _machine->set_program({ + 0x6004 // BRA.b +4 + }); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1006 + 4); + XCTAssertEqual(_machine->get_cycle_count(), 10); +} + +- (void)testBRAw { + _machine->set_program({ + 0x6000, 0x0004 // BRA.b +4 + }); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1006 + 4); + XCTAssertEqual(_machine->get_cycle_count(), 10); +} + +// MARK: BSR + +- (void)testBSRw { + _machine->set_program({ + 0x6100, 0x0006 // BSR.w $1008 + }); + _machine->set_initial_stack_pointer(0x3000); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1008 + 4); + XCTAssertEqual(state.stack_pointer(), 0x2ffc); + XCTAssertEqual(state.status & Flag::ConditionCodes, 0); + XCTAssertEqual(*_machine->ram_at(0x2ffc), 0); + XCTAssertEqual(*_machine->ram_at(0x2ffe), 0x1004); + + XCTAssertEqual(_machine->get_cycle_count(), 18); +} + +- (void)testBSRb { + _machine->set_program({ + 0x6106 // BSR.b $1008 + }); + _machine->set_initial_stack_pointer(0x3000); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1008 + 4); + XCTAssertEqual(state.stack_pointer(), 0x2ffc); + XCTAssertEqual(state.status & Flag::ConditionCodes, 0); + XCTAssertEqual(*_machine->ram_at(0x2ffc), 0); + XCTAssertEqual(*_machine->ram_at(0x2ffe), 0x1002); + + XCTAssertEqual(_machine->get_cycle_count(), 18); +} + +// MARK: CHK + +- (void)performCHKd1:(uint32_t)d1 d2:(uint32_t)d2 { + _machine->set_program({ + 0x4581 // CHK D1, D2 + }); + auto state = _machine->get_processor_state(); + state.data[1] = d1; + state.data[2] = d2; + state.status |= Flag::ConditionCodes; + + _machine->set_initial_stack_pointer(0); + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[1], d1); + XCTAssertEqual(state.data[2], d2); +} + +- (void)testCHK_1111v1111 { + [self performCHKd1:0x1111 d2:0x1111]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1002 + 4); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend); + XCTAssertEqual(10, _machine->get_cycle_count()); +} + +- (void)testCHK_1111v0000 { + [self performCHKd1:0x1111 d2:0x0000]; + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1002 + 4); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Zero); + XCTAssertEqual(10, _machine->get_cycle_count()); +} + +- (void)testCHK_8000v8001 { + [self performCHKd1:0x8000 d2:0x8001]; + + const auto state = _machine->get_processor_state(); + XCTAssertNotEqual(state.program_counter, 0x1002 + 4); + XCTAssertEqual(state.stack_pointer(), 0xfffffffa); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend); + XCTAssertEqual(42, _machine->get_cycle_count()); +} + +- (void)testCHK_8000v8000 { + [self performCHKd1:0x8000 d2:0x8000]; + + const auto state = _machine->get_processor_state(); + XCTAssertNotEqual(state.program_counter, 0x1002 + 4); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Negative); + XCTAssertEqual(44, _machine->get_cycle_count()); +} + +// MARK: DBcc + +- (void)performDBccTestOpcode:(uint16_t)opcode status:(uint16_t)status d2Outcome:(uint32_t)d2Output { + _machine->set_program({ + opcode, 0x0008 // DBcc D2, +8 + }); + auto state = _machine->get_processor_state(); + state.status = status; + state.data[2] = 1; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.data[2], d2Output); + XCTAssertEqual(state.status, status); +} + +- (void)testDBT { + [self performDBccTestOpcode:0x50ca status:0 d2Outcome:1]; +} + +- (void)testDBF { + [self performDBccTestOpcode:0x51ca status:0 d2Outcome:0]; +} + +- (void)testDBHI { + [self performDBccTestOpcode:0x52ca status:0 d2Outcome:1]; +} + +- (void)testDBHI_Carry { + [self performDBccTestOpcode:0x52ca status:Flag::Carry d2Outcome:0]; +} + +- (void)testDBHI_Zero { + [self performDBccTestOpcode:0x52ca status:Flag::Zero d2Outcome:0]; +} + +- (void)testDBLS_CarryOverflow { + [self performDBccTestOpcode:0x53ca status:Flag::Carry | Flag::Overflow d2Outcome:1]; +} + +- (void)testDBLS_Carry { + [self performDBccTestOpcode:0x53ca status:Flag::Carry d2Outcome:1]; +} + +- (void)testDBLS_Overflow { + [self performDBccTestOpcode:0x53ca status:Flag::Overflow d2Outcome:0]; +} + +- (void)testDBCC_Carry { + [self performDBccTestOpcode:0x54ca status:Flag::Carry d2Outcome:0]; +} + +- (void)testDBCC { + [self performDBccTestOpcode:0x54ca status:0 d2Outcome:1]; +} + +- (void)testDBCS { + [self performDBccTestOpcode:0x55ca status:0 d2Outcome:0]; +} + +- (void)testDBCS_Carry { + [self performDBccTestOpcode:0x55ca status:Flag::Carry d2Outcome:1]; +} + +- (void)testDBNE { + [self performDBccTestOpcode:0x56ca status:0 d2Outcome:1]; +} + +- (void)testDBNE_Zero { + [self performDBccTestOpcode:0x56ca status:Flag::Zero d2Outcome:0]; +} + +- (void)testDBEQ { + [self performDBccTestOpcode:0x57ca status:0 d2Outcome:0]; +} + +- (void)testDBEQ_Zero { + [self performDBccTestOpcode:0x57ca status:Flag::Zero d2Outcome:1]; +} + +- (void)testDBVC { + [self performDBccTestOpcode:0x58ca status:0 d2Outcome:1]; +} + +- (void)testDBVC_Overflow { + [self performDBccTestOpcode:0x58ca status:Flag::Overflow d2Outcome:0]; +} + +- (void)testDBVS { + [self performDBccTestOpcode:0x59ca status:0 d2Outcome:0]; +} + +- (void)testDBVS_Overflow { + [self performDBccTestOpcode:0x59ca status:Flag::Overflow d2Outcome:1]; +} + +- (void)testDBPL { + [self performDBccTestOpcode:0x5aca status:0 d2Outcome:1]; +} + +- (void)testDBPL_Negative { + [self performDBccTestOpcode:0x5aca status:Flag::Negative d2Outcome:0]; +} + +- (void)testDBMI { + [self performDBccTestOpcode:0x5bca status:0 d2Outcome:0]; +} + +- (void)testDBMI_Negative { + [self performDBccTestOpcode:0x5bca status:Flag::Negative d2Outcome:1]; +} + +- (void)testDBGE_NegativeOverflow { + [self performDBccTestOpcode:0x5cca status:Flag::Negative | Flag::Overflow d2Outcome:1]; +} + +- (void)testDBGE { + [self performDBccTestOpcode:0x5cca status:0 d2Outcome:1]; +} + +- (void)testDBGE_Negative { + [self performDBccTestOpcode:0x5cca status:Flag::Negative d2Outcome:0]; +} + +- (void)testDBGE_Overflow { + [self performDBccTestOpcode:0x5cca status:Flag::Overflow d2Outcome:0]; +} + +- (void)testDBLT_NegativeOverflow { + [self performDBccTestOpcode:0x5dca status:Flag::Negative | Flag::Overflow d2Outcome:0]; +} + +- (void)testDBLT { + [self performDBccTestOpcode:0x5dca status:0 d2Outcome:0]; +} + +- (void)testDBLT_Negative { + [self performDBccTestOpcode:0x5dca status:Flag::Negative d2Outcome:1]; +} + +- (void)testDBLT_Overflow { + [self performDBccTestOpcode:0x5dca status:Flag::Overflow d2Outcome:1]; +} + +- (void)testDBGT { + [self performDBccTestOpcode:0x5eca status:0 d2Outcome:1]; +} + +- (void)testDBGT_ZeroNegativeOverflow { + [self performDBccTestOpcode:0x5eca status:Flag::Zero | Flag::Negative | Flag::Overflow d2Outcome:0]; +} + +- (void)testDBGT_NegativeOverflow { + [self performDBccTestOpcode:0x5eca status:Flag::Negative | Flag::Overflow d2Outcome:1]; +} + +- (void)testDBGT_Zero { + [self performDBccTestOpcode:0x5eca status:Flag::Zero d2Outcome:0]; +} + +- (void)testDBLE { + [self performDBccTestOpcode:0x5fca status:0 d2Outcome:0]; +} + +- (void)testDBLE_Zero { + [self performDBccTestOpcode:0x5fca status:Flag::Zero d2Outcome:1]; +} + +- (void)testDBLE_Negative { + [self performDBccTestOpcode:0x5fca status:Flag::Negative d2Outcome:1]; +} + +- (void)testDBLE_NegativeOverflow { + [self performDBccTestOpcode:0x5fca status:Flag::Negative | Flag::Overflow d2Outcome:0]; +} + +/* Further DBF tests omitted; they seemed to be duplicative, assuming I'm not suffering a failure of comprehension. */ + +// MARK: JMP + +- (void)testJMP_A1 { + _machine->set_program({ + 0x4ed1 // JMP (A1) + }); + + auto state = _machine->get_processor_state(); + state.address[1] = 0x3000; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.address[1], 0x3000); + XCTAssertEqual(state.program_counter, 0x3000 + 4); + XCTAssertEqual(8, _machine->get_cycle_count()); +} + +- (void)testJMP_PC { + _machine->set_program({ + 0x4efa, 0x000a // JMP PC+a (i.e. to 0x100c) + }); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x100c + 4); + XCTAssertEqual(10, _machine->get_cycle_count()); +} + +// MARK: JSR + +- (void)testJSR_PC { + _machine->set_program({ + 0x4eba, 0x000a // JSR (+a)PC ; JSR to $100c + }); + _machine->set_initial_stack_pointer(0x2000); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.stack_pointer(), 0x1ffc); + XCTAssertEqual(state.program_counter, 0x100c + 4); + XCTAssertEqual(*_machine->ram_at(0x1ffc), 0x0000); + XCTAssertEqual(*_machine->ram_at(0x1ffe), 0x1004); + XCTAssertEqual(18, _machine->get_cycle_count()); +} + +- (void)testJSR_XXXl { + _machine->set_program({ + 0x4eb9, 0x0000, 0x1008 // JSR ($1008).l + }); + _machine->set_initial_stack_pointer(0x2000); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.stack_pointer(), 0x1ffc); + XCTAssertEqual(state.program_counter, 0x1008 + 4); + XCTAssertEqual(*_machine->ram_at(0x1ffc), 0x0000); + XCTAssertEqual(*_machine->ram_at(0x1ffe), 0x1006); + XCTAssertEqual(20, _machine->get_cycle_count()); +} + +// MARK: NOP + +- (void)testNOP { + _machine->set_program({ + 0x4e71 // NOP + }); + _machine->run_for_instructions(1); + XCTAssertEqual(4, _machine->get_cycle_count()); +} + +// MARK: RTR + +- (void)testRTR { + _machine->set_program({ + 0x4e77 // RTR + }); + _machine->set_initial_stack_pointer(0x2000); + *_machine->ram_at(0x2000) = 0x7fff; + *_machine->ram_at(0x2002) = 0; + *_machine->ram_at(0x2004) = 0xc; + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.stack_pointer(), 0x2006); + XCTAssertEqual(state.program_counter, 0x10); + XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::ConditionCodes); + XCTAssertEqual(20, _machine->get_cycle_count()); +} + +// MARK: RTS + +- (void)testRTS { + _machine->set_program({ + 0x4e75 // RTS + }); + _machine->set_initial_stack_pointer(0x2000); + *_machine->ram_at(0x2000) = 0x0000; + *_machine->ram_at(0x2002) = 0x000c; + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.stack_pointer(), 0x2004); + XCTAssertEqual(state.program_counter, 0x000c + 4); + XCTAssertEqual(16, _machine->get_cycle_count()); + +} + +// MARK: TRAP + +- (void)testTrap { + _machine->set_program({ + 0x4e41 // TRAP #1 + }); + auto state = _machine->get_processor_state(); + state.status = 0x700; + state.user_stack_pointer = 0x200; + state.supervisor_stack_pointer = 0x206; + *_machine->ram_at(0x84) = 0xfffe; + *_machine->ram_at(0xfffe) = 0x4e71; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.status, 0x2700); + XCTAssertEqual(*_machine->ram_at(0x200), 0x700); + XCTAssertEqual(*_machine->ram_at(0x202), 0x0000); + XCTAssertEqual(*_machine->ram_at(0x204), 0x1002); + XCTAssertEqual(state.supervisor_stack_pointer, 0x200); +} + +// MARK: TRAPV + +- (void)testTRAPV_taken { + _machine->set_program({ + 0x4e76 // TRAPV + }); + _machine->set_initial_stack_pointer(0x206); + + auto state = _machine->get_processor_state(); + state.status = 0x702; + state.supervisor_stack_pointer = 0x206; + *_machine->ram_at(0x1e) = 0xfffe; + *_machine->ram_at(0xfffe) = 0x4e71; + + _machine->set_processor_state(state); + _machine->run_for_instructions(1); + + state = _machine->get_processor_state(); + XCTAssertEqual(state.status, 0x2702); + XCTAssertEqual(state.stack_pointer(), 0x200); + XCTAssertEqual(*_machine->ram_at(0x202), 0x0000); + XCTAssertEqual(*_machine->ram_at(0x204), 0x1002); + XCTAssertEqual(*_machine->ram_at(0x200), 0x702); + XCTAssertEqual(34, _machine->get_cycle_count()); +} + +- (void)testTRAPV_untaken { + _machine->set_program({ + 0x4e76 // TRAPV + }); + + _machine->run_for_instructions(1); + + const auto state = _machine->get_processor_state(); + XCTAssertEqual(state.program_counter, 0x1002 + 4); + XCTAssertEqual(4, _machine->get_cycle_count()); +} + +@end diff --git a/OSBindings/Mac/Clock SignalTests/68000Tests.mm b/OSBindings/Mac/Clock SignalTests/68000Tests.mm index 400247fbd..da0aa5119 100644 --- a/OSBindings/Mac/Clock SignalTests/68000Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000Tests.mm @@ -708,127 +708,6 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(16, _machine->get_cycle_count()); } -// MARK: BRA - -- (void)testBRAb { - _machine->set_program({ - 0x6004 // BRA.b +4 - }); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1006 + 4); - XCTAssertEqual(_machine->get_cycle_count(), 10); -} - -- (void)testBRAw { - _machine->set_program({ - 0x6000, 0x0004 // BRA.b +4 - }); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1006 + 4); - XCTAssertEqual(_machine->get_cycle_count(), 10); -} - -// MARK: BSR - -- (void)testBSRw { - _machine->set_program({ - 0x6100, 0x0006 // BSR.w $1008 - }); - _machine->set_initial_stack_pointer(0x3000); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1008 + 4); - XCTAssertEqual(state.stack_pointer(), 0x2ffc); - XCTAssertEqual(state.status & Flag::ConditionCodes, 0); - XCTAssertEqual(*_machine->ram_at(0x2ffc), 0); - XCTAssertEqual(*_machine->ram_at(0x2ffe), 0x1004); - - XCTAssertEqual(_machine->get_cycle_count(), 18); -} - -- (void)testBSRb { - _machine->set_program({ - 0x6106 // BSR.b $1008 - }); - _machine->set_initial_stack_pointer(0x3000); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1008 + 4); - XCTAssertEqual(state.stack_pointer(), 0x2ffc); - XCTAssertEqual(state.status & Flag::ConditionCodes, 0); - XCTAssertEqual(*_machine->ram_at(0x2ffc), 0); - XCTAssertEqual(*_machine->ram_at(0x2ffe), 0x1002); - - XCTAssertEqual(_machine->get_cycle_count(), 18); -} - -// MARK: CHK - -- (void)performCHKd1:(uint32_t)d1 d2:(uint32_t)d2 { - _machine->set_program({ - 0x4581 // CHK D1, D2 - }); - auto state = _machine->get_processor_state(); - state.data[1] = d1; - state.data[2] = d2; - state.status |= Flag::ConditionCodes; - - _machine->set_initial_stack_pointer(0); - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(state.data[1], d1); - XCTAssertEqual(state.data[2], d2); -} - -- (void)testCHK_1111v1111 { - [self performCHKd1:0x1111 d2:0x1111]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1002 + 4); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend); - XCTAssertEqual(10, _machine->get_cycle_count()); -} - -- (void)testCHK_1111v0000 { - [self performCHKd1:0x1111 d2:0x0000]; - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1002 + 4); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Zero); - XCTAssertEqual(10, _machine->get_cycle_count()); -} - -- (void)testCHK_8000v8001 { - [self performCHKd1:0x8000 d2:0x8001]; - - const auto state = _machine->get_processor_state(); - XCTAssertNotEqual(state.program_counter, 0x1002 + 4); - XCTAssertEqual(state.stack_pointer(), 0xfffffffa); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend); - XCTAssertEqual(42, _machine->get_cycle_count()); -} - -- (void)testCHK_8000v8000 { - [self performCHKd1:0x8000 d2:0x8000]; - - const auto state = _machine->get_processor_state(); - XCTAssertNotEqual(state.program_counter, 0x1002 + 4); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Negative); - XCTAssertEqual(44, _machine->get_cycle_count()); -} - // MARK: CLR - (void)testCLRw { @@ -903,187 +782,6 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(20, _machine->get_cycle_count()); } -// MARK: DBcc - -- (void)performDBccTestOpcode:(uint16_t)opcode status:(uint16_t)status d2Outcome:(uint32_t)d2Output { - _machine->set_program({ - opcode, 0x0008 // DBcc D2, +8 - }); - auto state = _machine->get_processor_state(); - state.status = status; - state.data[2] = 1; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(state.data[2], d2Output); - XCTAssertEqual(state.status, status); -} - -- (void)testDBT { - [self performDBccTestOpcode:0x50ca status:0 d2Outcome:1]; -} - -- (void)testDBF { - [self performDBccTestOpcode:0x51ca status:0 d2Outcome:0]; -} - -- (void)testDBHI { - [self performDBccTestOpcode:0x52ca status:0 d2Outcome:1]; -} - -- (void)testDBHI_Carry { - [self performDBccTestOpcode:0x52ca status:Flag::Carry d2Outcome:0]; -} - -- (void)testDBHI_Zero { - [self performDBccTestOpcode:0x52ca status:Flag::Zero d2Outcome:0]; -} - -- (void)testDBLS_CarryOverflow { - [self performDBccTestOpcode:0x53ca status:Flag::Carry | Flag::Overflow d2Outcome:1]; -} - -- (void)testDBLS_Carry { - [self performDBccTestOpcode:0x53ca status:Flag::Carry d2Outcome:1]; -} - -- (void)testDBLS_Overflow { - [self performDBccTestOpcode:0x53ca status:Flag::Overflow d2Outcome:0]; -} - -- (void)testDBCC_Carry { - [self performDBccTestOpcode:0x54ca status:Flag::Carry d2Outcome:0]; -} - -- (void)testDBCC { - [self performDBccTestOpcode:0x54ca status:0 d2Outcome:1]; -} - -- (void)testDBCS { - [self performDBccTestOpcode:0x55ca status:0 d2Outcome:0]; -} - -- (void)testDBCS_Carry { - [self performDBccTestOpcode:0x55ca status:Flag::Carry d2Outcome:1]; -} - -- (void)testDBNE { - [self performDBccTestOpcode:0x56ca status:0 d2Outcome:1]; -} - -- (void)testDBNE_Zero { - [self performDBccTestOpcode:0x56ca status:Flag::Zero d2Outcome:0]; -} - -- (void)testDBEQ { - [self performDBccTestOpcode:0x57ca status:0 d2Outcome:0]; -} - -- (void)testDBEQ_Zero { - [self performDBccTestOpcode:0x57ca status:Flag::Zero d2Outcome:1]; -} - -- (void)testDBVC { - [self performDBccTestOpcode:0x58ca status:0 d2Outcome:1]; -} - -- (void)testDBVC_Overflow { - [self performDBccTestOpcode:0x58ca status:Flag::Overflow d2Outcome:0]; -} - -- (void)testDBVS { - [self performDBccTestOpcode:0x59ca status:0 d2Outcome:0]; -} - -- (void)testDBVS_Overflow { - [self performDBccTestOpcode:0x59ca status:Flag::Overflow d2Outcome:1]; -} - -- (void)testDBPL { - [self performDBccTestOpcode:0x5aca status:0 d2Outcome:1]; -} - -- (void)testDBPL_Negative { - [self performDBccTestOpcode:0x5aca status:Flag::Negative d2Outcome:0]; -} - -- (void)testDBMI { - [self performDBccTestOpcode:0x5bca status:0 d2Outcome:0]; -} - -- (void)testDBMI_Negative { - [self performDBccTestOpcode:0x5bca status:Flag::Negative d2Outcome:1]; -} - -- (void)testDBGE_NegativeOverflow { - [self performDBccTestOpcode:0x5cca status:Flag::Negative | Flag::Overflow d2Outcome:1]; -} - -- (void)testDBGE { - [self performDBccTestOpcode:0x5cca status:0 d2Outcome:1]; -} - -- (void)testDBGE_Negative { - [self performDBccTestOpcode:0x5cca status:Flag::Negative d2Outcome:0]; -} - -- (void)testDBGE_Overflow { - [self performDBccTestOpcode:0x5cca status:Flag::Overflow d2Outcome:0]; -} - -- (void)testDBLT_NegativeOverflow { - [self performDBccTestOpcode:0x5dca status:Flag::Negative | Flag::Overflow d2Outcome:0]; -} - -- (void)testDBLT { - [self performDBccTestOpcode:0x5dca status:0 d2Outcome:0]; -} - -- (void)testDBLT_Negative { - [self performDBccTestOpcode:0x5dca status:Flag::Negative d2Outcome:1]; -} - -- (void)testDBLT_Overflow { - [self performDBccTestOpcode:0x5dca status:Flag::Overflow d2Outcome:1]; -} - -- (void)testDBGT { - [self performDBccTestOpcode:0x5eca status:0 d2Outcome:1]; -} - -- (void)testDBGT_ZeroNegativeOverflow { - [self performDBccTestOpcode:0x5eca status:Flag::Zero | Flag::Negative | Flag::Overflow d2Outcome:0]; -} - -- (void)testDBGT_NegativeOverflow { - [self performDBccTestOpcode:0x5eca status:Flag::Negative | Flag::Overflow d2Outcome:1]; -} - -- (void)testDBGT_Zero { - [self performDBccTestOpcode:0x5eca status:Flag::Zero d2Outcome:0]; -} - -- (void)testDBLE { - [self performDBccTestOpcode:0x5fca status:0 d2Outcome:0]; -} - -- (void)testDBLE_Zero { - [self performDBccTestOpcode:0x5fca status:Flag::Zero d2Outcome:1]; -} - -- (void)testDBLE_Negative { - [self performDBccTestOpcode:0x5fca status:Flag::Negative d2Outcome:1]; -} - -- (void)testDBLE_NegativeOverflow { - [self performDBccTestOpcode:0x5fca status:Flag::Negative | Flag::Overflow d2Outcome:0]; -} - -/* Further DBF tests omitted; they seemed to be duplicative, assuming I'm not suffering a failure of comprehension. */ - - // MARK: EXG - (void)testEXG_D1D2 { @@ -1200,71 +898,6 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Extend | Flag::Negative); } -// MARK: JMP - -- (void)testJMP_A1 { - _machine->set_program({ - 0x4ed1 // JMP (A1) - }); - - auto state = _machine->get_processor_state(); - state.address[1] = 0x3000; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(state.address[1], 0x3000); - XCTAssertEqual(state.program_counter, 0x3000 + 4); - XCTAssertEqual(8, _machine->get_cycle_count()); -} - -- (void)testJMP_PC { - _machine->set_program({ - 0x4efa, 0x000a // JMP PC+a (i.e. to 0x100c) - }); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x100c + 4); - XCTAssertEqual(10, _machine->get_cycle_count()); -} - -// MARK: JSR - -- (void)testJSR_PC { - _machine->set_program({ - 0x4eba, 0x000a // JSR (+a)PC ; JSR to $100c - }); - _machine->set_initial_stack_pointer(0x2000); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.stack_pointer(), 0x1ffc); - XCTAssertEqual(state.program_counter, 0x100c + 4); - XCTAssertEqual(*_machine->ram_at(0x1ffc), 0x0000); - XCTAssertEqual(*_machine->ram_at(0x1ffe), 0x1004); - XCTAssertEqual(18, _machine->get_cycle_count()); -} - -- (void)testJSR_XXXl { - _machine->set_program({ - 0x4eb9, 0x0000, 0x1008 // JSR ($1008).l - }); - _machine->set_initial_stack_pointer(0x2000); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.stack_pointer(), 0x1ffc); - XCTAssertEqual(state.program_counter, 0x1008 + 4); - XCTAssertEqual(*_machine->ram_at(0x1ffc), 0x0000); - XCTAssertEqual(*_machine->ram_at(0x1ffe), 0x1006); - XCTAssertEqual(20, _machine->get_cycle_count()); -} - // MARK: LEA - (void)testLEA_w { @@ -2343,16 +1976,6 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(state.address[1], 0); } -// MARK: NOP - -- (void)testNOP { - _machine->set_program({ - 0x4e71 // NOP - }); - _machine->run_for_instructions(1); - XCTAssertEqual(4, _machine->get_cycle_count()); -} - // MARK: PEA - (void)testPEA_A1 { @@ -2767,45 +2390,6 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(state.status & Flag::ConditionCodes, 0); } -// MARK: RTR - -- (void)testRTR { - _machine->set_program({ - 0x4e77 // RTR - }); - _machine->set_initial_stack_pointer(0x2000); - *_machine->ram_at(0x2000) = 0x7fff; - *_machine->ram_at(0x2002) = 0; - *_machine->ram_at(0x2004) = 0xc; - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.stack_pointer(), 0x2006); - XCTAssertEqual(state.program_counter, 0x10); - XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::ConditionCodes); - XCTAssertEqual(20, _machine->get_cycle_count()); -} - -// MARK: RTS - -- (void)testRTS { - _machine->set_program({ - 0x4e75 // RTS - }); - _machine->set_initial_stack_pointer(0x2000); - *_machine->ram_at(0x2000) = 0x0000; - *_machine->ram_at(0x2002) = 0x000c; - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.stack_pointer(), 0x2004); - XCTAssertEqual(state.program_counter, 0x000c + 4); - XCTAssertEqual(16, _machine->get_cycle_count()); - -} - // MARK: Scc - (void)testSFDn { @@ -2908,30 +2492,6 @@ class CPU::MC68000::ProcessorStorageTests { XCTAssertEqual(state.status & Flag::ConditionCodes, Flag::Negative); } -// MARK: TRAP - -- (void)testTrap { - _machine->set_program({ - 0x4e41 // TRAP #1 - }); - auto state = _machine->get_processor_state(); - state.status = 0x700; - state.user_stack_pointer = 0x200; - state.supervisor_stack_pointer = 0x206; - *_machine->ram_at(0x84) = 0xfffe; - *_machine->ram_at(0xfffe) = 0x4e71; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(state.status, 0x2700); - XCTAssertEqual(*_machine->ram_at(0x200), 0x700); - XCTAssertEqual(*_machine->ram_at(0x202), 0x0000); - XCTAssertEqual(*_machine->ram_at(0x204), 0x1002); - XCTAssertEqual(state.supervisor_stack_pointer, 0x200); -} - // MARK: TST - (void)testTSTw_Dn { @@ -2970,44 +2530,6 @@ class CPU::MC68000::ProcessorStorageTests { // Omitted: test that tst.w A0 doesn't decode. -// MARK: TRAPV - -- (void)testTRAPV_taken { - _machine->set_program({ - 0x4e76 // TRAPV - }); - _machine->set_initial_stack_pointer(0x206); - - auto state = _machine->get_processor_state(); - state.status = 0x702; - state.supervisor_stack_pointer = 0x206; - *_machine->ram_at(0x1e) = 0xfffe; - *_machine->ram_at(0xfffe) = 0x4e71; - - _machine->set_processor_state(state); - _machine->run_for_instructions(1); - - state = _machine->get_processor_state(); - XCTAssertEqual(state.status, 0x2702); - XCTAssertEqual(state.stack_pointer(), 0x200); - XCTAssertEqual(*_machine->ram_at(0x202), 0x0000); - XCTAssertEqual(*_machine->ram_at(0x204), 0x1002); - XCTAssertEqual(*_machine->ram_at(0x200), 0x702); - XCTAssertEqual(34, _machine->get_cycle_count()); -} - -- (void)testTRAPV_untaken { - _machine->set_program({ - 0x4e76 // TRAPV - }); - - _machine->run_for_instructions(1); - - const auto state = _machine->get_processor_state(); - XCTAssertEqual(state.program_counter, 0x1002 + 4); - XCTAssertEqual(4, _machine->get_cycle_count()); -} - // MARK: UNLINK - (void)testUNLINK_A6 {