mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +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:
parent
b5c1773d59
commit
5119997122
@ -104,7 +104,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
#pragma mark - Test class
|
||||
|
||||
@implementation CSTestMachineZ80 {
|
||||
CPU::Z80::AllRAMProcessor _processor;
|
||||
CPU::Z80::AllRAMProcessor *_processor;
|
||||
MachineTrapHandler *_cppTrapHandler;
|
||||
BusOperationHandler *_busOperationHandler;
|
||||
|
||||
@ -118,6 +118,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
|
||||
- (instancetype)init {
|
||||
if(self = [super init]) {
|
||||
_processor = CPU::Z80::AllRAMProcessor::Processor();
|
||||
_cppTrapHandler = new MachineTrapHandler(self);
|
||||
_busOperationHandler = new BusOperationHandler(self);
|
||||
_busOperationCaptures = [[NSMutableArray alloc] init];
|
||||
@ -133,34 +134,34 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
#pragma mark - Accessors
|
||||
|
||||
- (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 {
|
||||
_processor.run_for_cycles(cycles);
|
||||
_processor->run_for_cycles(cycles);
|
||||
}
|
||||
|
||||
- (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 {
|
||||
_processor.set_data_at_address(address, 1, &value);
|
||||
_processor->set_data_at_address(address, 1, &value);
|
||||
}
|
||||
|
||||
- (uint8_t)valueAtAddress:(uint16_t)address {
|
||||
uint8_t value;
|
||||
_processor.get_data_at_address(address, 1, &value);
|
||||
_processor->get_data_at_address(address, 1, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
- (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 {
|
||||
_processor.set_trap_handler(_cppTrapHandler);
|
||||
_processor.add_trap_address(trapAddress);
|
||||
_processor->set_trap_handler(_cppTrapHandler);
|
||||
_processor->add_trap_address(trapAddress);
|
||||
}
|
||||
|
||||
- (void)testMachineDidTrapAtAddress:(uint16_t)address {
|
||||
@ -168,7 +169,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
}
|
||||
|
||||
- (BOOL)isHalted {
|
||||
return _processor.get_halt_line() ? YES : NO;
|
||||
return _processor->get_halt_line() ? YES : NO;
|
||||
}
|
||||
|
||||
#pragma mark - Z80-specific Runner
|
||||
@ -178,7 +179,7 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
||||
_timeSeekingReadOpcode = 0;
|
||||
while(!_isAtReadOpcode) {
|
||||
_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 {
|
||||
_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 {
|
||||
|
@ -167,9 +167,9 @@ class FUSETests: XCTestCase {
|
||||
|
||||
let name = itemDictionary["name"] as! String
|
||||
|
||||
// if name != "d3_1" {
|
||||
// continue;
|
||||
// }
|
||||
if name != "02" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let initialState = RegisterState(dictionary: itemDictionary["state"] as! [String: Any])
|
||||
let targetState = RegisterState(dictionary: outputDictionary["state"] as! [String: Any])
|
||||
|
@ -10,44 +10,67 @@
|
||||
#include <algorithm>
|
||||
|
||||
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) {
|
||||
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
switch(cycle.operation) {
|
||||
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);
|
||||
case BusOperation::Read:
|
||||
// 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));
|
||||
*cycle.value = memory_[address];
|
||||
break;
|
||||
case BusOperation::Write:
|
||||
// printf("w %04x\n", *cycle->address);
|
||||
memory_[address] = *cycle.value;
|
||||
break;
|
||||
inline int perform_machine_cycle(const MachineCycle &cycle) {
|
||||
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||
switch(cycle.operation) {
|
||||
case BusOperation::ReadOpcode:
|
||||
check_address_for_trap(address);
|
||||
case BusOperation::Read:
|
||||
*cycle.value = memory_[address];
|
||||
break;
|
||||
case BusOperation::Write:
|
||||
memory_[address] = *cycle.value;
|
||||
break;
|
||||
|
||||
case BusOperation::Output:
|
||||
break;
|
||||
case BusOperation::Input:
|
||||
// This logic is selected specifically because it seems to match
|
||||
// the FUSE unit tests. It might need factoring out.
|
||||
*cycle.value = address >> 8;
|
||||
break;
|
||||
case BusOperation::Output:
|
||||
break;
|
||||
case BusOperation::Input:
|
||||
// This logic is selected specifically because it seems to match
|
||||
// the FUSE unit tests. It might need factoring out.
|
||||
*cycle.value = address >> 8;
|
||||
break;
|
||||
|
||||
case BusOperation::Internal:
|
||||
break;
|
||||
case BusOperation::Internal:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("???\n");
|
||||
break;
|
||||
}
|
||||
timestamp_ += cycle.length;
|
||||
default:
|
||||
printf("???\n");
|
||||
break;
|
||||
}
|
||||
timestamp_ += cycle.length;
|
||||
|
||||
if(delegate_ != nullptr) {
|
||||
delegate_->z80_all_ram_processor_did_perform_bus_operation(*this, cycle.operation, address, cycle.value ? *cycle.value : 0x00, timestamp_);
|
||||
}
|
||||
if(delegate_ != nullptr) {
|
||||
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;
|
||||
}
|
||||
|
@ -16,23 +16,26 @@ namespace CPU {
|
||||
namespace Z80 {
|
||||
|
||||
class AllRAMProcessor:
|
||||
public ::CPU::AllRAMProcessor,
|
||||
public Processor<AllRAMProcessor> {
|
||||
public ::CPU::AllRAMProcessor {
|
||||
|
||||
public:
|
||||
AllRAMProcessor();
|
||||
|
||||
int perform_machine_cycle(const MachineCycle &cycle);
|
||||
static AllRAMProcessor *Processor();
|
||||
|
||||
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;
|
||||
};
|
||||
void set_memory_access_delegate(MemoryAccessDelegate *delegate) {
|
||||
inline void set_memory_access_delegate(MemoryAccessDelegate *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_;
|
||||
AllRAMProcessor() : ::CPU::AllRAMProcessor(65536), delegate_(nullptr) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user