1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-03-25 06:30:38 +00:00

Proceed to complete test running.

This commit is contained in:
Thomas Harte 2022-05-02 12:57:45 -04:00
parent fa49737538
commit 3827ecd6d3
6 changed files with 96 additions and 62 deletions
InstructionSets/M68k
OSBindings/Mac
Clock Signal.xcodeproj
Clock SignalTests

@ -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"

@ -46,6 +46,17 @@ template <Model model, typename BusHandler> 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<model> decoder_;

@ -201,7 +201,6 @@ void Executor<model, BusHandler>::run_for_instructions(int count) {
instruction_address_ = program_counter_.l;
const auto opcode = read_pc<uint16_t>();
const Preinstruction instruction = decoder_.decode(opcode);
program_counter_.l += 2;
// TODO: check privilege level.
@ -277,6 +276,45 @@ void Executor<model, BusHandler>::run_for_instructions(int count) {
}
}
// MARK: - State
template <Model model, typename BusHandler>
typename Executor<model, BusHandler>::Registers Executor<model, BusHandler>::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 <Model model, typename BusHandler>
void Executor<model, BusHandler>::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 <Model model, typename BusHandler>

@ -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

@ -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 = "<group>"; };
4BB5B997281B1F7B00522DA9 /* Status.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Status.hpp; sourceTree = "<group>"; };
4BB5B99A281B244400522DA9 /* PerformImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PerformImplementation.hpp; sourceTree = "<group>"; };
4BB5B99B281C805300522DA9 /* Executor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Executor.cpp; sourceTree = "<group>"; };
4BB5B99C281C805300522DA9 /* Executor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Executor.hpp; sourceTree = "<group>"; };
4BB5B99F281F121200522DA9 /* ExecutorImplementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ExecutorImplementation.hpp; sourceTree = "<group>"; };
4BB697C91D4B6D3E00248BDF /* TimedEventLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimedEventLoop.cpp; sourceTree = "<group>"; };
@ -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 */,

@ -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<NSNumber *> *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])];
}
}