1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Works 68000 mk2 into the comparative tests.

... revealing that I've leant a little too hard on __LINE__.
This commit is contained in:
Thomas Harte 2022-05-16 20:04:13 -04:00
parent 345f7c3c62
commit 3db2de7478
8 changed files with 81 additions and 44 deletions

View File

@ -13,6 +13,7 @@
#include "Instruction.hpp"
#include "Model.hpp"
#include "Perform.hpp"
#include "RegisterSet.hpp"
#include "Status.hpp"
namespace InstructionSet {
@ -80,17 +81,9 @@ template <Model model, typename BusHandler> class Executor {
/// Sets the current input interrupt level.
void set_interrupt_level(int);
// TODO: this will likely be shared in some capacity with the bus-accurate versions of the 680x0;
// therefore it will almost certainly be factored out in future.
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 &);
// State for the executor is just the register set.
RegisterSet get_state();
void set_state(const RegisterSet &);
private:
class State: public NullFlowController {

View File

@ -102,8 +102,8 @@ void Executor<model, BusHandler>::run_for_instructions(int count) {
}
template <Model model, typename BusHandler>
typename Executor<model, BusHandler>::Registers Executor<model, BusHandler>::get_state() {
Registers result;
RegisterSet Executor<model, BusHandler>::get_state() {
RegisterSet result;
for(int c = 0; c < 8; c++) {
result.data[c] = Dn(c).l;
@ -122,7 +122,7 @@ typename Executor<model, BusHandler>::Registers Executor<model, BusHandler>::get
}
template <Model model, typename BusHandler>
void Executor<model, BusHandler>::set_state(const Registers &state) {
void Executor<model, BusHandler>::set_state(const RegisterSet &state) {
for(int c = 0; c < 8; c++) {
Dn(c).l = state.data[c];
}

View File

@ -0,0 +1,26 @@
//
// RegisterSet.hpp
// Clock Signal
//
// Created by Thomas Harte on 16/05/2022.
// Copyright © 2022 Thomas Harte. All rights reserved.
//
#ifndef InstructionSets_M68k_RegisterSet_h
#define InstructionSets_M68k_RegisterSet_h
namespace InstructionSet {
namespace M68k {
struct RegisterSet {
uint32_t data[8], address[7];
uint32_t user_stack_pointer;
uint32_t supervisor_stack_pointer;
uint16_t status;
uint32_t program_counter;
};
}
}
#endif /* InstructionSets_M68k_RegisterSet_h */

View File

@ -1676,6 +1676,7 @@
4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZX8081.cpp; sourceTree = "<group>"; };
4BA0F68D1EEA0E8400E9489E /* ZX8081.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ZX8081.hpp; sourceTree = "<group>"; };
4BA141C12073100800A31EC9 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BA3AE44283317CB00328FED /* RegisterSet.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RegisterSet.hpp; sourceTree = "<group>"; };
4BA61EAE1D91515900B3C876 /* NSData+StdVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+StdVector.h"; sourceTree = "<group>"; };
4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSData+StdVector.mm"; sourceTree = "<group>"; };
4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MasterSystemVDPTests.mm; sourceTree = "<group>"; };
@ -3215,6 +3216,7 @@
4B79629C2819681F008130F9 /* Instruction.hpp */,
4B79629D2819681F008130F9 /* Model.hpp */,
4BB5B996281B1E3F00522DA9 /* Perform.hpp */,
4BA3AE44283317CB00328FED /* RegisterSet.hpp */,
4BB5B997281B1F7B00522DA9 /* Status.hpp */,
4BB5B999281B244400522DA9 /* Implementation */,
);

View File

@ -8,7 +8,7 @@
#import <XCTest/XCTest.h>
#include "../../../Processors/68000/68000.hpp"
#include "../../../Processors/68000Mk2/68000Mk2.hpp"
#include "../../../InstructionSets/M68k/Executor.hpp"
#include "../../../InstructionSets/M68k/Decoder.hpp"
@ -16,7 +16,7 @@
#include <memory>
#include <functional>
//#define USE_EXISTING_IMPLEMENTATION
//#define USE_EXECUTOR
//#define MAKE_SUGGESTIONS
namespace {
@ -168,10 +168,10 @@ struct Test68000 {
// Compare against a test set if one has been supplied.
if(_testSet && ![_testSet containsObject:name]) continue;
#ifdef USE_EXISTING_IMPLEMENTATION
[self testOperationClassic:test name:name];
#else
#ifdef USE_EXECUTOR
[self testOperationExecutor:test name:name];
#else
[self testOperationClassic:test name:name];
#endif
}
}
@ -179,21 +179,20 @@ struct Test68000 {
- (void)testOperationClassic:(NSDictionary *)test name:(NSString *)name {
// This is the test class for 68000 execution.
struct Test68000: public CPU::MC68000::BusHandler {
struct Test68000: public CPU::MC68000Mk2::BusHandler {
std::array<uint8_t, 16*1024*1024> ram;
CPU::MC68000::Processor<Test68000, true, true> processor;
CPU::MC68000Mk2::Processor<Test68000> processor;
std::function<void(void)> comparitor;
Test68000() : processor(*this) {
}
Test68000() : processor(*this) {}
void will_perform(uint32_t, uint16_t) {
--instructions_remaining_;
if(!instructions_remaining_) comparitor();
}
HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int) {
using Microcycle = CPU::MC68000::Microcycle;
HalfCycles perform_bus_operation(const CPU::MC68000Mk2::Microcycle &cycle, int) {
using Microcycle = CPU::MC68000Mk2::Microcycle;
if(cycle.data_select_active()) {
cycle.apply(&ram[cycle.host_endian_byte_address()]);
}
@ -234,13 +233,13 @@ struct Test68000 {
const NSString *dX = [@"d" stringByAppendingFormat:@"%d", c];
const NSString *aX = [@"a" stringByAppendingFormat:@"%d", c];
state.data[c] = uint32_t([initialState[dX] integerValue]);
state.registers.data[c] = uint32_t([initialState[dX] integerValue]);
if(c < 7)
state.address[c] = uint32_t([initialState[aX] integerValue]);
state.registers.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.registers.supervisor_stack_pointer = uint32_t([initialState[@"a7"] integerValue]);
state.registers.user_stack_pointer = uint32_t([initialState[@"usp"] integerValue]);
state.registers.status = [initialState[@"sr"] integerValue];
test68000->processor.set_state(state);
}
@ -253,22 +252,22 @@ struct Test68000 {
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];
if(state.registers.data[c] != [finalState[dX] integerValue]) [_failures addObject:name];
if(c < 7 && state.registers.address[c] != [finalState[aX] integerValue]) [_failures addObject:name];
XCTAssertEqual(state.data[c], [finalState[dX] integerValue], @"%@: D%d inconsistent", name, c);
XCTAssertEqual(state.registers.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);
XCTAssertEqual(state.registers.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];
if(state.registers.supervisor_stack_pointer != [finalState[@"a7"] integerValue]) [_failures addObject:name];
if(state.registers.user_stack_pointer != [finalState[@"usp"] integerValue]) [_failures addObject:name];
if(state.registers.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);
XCTAssertEqual(state.registers.supervisor_stack_pointer, [finalState[@"a7"] integerValue], @"%@: A7 inconsistent", name);
XCTAssertEqual(state.registers.user_stack_pointer, [finalState[@"usp"] integerValue], @"%@: USP inconsistent", name);
XCTAssertEqual(state.registers.status, [finalState[@"sr"] integerValue], @"%@: Status inconsistent", name);
XCTAssertEqual(state.registers.program_counter - 4, [finalState[@"pc"] integerValue], @"%@: Program counter inconsistent", name);
// Test final memory state.
NSArray<NSNumber *> *const finalMemory = test[@"final memory"];

View File

@ -11,6 +11,7 @@
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../Numeric/RegisterSizes.hpp"
#include "../../InstructionSets/M68k/RegisterSet.hpp"
#include "Implementation/68000Mk2Storage.hpp"
@ -356,12 +357,19 @@ class BusHandler {
void will_perform([[maybe_unused]] uint32_t address, [[maybe_unused]] uint16_t opcode) {}
};
struct State {
InstructionSet::M68k::RegisterSet registers;
};
template <class BusHandler, bool dtack_is_implicit = true, bool permit_overrun = true, bool signal_will_perform = false> class Processor: private ProcessorBase {
public:
Processor(BusHandler &bus_handler) : ProcessorBase(), bus_handler_(bus_handler) {}
void run_for(HalfCycles duration);
CPU::MC68000Mk2::State get_state();
void set_state(const CPU::MC68000Mk2::State &);
private:
BusHandler &bus_handler_;
};

View File

@ -160,8 +160,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
case State::Reset:
IdleBus(7); // (n-)*5 nn
address = 0; ReadDataWord(address, stack_pointers_[7].high); // nF
address += 2; ReadDataWord(address, stack_pointers_[7].low); // nf
address = 0; ReadDataWord(address, registers_[15].high); // nF
address += 2; ReadDataWord(address, registers_[15].low); // nf
address += 2; ReadDataWord(address, program_counter_.high); // nV
address += 2; ReadDataWord(address, program_counter_.low); // nv
@ -182,6 +182,15 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
}
template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>
CPU::MC68000Mk2::State Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::get_state() {
return CPU::MC68000Mk2::State();
}
template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>
void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::set_state(const CPU::MC68000Mk2::State &) {
}
}
}

View File

@ -21,9 +21,9 @@ struct ProcessorBase {
Dispatch = -2,
WaitForDTACK = -3,
};
int state_ = State::Reset;
HalfCycles time_remaining_;
int state_ = State::Reset;
int post_dtack_state_ = 0;
int is_supervisor_ = 1;