1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 03:32:01 +00:00

Added the concept of a trap handler to the all-RAM processor and exposed it via the test Z80 classes.

This commit is contained in:
Thomas Harte 2017-05-19 21:20:28 -04:00
parent eae1f78221
commit 62b432c046
5 changed files with 83 additions and 0 deletions

View File

@ -13,6 +13,12 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) {
CSTestMachineZ80RegisterStackPointer, CSTestMachineZ80RegisterStackPointer,
}; };
@class CSTestMachineZ80;
@interface CSTestMachineTrapHandler
- (void)testMachine:(CSTestMachineZ80 *)testMachine didTrapAtAddress:(uint16_t)address;
@end
@interface CSTestMachineZ80 : NSObject @interface CSTestMachineZ80 : NSObject
- (void)setData:(NSData *)data atAddress:(uint16_t)startAddress; - (void)setData:(NSData *)data atAddress:(uint16_t)startAddress;
@ -21,4 +27,7 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) {
- (void)setValue:(uint16_t)value forRegister:(CSTestMachineZ80Register)reg; - (void)setValue:(uint16_t)value forRegister:(CSTestMachineZ80Register)reg;
- (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg; - (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg;
@property(nonatomic, weak) id<CSTestMachineTrapHandler> trapHandler;
- (void)addTrapAddress:(uint16_t)trapAddress;
@end @end

View File

@ -9,6 +9,26 @@
#import "TestMachineZ80.h" #import "TestMachineZ80.h"
#include "Z80AllRAM.hpp" #include "Z80AllRAM.hpp"
@interface CSTestMachineZ80 ()
- (void)testMachineDidTrapAtAddress:(uint16_t)address;
@end
#pragma mark - C++ trap handler
class MachineTrapHandler: public CPU::AllRAMProcessor::TrapHandler {
public:
MachineTrapHandler(CSTestMachineZ80 *targetMachine) : target_(targetMachine) {}
void processor_did_trap(CPU::AllRAMProcessor &, uint16_t address) {
[target_ testMachineDidTrapAtAddress:address];
}
private:
CSTestMachineZ80 *target_;
};
#pragma mark - Register enum map
static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
switch (reg) { switch (reg) {
case CSTestMachineZ80RegisterProgramCounter: return CPU::Z80::Register::ProgramCounter; case CSTestMachineZ80RegisterProgramCounter: return CPU::Z80::Register::ProgramCounter;
@ -16,8 +36,25 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
} }
} }
#pragma mark - Test class
@implementation CSTestMachineZ80 { @implementation CSTestMachineZ80 {
CPU::Z80::AllRAMProcessor _processor; CPU::Z80::AllRAMProcessor _processor;
MachineTrapHandler *_cppTrapHandler;
}
#pragma mark - Lifecycle
- (instancetype)init {
if(self = [super init]) {
_cppTrapHandler = new MachineTrapHandler(self);
_processor.set_trap_handler(_cppTrapHandler);
}
return self;
}
- (void)dealloc {
delete _cppTrapHandler;
} }
#pragma mark - Accessors #pragma mark - Accessors
@ -38,4 +75,12 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
return _processor.get_value_of_register(registerForRegister(reg)); return _processor.get_value_of_register(registerForRegister(reg));
} }
- (void)addTrapAddress:(uint16_t)trapAddress {
_processor.add_trap_address(trapAddress);
}
- (void)testMachineDidTrapAtAddress:(uint16_t)address {
[self.trapHandler testMachine:self didTrapAtAddress:address];
}
@end @end

View File

@ -22,3 +22,17 @@ void AllRAMProcessor::set_data_at_address(uint16_t startAddress, size_t length,
uint32_t AllRAMProcessor::get_timestamp() { uint32_t AllRAMProcessor::get_timestamp() {
return timestamp_; return timestamp_;
} }
void AllRAMProcessor::check_address_for_trap(uint16_t address) {
if(trap_addresses_.find(address) != trap_addresses_.end()) {
trap_handler_->processor_did_trap(*this, address);
}
}
void AllRAMProcessor::set_trap_handler(TrapHandler *trap_handler) {
trap_handler_ = trap_handler;
}
void AllRAMProcessor::add_trap_address(uint16_t address) {
trap_addresses_.insert(address);
}

View File

@ -10,6 +10,7 @@
#define AllRAMProcessor_hpp #define AllRAMProcessor_hpp
#include <cstdint> #include <cstdint>
#include <set>
#include <vector> #include <vector>
namespace CPU { namespace CPU {
@ -20,9 +21,22 @@ class AllRAMProcessor {
uint32_t get_timestamp(); uint32_t get_timestamp();
void set_data_at_address(uint16_t startAddress, size_t length, const uint8_t *data); void set_data_at_address(uint16_t startAddress, size_t length, const uint8_t *data);
class TrapHandler {
public:
virtual void processor_did_trap(AllRAMProcessor &, uint16_t address) = 0;
};
void set_trap_handler(TrapHandler *trap_handler);
void add_trap_address(uint16_t address);
protected: protected:
std::vector<uint8_t> memory_; std::vector<uint8_t> memory_;
uint32_t timestamp_; uint32_t timestamp_;
void check_address_for_trap(uint16_t address);
private:
std::set<uint16_t> trap_addresses_;
TrapHandler *trap_handler_;
}; };
} }

View File

@ -16,6 +16,7 @@ AllRAMProcessor::AllRAMProcessor() : ::CPU::AllRAMProcessor(65536) {}
int AllRAMProcessor::perform_machine_cycle(const MachineCycle *cycle) { int AllRAMProcessor::perform_machine_cycle(const MachineCycle *cycle) {
switch(cycle->operation) { switch(cycle->operation) {
case BusOperation::ReadOpcode: case BusOperation::ReadOpcode:
check_address_for_trap(*cycle->address);
case BusOperation::Read: case BusOperation::Read:
printf("r %04x\n", *cycle->address); printf("r %04x\n", *cycle->address);
*cycle->value = memory_[*cycle->address]; *cycle->value = memory_[*cycle->address];