mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Introduces failing test of 68000 opcode coverage.
This commit is contained in:
parent
7cbd5e0ef6
commit
3983f8303f
@ -308,6 +308,7 @@
|
||||
4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
|
||||
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 */; };
|
||||
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; };
|
||||
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */; };
|
||||
4BA91E1D216D85BA00F79557 /* MasterSystemVDPTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */; };
|
||||
@ -1040,6 +1041,7 @@
|
||||
4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiSpeaker.cpp; sourceTree = "<group>"; };
|
||||
4B9BE3FF203A0C0600FFAE60 /* MultiSpeaker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiSpeaker.hpp; sourceTree = "<group>"; };
|
||||
4B9F11C82272375400701480 /* qltrace.txt.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = qltrace.txt.gz; sourceTree = "<group>"; };
|
||||
4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = OPCLOGR2.BIN; path = "68000 Coverage/OPCLOGR2.BIN"; sourceTree = "<group>"; };
|
||||
4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZX8081.cpp; path = Data/ZX8081.cpp; sourceTree = "<group>"; };
|
||||
4BA0F68D1EEA0E8400E9489E /* ZX8081.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ZX8081.hpp; path = Data/ZX8081.hpp; sourceTree = "<group>"; };
|
||||
4BA141C12073100800A31EC9 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
|
||||
@ -1570,6 +1572,7 @@
|
||||
4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */,
|
||||
4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */,
|
||||
4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */,
|
||||
4B9F11CB22729B3500701480 /* OPCLOGR2.BIN */,
|
||||
4BBF49B41ED2881600AB3669 /* FUSE */,
|
||||
4B9F11C72272375400701480 /* QL Startup */,
|
||||
4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */,
|
||||
@ -3528,6 +3531,7 @@
|
||||
4BB2997D1B587D8400A49093 /* ldxay in Resources */,
|
||||
4BB299D71B587D8400A49093 /* staax in Resources */,
|
||||
4B98A1CE1FFADEC500ADF63B /* MSX ROMs in Resources */,
|
||||
4B9F11CC22729B3600701480 /* OPCLOGR2.BIN in Resources */,
|
||||
4BB2990C1B587D8400A49093 /* asoax in Resources */,
|
||||
4BB299191B587D8400A49093 /* bita in Resources */,
|
||||
4BB2992A1B587D8400A49093 /* cia2ta in Resources */,
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
|
||||
#include "68000.hpp"
|
||||
|
||||
@ -72,11 +73,88 @@ class RAM68000: public CPU::MC68000::BusHandler {
|
||||
m68000_.set_state(state);
|
||||
}
|
||||
|
||||
const CPU::MC68000::Processor<RAM68000, true> &processor() {
|
||||
return m68000_;
|
||||
}
|
||||
|
||||
private:
|
||||
CPU::MC68000::Processor<RAM68000, true> m68000_;
|
||||
std::vector<uint16_t> ram_;
|
||||
};
|
||||
|
||||
class CPU::MC68000::ProcessorStorageTests {
|
||||
public:
|
||||
ProcessorStorageTests(const CPU::MC68000::ProcessorStorage &storage, const char *coverage_file_name) {
|
||||
FILE *source = fopen(coverage_file_name, "rb");
|
||||
|
||||
// The file format here is [2 bytes opcode][2 ASCII characters:VA for valid, IN for invalid]...
|
||||
// The file terminates with four additional bytes that begin with two zero bytes.
|
||||
//
|
||||
// The version of the file I grabbed seems to cover all opcodes, making their enumeration
|
||||
// arguably redundant; the code below nevertheless uses the codes from the file.
|
||||
//
|
||||
// Similarly, I'm testing for exactly the strings VA or IN to ensure no further
|
||||
// types creep into any updated version of the table that I then deal with incorrectly.
|
||||
uint16_t last_observed = 0;
|
||||
while(true) {
|
||||
// Fetch opcode number.
|
||||
uint16_t next_opcode = fgetc(source) << 8;
|
||||
next_opcode |= fgetc(source);
|
||||
if(next_opcode < last_observed) break;
|
||||
last_observed = next_opcode;
|
||||
|
||||
// Determine whether it's meant to be valid.
|
||||
char type[3];
|
||||
type[0] = fgetc(source);
|
||||
type[1] = fgetc(source);
|
||||
type[2] = '\0';
|
||||
|
||||
if(!strcmp(type, "VA")) {
|
||||
// Test for validity.
|
||||
if(!storage.instructions[next_opcode].micro_operations) {
|
||||
false_invalids_.insert(next_opcode);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!strcmp(type, "IN")) {
|
||||
// Test for invalidity.
|
||||
if(!storage.instructions[next_opcode].micro_operations) {
|
||||
false_valids_.insert(next_opcode);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fclose(source);
|
||||
}
|
||||
|
||||
NSString *false_valids() const {
|
||||
return contents_of(false_valids_);
|
||||
}
|
||||
|
||||
NSString *false_invalids() const {
|
||||
return contents_of(false_invalids_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<uint16_t> false_invalids_;
|
||||
std::set<uint16_t> false_valids_;
|
||||
|
||||
static NSString *contents_of(const std::set<uint16_t> &set) {
|
||||
NSMutableString *result = [[NSMutableString alloc] init];
|
||||
|
||||
for(auto value: set) {
|
||||
[result appendFormat:@"%04x ", value];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@interface M68000Tests : XCTestCase
|
||||
@end
|
||||
|
||||
@ -164,4 +242,15 @@ class RAM68000: public CPU::MC68000::BusHandler {
|
||||
XCTAssert(state.data[2] == 0x303cfb2e, "D2 was %08x instead of 0x303cfb2e", state.data[2]);
|
||||
}
|
||||
|
||||
- (void)testOpcodeCoverage {
|
||||
// Perform an audit of implemented instructions.
|
||||
CPU::MC68000::ProcessorStorageTests storage_tests(
|
||||
_machine->processor(),
|
||||
[[NSBundle bundleForClass:[self class]] pathForResource:@"OPCLOGR2" ofType:@"BIN"].UTF8String
|
||||
);
|
||||
|
||||
XCTAssert(!storage_tests.false_valids().length, "Opcodes should be invalid but aren't: %@", storage_tests.false_valids());
|
||||
XCTAssert(!storage_tests.false_invalids().length, "Opcodes should be valid but aren't: %@", storage_tests.false_invalids());
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -387,6 +387,7 @@ class ProcessorStorage {
|
||||
|
||||
private:
|
||||
friend class ProcessorStorageConstructor;
|
||||
friend class ProcessorStorageTests;
|
||||
};
|
||||
|
||||
#endif /* MC68000Storage_h */
|
||||
|
Loading…
Reference in New Issue
Block a user