mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Factors out the [unit testing] stuff of being a trace-checking 68000 bus handler.
This commit is contained in:
parent
407643c575
commit
c466b6f9e7
@ -963,6 +963,7 @@
|
||||
4B83348E1F5DBA6E0097E338 /* 6522Storage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = 6522Storage.hpp; path = Implementation/6522Storage.hpp; sourceTree = "<group>"; };
|
||||
4B8334911F5E24FF0097E338 /* C1540Base.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = C1540Base.hpp; path = Implementation/C1540Base.hpp; sourceTree = "<group>"; };
|
||||
4B8334941F5E25B60097E338 /* C1540.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = C1540.cpp; path = Implementation/C1540.cpp; sourceTree = "<group>"; };
|
||||
4B85322922778E4200F26553 /* Comparative68000.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Comparative68000.hpp; sourceTree = "<group>"; };
|
||||
4B86E2591F8C628F006FAA45 /* Keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Keyboard.cpp; sourceTree = "<group>"; };
|
||||
4B86E25A1F8C628F006FAA45 /* Keyboard.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = "<group>"; };
|
||||
4B8805EE1DCFC99C003085B1 /* Acorn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acorn.cpp; path = Parsers/Acorn.cpp; sourceTree = "<group>"; };
|
||||
@ -2842,6 +2843,7 @@
|
||||
4BB73EB51B587A5100552FC2 /* Clock SignalTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B85322922778E4200F26553 /* Comparative68000.hpp */,
|
||||
4BD388872239E198002D14B5 /* 68000Tests.mm */,
|
||||
4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */,
|
||||
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */,
|
||||
|
59
OSBindings/Mac/Clock SignalTests/Comparative68000.hpp
Normal file
59
OSBindings/Mac/Clock SignalTests/Comparative68000.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// Comparative68000.hpp
|
||||
// Clock SignalTests
|
||||
//
|
||||
// Created by Thomas Harte on 29/04/2019.
|
||||
// Copyright © 2019 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Comparative68000_hpp
|
||||
#define Comparative68000_hpp
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "68000.hpp"
|
||||
|
||||
class ComparativeBusHandler: public CPU::MC68000::BusHandler {
|
||||
public:
|
||||
ComparativeBusHandler(const char *trace_name) {
|
||||
trace = gzopen(trace_name, "rt");
|
||||
}
|
||||
|
||||
~ComparativeBusHandler() {
|
||||
gzclose(trace);
|
||||
}
|
||||
|
||||
void will_perform(uint32_t address, uint16_t opcode) {
|
||||
// Obtain the next line from the trace file.
|
||||
char correct_state[300] = "\n";
|
||||
gzgets(trace, correct_state, sizeof(correct_state));
|
||||
++line_count;
|
||||
|
||||
// Generate state locally.
|
||||
const auto state = get_state();
|
||||
char local_state[300];
|
||||
sprintf(local_state, "%04x: %02x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
|
||||
address,
|
||||
state.status,
|
||||
state.data[0], state.data[1], state.data[2], state.data[3], state.data[4], state.data[5], state.data[6], state.data[7],
|
||||
state.address[0], state.address[1], state.address[2], state.address[3], state.address[4], state.address[5], state.address[6],
|
||||
(state.status & 0x2000) ? state.supervisor_stack_pointer : state.user_stack_pointer
|
||||
);
|
||||
|
||||
// Check that the two coincide.
|
||||
if(strcmp(correct_state, local_state)) {
|
||||
fprintf(stderr, "Diverges at line %d\n", line_count);
|
||||
fprintf(stderr, "Good: %s\n", correct_state);
|
||||
fprintf(stderr, "Bad: %s\n", local_state);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
virtual CPU::MC68000::ProcessorState get_state() = 0;
|
||||
|
||||
private:
|
||||
int line_count = 0;
|
||||
gzFile trace;
|
||||
};
|
||||
|
||||
#endif /* Comparative68000_hpp */
|
@ -17,53 +17,26 @@
|
||||
#include <zlib.h>
|
||||
|
||||
#include "68000.hpp"
|
||||
#include "Comparative68000.hpp"
|
||||
#include "CSROMFetcher.hpp"
|
||||
|
||||
class QL: public CPU::MC68000::BusHandler {
|
||||
class QL: public ComparativeBusHandler {
|
||||
public:
|
||||
QL(const std::vector<uint8_t> &rom, const char *trace_name) : m68000_(*this) {
|
||||
QL(const std::vector<uint8_t> &rom, const char *trace_name) : ComparativeBusHandler(trace_name), m68000_(*this) {
|
||||
assert(!(rom.size() & 1));
|
||||
rom_.resize(rom.size() / 2);
|
||||
|
||||
for(size_t c = 0; c < rom_.size(); ++c) {
|
||||
rom_[c] = (rom[c << 1] << 8) | rom[(c << 1) + 1];
|
||||
}
|
||||
|
||||
trace = gzopen(trace_name, "rt");
|
||||
}
|
||||
|
||||
~QL() {
|
||||
gzclose(trace);
|
||||
}
|
||||
|
||||
void run_for(HalfCycles cycles) {
|
||||
m68000_.run_for(cycles);
|
||||
}
|
||||
|
||||
void will_perform(uint32_t address, uint16_t opcode) {
|
||||
// Obtain the next line from the trace file.
|
||||
char correct_state[300] = "\n";
|
||||
gzgets(trace, correct_state, sizeof(correct_state));
|
||||
++line_count;
|
||||
|
||||
// Generate state locally.
|
||||
const auto state = m68000_.get_state();
|
||||
char local_state[300];
|
||||
sprintf(local_state, "%04x: %02x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
|
||||
address,
|
||||
state.status,
|
||||
state.data[0], state.data[1], state.data[2], state.data[3], state.data[4], state.data[5], state.data[6], state.data[7],
|
||||
state.address[0], state.address[1], state.address[2], state.address[3], state.address[4], state.address[5], state.address[6],
|
||||
(state.status & 0x2000) ? state.supervisor_stack_pointer : state.user_stack_pointer
|
||||
);
|
||||
|
||||
// Check that the two coincide.
|
||||
if(strcmp(correct_state, local_state)) {
|
||||
fprintf(stderr, "Diverges at line %d\n", line_count);
|
||||
fprintf(stderr, "Good: %s\n", correct_state);
|
||||
fprintf(stderr, "Bad: %s\n", local_state);
|
||||
assert(false);
|
||||
}
|
||||
CPU::MC68000::ProcessorState get_state() override {
|
||||
return m68000_.get_state();
|
||||
}
|
||||
|
||||
HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int is_supervisor) {
|
||||
@ -115,9 +88,6 @@ class QL: public CPU::MC68000::BusHandler {
|
||||
|
||||
std::vector<uint16_t> rom_;
|
||||
std::array<uint16_t, 64*1024> ram_;
|
||||
|
||||
int line_count = 0;
|
||||
gzFile trace;
|
||||
};
|
||||
|
||||
@interface QLTests : XCTestCase
|
||||
|
@ -149,10 +149,10 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> void Proces
|
||||
active_micro_op_ = active_program_->micro_operations;
|
||||
} else {
|
||||
active_program_ = nullptr;
|
||||
active_micro_op_ = exception_micro_ops_; // TODO.
|
||||
active_micro_op_ = exception_micro_ops_;
|
||||
|
||||
// The vector used dependds on whether this is a vanilla unrecognised instruction, or
|
||||
// one on the A or F lines.
|
||||
// The vector used depends on whether this is a vanilla unrecognised instruction,
|
||||
// or one on the A or F lines.
|
||||
switch(decoded_instruction_ >> 12) {
|
||||
default: populate_trap_steps(get_status(), 4); break;
|
||||
case 0xa: populate_trap_steps(get_status(), 10); break;
|
||||
|
@ -3497,6 +3497,11 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
|
||||
// Target addresses and values will be filled in by TRAP/illegal too.
|
||||
const size_t trap_offset = constructor.assemble_program("r nw nw nW nV nv np np", { &precomputed_addresses_[0], &precomputed_addresses_[1], &precomputed_addresses_[2] });
|
||||
|
||||
// Chuck in the proper micro-ops for handling an exception.
|
||||
const auto exception_offset = all_micro_ops_.size();
|
||||
all_micro_ops_.emplace_back(ProcessorBase::MicroOp::Action::None);
|
||||
all_micro_ops_.emplace_back();
|
||||
|
||||
// Install operations.
|
||||
constructor.install_instructions();
|
||||
|
||||
@ -3535,6 +3540,10 @@ CPU::MC68000::ProcessorStorage::ProcessorStorage() {
|
||||
steps[4].microcycle.value = steps[5].microcycle.value = &program_counter_.halves.low;
|
||||
}
|
||||
|
||||
// Complete linkage of the exception micro program.
|
||||
exception_micro_ops_ = &all_micro_ops_[exception_offset];
|
||||
exception_micro_ops_->bus_program = trap_steps_;
|
||||
|
||||
// Set initial state.
|
||||
active_step_ = reset_bus_steps_;
|
||||
effective_address_[0] = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user