From 62b432c046d77456d145e3d45c80b5edbb1870f3 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 19 May 2017 21:20:28 -0400 Subject: [PATCH] Added the concept of a trap handler to the all-RAM processor and exposed it via the test Z80 classes. --- .../Bridges/TestMachineZ80.h | 9 ++++ .../Bridges/TestMachineZ80.mm | 45 +++++++++++++++++++ Processors/AllRAMProcessor.cpp | 14 ++++++ Processors/AllRAMProcessor.hpp | 14 ++++++ Processors/Z80/Z80AllRAM.cpp | 1 + 5 files changed, 83 insertions(+) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h index e934f84d3..4498db824 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h @@ -13,6 +13,12 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { CSTestMachineZ80RegisterStackPointer, }; +@class CSTestMachineZ80; + +@interface CSTestMachineTrapHandler +- (void)testMachine:(CSTestMachineZ80 *)testMachine didTrapAtAddress:(uint16_t)address; +@end + @interface CSTestMachineZ80 : NSObject - (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; - (uint16_t)valueForRegister:(CSTestMachineZ80Register)reg; +@property(nonatomic, weak) id trapHandler; +- (void)addTrapAddress:(uint16_t)trapAddress; + @end diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm index 00de40840..badcb15e7 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm @@ -9,6 +9,26 @@ #import "TestMachineZ80.h" #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) { switch (reg) { case CSTestMachineZ80RegisterProgramCounter: return CPU::Z80::Register::ProgramCounter; @@ -16,8 +36,25 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { } } +#pragma mark - Test class + @implementation CSTestMachineZ80 { 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 @@ -38,4 +75,12 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register 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 diff --git a/Processors/AllRAMProcessor.cpp b/Processors/AllRAMProcessor.cpp index e017be294..74d49df5a 100644 --- a/Processors/AllRAMProcessor.cpp +++ b/Processors/AllRAMProcessor.cpp @@ -22,3 +22,17 @@ void AllRAMProcessor::set_data_at_address(uint16_t startAddress, size_t length, uint32_t AllRAMProcessor::get_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); +} diff --git a/Processors/AllRAMProcessor.hpp b/Processors/AllRAMProcessor.hpp index 0db92bb06..17b69b7d6 100644 --- a/Processors/AllRAMProcessor.hpp +++ b/Processors/AllRAMProcessor.hpp @@ -10,6 +10,7 @@ #define AllRAMProcessor_hpp #include +#include #include namespace CPU { @@ -20,9 +21,22 @@ class AllRAMProcessor { uint32_t get_timestamp(); 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: std::vector memory_; uint32_t timestamp_; + + void check_address_for_trap(uint16_t address); + + private: + std::set trap_addresses_; + TrapHandler *trap_handler_; }; } diff --git a/Processors/Z80/Z80AllRAM.cpp b/Processors/Z80/Z80AllRAM.cpp index b3d6b9a39..a17299edb 100644 --- a/Processors/Z80/Z80AllRAM.cpp +++ b/Processors/Z80/Z80AllRAM.cpp @@ -16,6 +16,7 @@ AllRAMProcessor::AllRAMProcessor() : ::CPU::AllRAMProcessor(65536) {} int AllRAMProcessor::perform_machine_cycle(const MachineCycle *cycle) { switch(cycle->operation) { case BusOperation::ReadOpcode: + check_address_for_trap(*cycle->address); case BusOperation::Read: printf("r %04x\n", *cycle->address); *cycle->value = memory_[*cycle->address];