mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-09 06:29:33 +00:00
Ensures state is evaluated directly at opcode end.
This commit is contained in:
parent
37e26c0c37
commit
adf6723bf6
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
@interface M68000ComparativeTests : XCTestCase
|
@interface M68000ComparativeTests : XCTestCase
|
||||||
@end
|
@end
|
||||||
@ -50,12 +51,14 @@
|
|||||||
struct Test68000: public CPU::MC68000::BusHandler {
|
struct Test68000: public CPU::MC68000::BusHandler {
|
||||||
std::array<uint8_t, 16*1024*1024> ram;
|
std::array<uint8_t, 16*1024*1024> ram;
|
||||||
CPU::MC68000::Processor<Test68000, true, true> processor;
|
CPU::MC68000::Processor<Test68000, true, true> processor;
|
||||||
|
std::function<void(void)> comparitor;
|
||||||
|
|
||||||
Test68000() : processor(*this) {
|
Test68000() : processor(*this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void will_perform(uint32_t address, uint16_t opcode) {
|
void will_perform(uint32_t address, uint16_t opcode) {
|
||||||
--instructions_remaining_;
|
--instructions_remaining_;
|
||||||
|
if(!instructions_remaining_) comparitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int is_supervisor) {
|
HalfCycles perform_bus_operation(const CPU::MC68000::Microcycle &cycle, int is_supervisor) {
|
||||||
@ -66,8 +69,9 @@
|
|||||||
return HalfCycles(0);
|
return HalfCycles(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_for_instructions(int instructions) {
|
void run_for_instructions(int instructions, const std::function<void(void)> &compare) {
|
||||||
instructions_remaining_ = instructions + 1; // i.e. run up to the will_perform of the instruction after.
|
instructions_remaining_ = instructions + 1; // i.e. run up to the will_perform of the instruction after.
|
||||||
|
comparitor = std::move(compare);
|
||||||
while(instructions_remaining_) {
|
while(instructions_remaining_) {
|
||||||
processor.run_for(HalfCycles(2));
|
processor.run_for(HalfCycles(2));
|
||||||
}
|
}
|
||||||
@ -76,64 +80,70 @@
|
|||||||
private:
|
private:
|
||||||
int instructions_remaining_;
|
int instructions_remaining_;
|
||||||
};
|
};
|
||||||
auto test68000 = std::make_unique<Test68000>();
|
auto uniqueTest68000 = std::make_unique<Test68000>();
|
||||||
|
auto test68000 = uniqueTest68000.get();
|
||||||
|
memset(test68000->ram.data(), 0xce, test68000->ram.size());
|
||||||
|
|
||||||
// Apply initial memory state.
|
{
|
||||||
NSArray<NSNumber *> *const initialMemory = test[@"initial memory"];
|
// Apply initial memory state.
|
||||||
NSEnumerator<NSNumber *> *enumerator = [initialMemory objectEnumerator];
|
NSArray<NSNumber *> *const initialMemory = test[@"initial memory"];
|
||||||
while(true) {
|
NSEnumerator<NSNumber *> *enumerator = [initialMemory objectEnumerator];
|
||||||
NSNumber *const address = [enumerator nextObject];
|
while(true) {
|
||||||
NSNumber *const value = [enumerator nextObject];
|
NSNumber *const address = [enumerator nextObject];
|
||||||
|
NSNumber *const value = [enumerator nextObject];
|
||||||
|
|
||||||
if(!address || !value) break;
|
if(!address || !value) break;
|
||||||
test68000->ram[address.integerValue ^ 1] = value.integerValue; // Effect a short-resolution endianness swap.
|
test68000->ram[address.integerValue ^ 1] = value.integerValue; // Effect a short-resolution endianness swap.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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] = [initialState[dX] integerValue];
|
|
||||||
if(c < 7)
|
|
||||||
state.address[c] = [initialState[aX] integerValue];
|
|
||||||
}
|
|
||||||
state.supervisor_stack_pointer = [initialState[@"a7"] integerValue];
|
|
||||||
state.user_stack_pointer = [initialState[@"usp"] integerValue];
|
|
||||||
state.status = [initialState[@"sr"] integerValue];
|
|
||||||
test68000->processor.set_state(state);
|
|
||||||
|
|
||||||
// Run the thing.
|
// Run the thing.
|
||||||
test68000->run_for_instructions(1);
|
const auto comparitor = [=] {
|
||||||
|
// 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];
|
||||||
|
|
||||||
// Test the end state.
|
XCTAssertEqual(state.data[c], [finalState[dX] integerValue], @"%@: D%d inconsistent", name, c);
|
||||||
NSDictionary *const finalState = test[@"final state"];
|
if(c < 7) {
|
||||||
state = test68000->processor.get_state();
|
XCTAssertEqual(state.address[c], [finalState[aX] integerValue], @"%@: A%d inconsistent", name, c);
|
||||||
for(int c = 0; c < 8; ++c) {
|
}
|
||||||
const NSString *dX = [@"d" stringByAppendingFormat:@"%d", c];
|
|
||||||
const NSString *aX = [@"a" stringByAppendingFormat:@"%d", c];
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
XCTAssertEqual(state.supervisor_stack_pointer, [finalState[@"a7"] integerValue], @"%@: A7 inconsistent", 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.user_stack_pointer, [finalState[@"usp"] integerValue], @"%@: USP inconsistent", name);
|
XCTAssertEqual(state.status, [finalState[@"sr"] integerValue], @"%@: Status inconsistent", name);
|
||||||
XCTAssertEqual(state.status, [finalState[@"sr"] integerValue], @"%@: Status inconsistent", name);
|
|
||||||
|
|
||||||
// Test final memory state.
|
// Test final memory state.
|
||||||
NSArray<NSNumber *> *const finalMemory = test[@"final memory"];
|
NSArray<NSNumber *> *const finalMemory = test[@"final memory"];
|
||||||
enumerator = [finalMemory objectEnumerator];
|
NSEnumerator *enumerator = [finalMemory objectEnumerator];
|
||||||
while(true) {
|
while(true) {
|
||||||
NSNumber *const address = [enumerator nextObject];
|
NSNumber *const address = [enumerator nextObject];
|
||||||
NSNumber *const value = [enumerator nextObject];
|
NSNumber *const value = [enumerator nextObject];
|
||||||
|
|
||||||
if(!address || !value) break;
|
if(!address || !value) break;
|
||||||
XCTAssertEqual(test68000->ram[address.integerValue ^ 1], value.integerValue, @"%@: Memory at location %@ inconsistent", name, address);
|
XCTAssertEqual(test68000->ram[address.integerValue ^ 1], value.integerValue, @"%@: Memory at location %@ inconsistent", name, address);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test68000->run_for_instructions(1, comparitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
Reference in New Issue
Block a user