From 3827ecd6d3388768b9cf4cef70a95570a0473fae Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 2 May 2022 12:57:45 -0400 Subject: [PATCH] Proceed to complete test running. --- InstructionSets/M68k/Executor.cpp | 10 --- InstructionSets/M68k/Executor.hpp | 11 +++ .../Implementation/ExecutorImplementation.hpp | 40 +++++++++- .../Implementation/PerformImplementation.hpp | 12 +-- .../Clock Signal.xcodeproj/project.pbxproj | 6 -- .../68000ComparativeTests.mm | 79 ++++++++++--------- 6 files changed, 96 insertions(+), 62 deletions(-) delete mode 100644 InstructionSets/M68k/Executor.cpp diff --git a/InstructionSets/M68k/Executor.cpp b/InstructionSets/M68k/Executor.cpp deleted file mode 100644 index 6c15fd977..000000000 --- a/InstructionSets/M68k/Executor.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// Executor.cpp -// Clock Signal -// -// Created by Thomas Harte on 29/04/2022. -// Copyright © 2022 Thomas Harte. All rights reserved. -// - -#include "Executor.hpp" - diff --git a/InstructionSets/M68k/Executor.hpp b/InstructionSets/M68k/Executor.hpp index c6e2ef73e..9762540d6 100644 --- a/InstructionSets/M68k/Executor.hpp +++ b/InstructionSets/M68k/Executor.hpp @@ -46,6 +46,17 @@ template class Executor { void add_pc(uint32_t); void decline_branch(); + // TODO: ownership of this shouldn't be here. + struct Registers { + uint32_t data[8], address[7]; + uint32_t user_stack_pointer; + uint32_t supervisor_stack_pointer; + uint16_t status; + uint32_t program_counter; + }; + Registers get_state(); + void set_state(const Registers &); + private: BusHandler &bus_handler_; Predecoder decoder_; diff --git a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp index 61e895c9a..6a4ef7e97 100644 --- a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp +++ b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp @@ -201,7 +201,6 @@ void Executor::run_for_instructions(int count) { instruction_address_ = program_counter_.l; const auto opcode = read_pc(); const Preinstruction instruction = decoder_.decode(opcode); - program_counter_.l += 2; // TODO: check privilege level. @@ -277,6 +276,45 @@ void Executor::run_for_instructions(int count) { } } +// MARK: - State + +template +typename Executor::Registers Executor::get_state() { + Registers result; + + for(int c = 0; c < 8; c++) { + result.data[c] = data_[c].l; + } + for(int c = 0; c < 7; c++) { + result.address[c] = address_[c].l; + } + result.status = status_.status(); + result.program_counter = program_counter_.l; + + stack_pointers_[status_.is_supervisor_] = address_[7]; + result.user_stack_pointer = stack_pointers_[0].l; + result.supervisor_stack_pointer = stack_pointers_[1].l; + + return result; +} + +template +void Executor::set_state(const Registers &state) { + for(int c = 0; c < 8; c++) { + data_[c].l = state.data[c]; + } + for(int c = 0; c < 7; c++) { + address_[c].l = state.address[c]; + } + status_.set_status(state.status); + program_counter_.l = state.program_counter; + + stack_pointers_[0].l = state.user_stack_pointer; + stack_pointers_[1].l = state.supervisor_stack_pointer; + address_[7] = stack_pointers_[status_.is_supervisor_]; +} + +// MARK: - Flow Control. // TODO: flow control, all below here. template diff --git a/InstructionSets/M68k/Implementation/PerformImplementation.hpp b/InstructionSets/M68k/Implementation/PerformImplementation.hpp index 8af76d549..a51e2d2a0 100644 --- a/InstructionSets/M68k/Implementation/PerformImplementation.hpp +++ b/InstructionSets/M68k/Implementation/PerformImplementation.hpp @@ -868,7 +868,7 @@ template < status.overflow_flag_ = status.carry_flag_ = 0; break; -#define sbcd() \ +#define sbcd(d) \ /* Perform the BCD arithmetic by evaluating the two nibbles separately. */ \ const int unadjusted_result = destination - source - (status.extend_flag_ ? 1 : 0); \ int result = (destination & 0xf) - (source & 0xf) - (status.extend_flag_ ? 1 : 0); \ @@ -883,7 +883,7 @@ template < status.overflow_flag_ = unadjusted_result & ~result & 0x80; \ \ /* Store the result. */ \ - dest.b = uint8_t(result); + d = uint8_t(result); /* SBCD subtracts the lowest byte of the source from that of the destination using @@ -892,17 +892,17 @@ template < case Operation::SBCD: { const uint8_t source = src.b; const uint8_t destination = dest.b; - sbcd(); + sbcd(dest.b); } break; /* - NBCD is like SBCD except that the result is 0 - destination rather than + NBCD is like SBCD except that the result is 0 - source rather than destination - source. */ case Operation::NBCD: { - const uint8_t source = dest.b; + const uint8_t source = src.b; const uint8_t destination = 0; - sbcd(); + sbcd(src.b); } break; #undef sbcd diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 9ae760f2b..65f92b403 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -894,8 +894,6 @@ 4BB4BFB022A42F290069048D /* MacintoshIMG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFAE22A42F290069048D /* MacintoshIMG.cpp */; }; 4BB4BFB922A4372F0069048D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */; }; 4BB4BFBA22A4372F0069048D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4BFB822A4372E0069048D /* StaticAnalyser.cpp */; }; - 4BB5B99D281C814E00522DA9 /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB5B99B281C805300522DA9 /* Executor.cpp */; }; - 4BB5B99E281C814F00522DA9 /* Executor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB5B99B281C805300522DA9 /* Executor.cpp */; }; 4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */; }; 4BB697CE1D4BA44400248BDF /* CommodoreGCR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB697CC1D4BA44400248BDF /* CommodoreGCR.cpp */; }; 4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EA11B587A5100552FC2 /* AppDelegate.swift */; }; @@ -1941,7 +1939,6 @@ 4BB5B996281B1E3F00522DA9 /* Perform.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Perform.hpp; sourceTree = ""; }; 4BB5B997281B1F7B00522DA9 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = ""; }; 4BB5B99A281B244400522DA9 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = ""; }; - 4BB5B99B281C805300522DA9 /* Executor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Executor.cpp; sourceTree = ""; }; 4BB5B99C281C805300522DA9 /* Executor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Executor.hpp; sourceTree = ""; }; 4BB5B99F281F121200522DA9 /* ExecutorImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ExecutorImplementation.hpp; sourceTree = ""; }; 4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = ""; }; @@ -3170,7 +3167,6 @@ isa = PBXGroup; children = ( 4B79629F2819681F008130F9 /* Decoder.cpp */, - 4BB5B99B281C805300522DA9 /* Executor.cpp */, 4B7962A4281C2EE3008130F9 /* Sequence.cpp */, 4B79629E2819681F008130F9 /* Decoder.hpp */, 4BB5B99C281C805300522DA9 /* Executor.hpp */, @@ -5466,7 +5462,6 @@ 4B1B88C1202E3DB200B67DFF /* MultiConfigurable.cpp in Sources */, 4B055AA31FAE85DF0060FFFF /* ImplicitSectors.cpp in Sources */, 4B8318B322D3E540006DB630 /* Audio.cpp in Sources */, - 4BB5B99E281C814F00522DA9 /* Executor.cpp in Sources */, 4B055AAE1FAE85FD0060FFFF /* TrackSerialiser.cpp in Sources */, 4B89452B201967B4007DE474 /* File.cpp in Sources */, 4B6AAEAC230E40250078E864 /* SCSI.cpp in Sources */, @@ -5717,7 +5712,6 @@ 4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */, 4B7BA03723CEB86000B98D9E /* BD500.cpp in Sources */, 4B38F3481F2EC11D00D9235D /* AmstradCPC.cpp in Sources */, - 4BB5B99D281C814E00522DA9 /* Executor.cpp in Sources */, 4B8FE2221DA19FB20090D3CE /* MachineController.swift in Sources */, 4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */, 4B4B1A3C200198CA00A0F866 /* KonamiSCC.cpp in Sources */, diff --git a/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm b/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm index 08a3ea9cd..b57921542 100644 --- a/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm @@ -274,24 +274,25 @@ NSNumber *const value = [enumerator nextObject]; if(!address || !value) break; - test68000->ram[address.integerValue ^ 1] = value.integerValue; // Effect a short-resolution endianness swap. + test68000->ram[address.integerValue] = value.integerValue; } // Apply initial processor state. -// NSDictionary *const initialState = test[@"initial state"]; -// auto state = test68000->processor.get_state(); -// for(int c = 0; c < 8; ++c) { -// const NSString *dX = [@"d" stringByAppendingFormat:@"%d", c]; -// const NSString *aX = [@"a" stringByAppendingFormat:@"%d", c]; -// -// state.data[c] = uint32_t([initialState[dX] integerValue]); -// if(c < 7) -// state.address[c] = uint32_t([initialState[aX] integerValue]); -// } -// state.supervisor_stack_pointer = uint32_t([initialState[@"a7"] integerValue]); -// state.user_stack_pointer = uint32_t([initialState[@"usp"] integerValue]); -// state.status = [initialState[@"sr"] integerValue]; -// test68000->processor.set_state(state); + NSDictionary *const initialState = test[@"initial state"]; + auto state = test68000->processor.get_state(); + for(int c = 0; c < 8; ++c) { + const NSString *dX = [@"d" stringByAppendingFormat:@"%d", c]; + const NSString *aX = [@"a" stringByAppendingFormat:@"%d", c]; + + state.data[c] = uint32_t([initialState[dX] integerValue]); + if(c < 7) + state.address[c] = uint32_t([initialState[aX] integerValue]); + } + state.supervisor_stack_pointer = uint32_t([initialState[@"a7"] integerValue]); + state.user_stack_pointer = uint32_t([initialState[@"usp"] integerValue]); + state.status = [initialState[@"sr"] integerValue]; + state.program_counter = uint32_t([initialState[@"pc"] integerValue]); + test68000->processor.set_state(state); } // Run the thing. @@ -299,27 +300,27 @@ // Test the end state. NSDictionary *const finalState = test[@"final state"]; -// const auto state = test68000->processor.get_state(); -// for(int c = 0; c < 8; ++c) { -// const NSString *dX = [@"d" stringByAppendingFormat:@"%d", c]; -// const NSString *aX = [@"a" stringByAppendingFormat:@"%d", c]; -// -// if(state.data[c] != [finalState[dX] integerValue]) [_failures addObject:name]; -// if(c < 7 && state.address[c] != [finalState[aX] integerValue]) [_failures addObject:name]; -// -// XCTAssertEqual(state.data[c], [finalState[dX] integerValue], @"%@: D%d inconsistent", name, c); -// if(c < 7) { -// XCTAssertEqual(state.address[c], [finalState[aX] integerValue], @"%@: A%d inconsistent", name, c); -// } -// } -// if(state.supervisor_stack_pointer != [finalState[@"a7"] integerValue]) [_failures addObject:name]; -// if(state.user_stack_pointer != [finalState[@"usp"] integerValue]) [_failures addObject:name]; -// if(state.status != [finalState[@"sr"] integerValue]) [_failures addObject:name]; -// -// XCTAssertEqual(state.supervisor_stack_pointer, [finalState[@"a7"] integerValue], @"%@: A7 inconsistent", name); -// XCTAssertEqual(state.user_stack_pointer, [finalState[@"usp"] integerValue], @"%@: USP inconsistent", name); -// XCTAssertEqual(state.status, [finalState[@"sr"] integerValue], @"%@: Status inconsistent", name); -// XCTAssertEqual(state.program_counter - 4, [finalState[@"pc"] integerValue], @"%@: Program counter inconsistent", name); + const auto state = test68000->processor.get_state(); + for(int c = 0; c < 8; ++c) { + const NSString *dX = [@"d" stringByAppendingFormat:@"%d", c]; + const NSString *aX = [@"a" stringByAppendingFormat:@"%d", c]; + + if(state.data[c] != [finalState[dX] integerValue]) [_failures addObject:name]; + if(c < 7 && state.address[c] != [finalState[aX] integerValue]) [_failures addObject:name]; + + XCTAssertEqual(state.data[c], [finalState[dX] integerValue], @"%@: D%d inconsistent", name, c); + if(c < 7) { + XCTAssertEqual(state.address[c], [finalState[aX] integerValue], @"%@: A%d inconsistent", name, c); + } + } + if(state.supervisor_stack_pointer != [finalState[@"a7"] integerValue]) [_failures addObject:name]; + if(state.user_stack_pointer != [finalState[@"usp"] integerValue]) [_failures addObject:name]; + if(state.status != [finalState[@"sr"] integerValue]) [_failures addObject:name]; + + XCTAssertEqual(state.supervisor_stack_pointer, [finalState[@"a7"] integerValue], @"%@: A7 inconsistent", name); + XCTAssertEqual(state.user_stack_pointer, [finalState[@"usp"] integerValue], @"%@: USP inconsistent", name); + XCTAssertEqual(state.status, [finalState[@"sr"] integerValue], @"%@: Status inconsistent", name); + XCTAssertEqual(state.program_counter, [finalState[@"pc"] integerValue], @"%@: Program counter inconsistent", name); // Test final memory state. NSArray *const finalMemory = test[@"final memory"]; @@ -329,13 +330,13 @@ NSNumber *const value = [enumerator nextObject]; if(!address || !value) break; - XCTAssertEqual(test68000->ram[address.integerValue ^ 1], value.integerValue, @"%@: Memory at location %@ inconsistent", name, address); - if(test68000->ram[address.integerValue ^ 1] != value.integerValue) [_failures addObject:name]; + XCTAssertEqual(test68000->ram[address.integerValue], value.integerValue, @"%@: Memory at location %@ inconsistent", name, address); + if(test68000->ram[address.integerValue] != value.integerValue) [_failures addObject:name]; } // Consider collating extra detail. if([_failures containsObject:name]) { - [_failingOpcodes addObject:@((test68000->ram[0x101] << 8) | test68000->ram[0x100])]; + [_failingOpcodes addObject:@((test68000->ram[0x100] << 8) | test68000->ram[0x101])]; } }