1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-09 06:29:33 +00:00

Ensure complete runs of each tested opcode.

This commit is contained in:
Thomas Harte 2022-06-18 16:26:40 -04:00
parent 586ef4810b
commit f8e6954739

View File

@ -15,9 +15,12 @@
namespace { namespace {
struct StopException {};
struct BusHandler: public CPU::MOS6502Esque::BusHandler<uint32_t> { struct BusHandler: public CPU::MOS6502Esque::BusHandler<uint32_t> {
// Use a map to store RAM contents, in order to preserve initialised state. // Use a map to store RAM contents, in order to preserve initialised state.
std::unordered_map<uint32_t, uint8_t> ram; std::unordered_map<uint32_t, uint8_t> ram;
std::unordered_map<uint32_t, uint8_t> inventions;
Cycles perform_bus_operation(CPU::MOS6502Esque::BusOperation operation, uint32_t address, uint8_t *value) { Cycles perform_bus_operation(CPU::MOS6502Esque::BusOperation operation, uint32_t address, uint8_t *value) {
// Record the basics of the operation. // Record the basics of the operation.
@ -31,7 +34,11 @@ struct BusHandler: public CPU::MOS6502Esque::BusHandler<uint32_t> {
auto ram_value = ram.find(address); auto ram_value = ram.find(address);
switch(operation) { switch(operation) {
case BusOperation::ReadOpcode: case BusOperation::ReadOpcode:
++opcodes_fetched_; --opcodes_remaining;
if(!opcodes_remaining) {
cycles.pop_back();
throw StopException();
}
case BusOperation::Read: case BusOperation::Read:
case BusOperation::ReadProgram: case BusOperation::ReadProgram:
case BusOperation::ReadVector: case BusOperation::ReadVector:
@ -39,7 +46,7 @@ struct BusHandler: public CPU::MOS6502Esque::BusHandler<uint32_t> {
cycle.value = *value = ram_value->second; cycle.value = *value = ram_value->second;
} else { } else {
cycle.value = *value = uint8_t(rand() >> 8); cycle.value = *value = uint8_t(rand() >> 8);
ram[address] = cycle.value; inventions[address] = ram[address] = cycle.value;
} }
break; break;
@ -54,7 +61,19 @@ struct BusHandler: public CPU::MOS6502Esque::BusHandler<uint32_t> {
return Cycles(1); return Cycles(1);
} }
int opcodes_fetched_ = 0; template <typename Processor> void setup(Processor &processor, uint8_t opcode) {
ram.clear();
inventions.clear();
cycles.clear();
using Register = CPU::MOS6502Esque::Register;
const uint32_t pc =
processor.get_value_of_register(Register::ProgramCounter) |
(processor.get_value_of_register(Register::ProgramBank) << 8);
inventions[pc] = ram[pc] = opcode;
}
int opcodes_remaining = 0;
struct Cycle { struct Cycle {
CPU::MOS6502Esque::BusOperation operation; CPU::MOS6502Esque::BusOperation operation;
@ -77,17 +96,29 @@ struct BusHandler: public CPU::MOS6502Esque::BusHandler<uint32_t> {
BusHandler handler; BusHandler handler;
CPU::WDC65816::Processor<BusHandler, false> processor(handler); CPU::WDC65816::Processor<BusHandler, false> processor(handler);
// Never run the official reset procedure.
processor.set_power_on(false);
for(int operation = 0; operation < 512; operation++) { for(int operation = 0; operation < 512; operation++) {
const bool is_emulated = operation & 256; const bool is_emulated = operation & 256;
const uint8_t opcode = operation & 255; const uint8_t opcode = operation & 255;
// TODO: set up for opcode and emulation mode. // Ensure processor's next action is an opcode fetch.
processor.restart_operation_fetch();
// TODO: run for a bit longer than this, of course. // Randomise processor state.
processor.run_for(Cycles(1)); using Register = CPU::MOS6502Esque::Register;
processor.set_value_of_register(Register::EmulationFlag, is_emulated);
// Establish the opcode.
handler.setup(processor, opcode);
// Run to the second opcode fetch.
handler.opcodes_remaining = 2;
try {
processor.run_for(Cycles(100));
} catch (const StopException &) {}
} }
printf("");
} }
@end @end