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:
parent
b5c1773d59
commit
5119997122
@ -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 {
|
||||||
|
@ -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])
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user