1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-12 15:31:09 +00:00

Made an attempt, flawed so far, to find a neat way for processor subclasses to offer bus management as an inline function.

This commit is contained in:
Thomas Harte 2017-05-30 22:41:23 -04:00
parent b5c1773d59
commit 5119997122
4 changed files with 82 additions and 55 deletions

View File

@ -104,7 +104,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
#pragma mark - Test class #pragma mark - Test class
@implementation CSTestMachineZ80 { @implementation CSTestMachineZ80 {
CPU::Z80::AllRAMProcessor _processor; CPU::Z80::AllRAMProcessor *_processor;
MachineTrapHandler *_cppTrapHandler; MachineTrapHandler *_cppTrapHandler;
BusOperationHandler *_busOperationHandler; BusOperationHandler *_busOperationHandler;
@ -118,6 +118,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
- (instancetype)init { - (instancetype)init {
if(self = [super init]) { if(self = [super init]) {
_processor = CPU::Z80::AllRAMProcessor::Processor();
_cppTrapHandler = new MachineTrapHandler(self); _cppTrapHandler = new MachineTrapHandler(self);
_busOperationHandler = new BusOperationHandler(self); _busOperationHandler = new BusOperationHandler(self);
_busOperationCaptures = [[NSMutableArray alloc] init]; _busOperationCaptures = [[NSMutableArray alloc] init];
@ -133,34 +134,34 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
#pragma mark - Accessors #pragma mark - Accessors
- (void)setData:(NSData *)data atAddress:(uint16_t)startAddress { - (void)setData:(NSData *)data atAddress:(uint16_t)startAddress {
_processor.set_data_at_address(startAddress, data.length, (const uint8_t *)data.bytes); _processor->set_data_at_address(startAddress, data.length, (const uint8_t *)data.bytes);
} }
- (void)runForNumberOfCycles:(int)cycles { - (void)runForNumberOfCycles:(int)cycles {
_processor.run_for_cycles(cycles); _processor->run_for_cycles(cycles);
} }
- (void)setValue:(uint16_t)value forRegister:(CSTestMachineZ80Register)reg { - (void)setValue:(uint16_t)value forRegister:(CSTestMachineZ80Register)reg {
_processor.set_value_of_register(registerForRegister(reg), value); _processor->set_value_of_register(registerForRegister(reg), value);
} }
- (void)setValue:(uint8_t)value atAddress:(uint16_t)address { - (void)setValue:(uint8_t)value atAddress:(uint16_t)address {
_processor.set_data_at_address(address, 1, &value); _processor->set_data_at_address(address, 1, &value);
} }
- (uint8_t)valueAtAddress:(uint16_t)address { - (uint8_t)valueAtAddress:(uint16_t)address {
uint8_t value; uint8_t value;
_processor.get_data_at_address(address, 1, &value); _processor->get_data_at_address(address, 1, &value);
return value; return value;
} }
- (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg { - (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg {
return _processor.get_value_of_register(registerForRegister(reg)); return _processor->get_value_of_register(registerForRegister(reg));
} }
- (void)addTrapAddress:(uint16_t)trapAddress { - (void)addTrapAddress:(uint16_t)trapAddress {
_processor.set_trap_handler(_cppTrapHandler); _processor->set_trap_handler(_cppTrapHandler);
_processor.add_trap_address(trapAddress); _processor->add_trap_address(trapAddress);
} }
- (void)testMachineDidTrapAtAddress:(uint16_t)address { - (void)testMachineDidTrapAtAddress:(uint16_t)address {
@ -168,7 +169,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
} }
- (BOOL)isHalted { - (BOOL)isHalted {
return _processor.get_halt_line() ? YES : NO; return _processor->get_halt_line() ? YES : NO;
} }
#pragma mark - Z80-specific Runner #pragma mark - Z80-specific Runner
@ -178,7 +179,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
_timeSeekingReadOpcode = 0; _timeSeekingReadOpcode = 0;
while(!_isAtReadOpcode) { while(!_isAtReadOpcode) {
_timeSeekingReadOpcode++; _timeSeekingReadOpcode++;
_processor.run_for_cycles(1); _processor->run_for_cycles(1);
} }
} }
@ -186,7 +187,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
- (void)setCaptureBusActivity:(BOOL)captureBusActivity { - (void)setCaptureBusActivity:(BOOL)captureBusActivity {
_captureBusActivity = captureBusActivity; _captureBusActivity = captureBusActivity;
_processor.set_memory_access_delegate(captureBusActivity ? _busOperationHandler : nullptr); _processor->set_memory_access_delegate(captureBusActivity ? _busOperationHandler : nullptr);
} }
- (void)testMachineDidPerformBusOperation:(CPU::Z80::BusOperation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)timeStamp { - (void)testMachineDidPerformBusOperation:(CPU::Z80::BusOperation)operation address:(uint16_t)address value:(uint8_t)value timeStamp:(int)timeStamp {

View File

@ -167,9 +167,9 @@ class FUSETests: XCTestCase {
let name = itemDictionary["name"] as! String let name = itemDictionary["name"] as! String
// if name != "d3_1" { if name != "02" {
// continue; continue;
// } }
let initialState = RegisterState(dictionary: itemDictionary["state"] as! [String: Any]) let initialState = RegisterState(dictionary: itemDictionary["state"] as! [String: Any])
let targetState = RegisterState(dictionary: outputDictionary["state"] as! [String: Any]) let targetState = RegisterState(dictionary: outputDictionary["state"] as! [String: Any])

View File

@ -10,44 +10,67 @@
#include <algorithm> #include <algorithm>
using namespace CPU::Z80; using namespace CPU::Z80;
namespace {
AllRAMProcessor::AllRAMProcessor() : ::CPU::AllRAMProcessor(65536), delegate_(nullptr) {} class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor<ConcreteAllRAMProcessor> {
public:
ConcreteAllRAMProcessor() : AllRAMProcessor() {}
int AllRAMProcessor::perform_machine_cycle(const MachineCycle &cycle) { inline int perform_machine_cycle(const MachineCycle &cycle) {
uint16_t address = cycle.address ? *cycle.address : 0x0000; uint16_t address = cycle.address ? *cycle.address : 0x0000;
switch(cycle.operation) { switch(cycle.operation) {
case BusOperation::ReadOpcode: case BusOperation::ReadOpcode:
// printf("%04x %02x [BC=%02x]\n", *cycle->address, memory_[*cycle->address], get_value_of_register(CPU::Z80::Register::BC)); check_address_for_trap(address);
check_address_for_trap(address); case BusOperation::Read:
case BusOperation::Read: *cycle.value = memory_[address];
// printf("r %04x [%02x] AF:%04x BC:%04x DE:%04x HL:%04x SP:%04x\n", *cycle->address, memory_[*cycle->address], get_value_of_register(CPU::Z80::Register::AF), get_value_of_register(CPU::Z80::Register::BC), get_value_of_register(CPU::Z80::Register::DE), get_value_of_register(CPU::Z80::Register::HL), get_value_of_register(CPU::Z80::Register::StackPointer)); break;
*cycle.value = memory_[address]; case BusOperation::Write:
break; memory_[address] = *cycle.value;
case BusOperation::Write: break;
// printf("w %04x\n", *cycle->address);
memory_[address] = *cycle.value;
break;
case BusOperation::Output: case BusOperation::Output:
break; break;
case BusOperation::Input: case BusOperation::Input:
// This logic is selected specifically because it seems to match // This logic is selected specifically because it seems to match
// the FUSE unit tests. It might need factoring out. // the FUSE unit tests. It might need factoring out.
*cycle.value = address >> 8; *cycle.value = address >> 8;
break; break;
case BusOperation::Internal: case BusOperation::Internal:
break; break;
default: default:
printf("???\n"); printf("???\n");
break; break;
} }
timestamp_ += cycle.length; timestamp_ += cycle.length;
if(delegate_ != nullptr) { if(delegate_ != nullptr) {
delegate_->z80_all_ram_processor_did_perform_bus_operation(*this, cycle.operation, address, cycle.value ? *cycle.value : 0x00, timestamp_); delegate_->z80_all_ram_processor_did_perform_bus_operation(*this, cycle.operation, address, cycle.value ? *cycle.value : 0x00, timestamp_);
} }
return 0;
}
void run_for_cycles(int cycles) {
CPU::Z80::Processor<ConcreteAllRAMProcessor>::run_for_cycles(cycles);
}
uint16_t get_value_of_register(Register r) {
return CPU::Z80::Processor<ConcreteAllRAMProcessor>::get_value_of_register(r);
}
void set_value_of_register(Register r, uint16_t value) {
CPU::Z80::Processor<ConcreteAllRAMProcessor>::set_value_of_register(r, value);
}
bool get_halt_line() {
return CPU::Z80::Processor<ConcreteAllRAMProcessor>::get_halt_line();
}
};
return 0; }
AllRAMProcessor *AllRAMProcessor::Processor() {
return new ConcreteAllRAMProcessor;
} }

View File

@ -16,23 +16,26 @@ namespace CPU {
namespace Z80 { namespace Z80 {
class AllRAMProcessor: class AllRAMProcessor:
public ::CPU::AllRAMProcessor, public ::CPU::AllRAMProcessor {
public Processor<AllRAMProcessor> {
public: public:
AllRAMProcessor(); static AllRAMProcessor *Processor();
int perform_machine_cycle(const MachineCycle &cycle);
struct MemoryAccessDelegate { struct MemoryAccessDelegate {
virtual void z80_all_ram_processor_did_perform_bus_operation(AllRAMProcessor &processor, BusOperation operation, uint16_t address, uint8_t value, int time_stamp) = 0; virtual void z80_all_ram_processor_did_perform_bus_operation(AllRAMProcessor &processor, BusOperation operation, uint16_t address, uint8_t value, int time_stamp) = 0;
}; };
void set_memory_access_delegate(MemoryAccessDelegate *delegate) { inline void set_memory_access_delegate(MemoryAccessDelegate *delegate) {
delegate_ = delegate; delegate_ = delegate;
} }
private: virtual void run_for_cycles(int cycles) = 0;
virtual uint16_t get_value_of_register(Register r) = 0;
virtual void set_value_of_register(Register r, uint16_t value) = 0;
virtual bool get_halt_line() = 0;
protected:
MemoryAccessDelegate *delegate_; MemoryAccessDelegate *delegate_;
AllRAMProcessor() : ::CPU::AllRAMProcessor(65536), delegate_(nullptr) {}
}; };
} }