From aed2827e7b48305a491ffb38aa70712afba9a19c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 12 Jun 2017 22:22:00 -0400 Subject: [PATCH] Implemented a rudimentary way to test that instructions take as long as the FUSE tests think they should. Hence discovered that the (HL)-accessing BIT, RES and SET weren't. Corrected. --- .../Mac/Clock SignalTests/Bridges/TestMachineZ80.h | 1 + .../Mac/Clock SignalTests/Bridges/TestMachineZ80.mm | 4 ++++ OSBindings/Mac/Clock SignalTests/FUSETests.swift | 4 ++++ Processors/Z80/Z80.hpp | 9 ++++++++- Processors/Z80/Z80AllRAM.cpp | 11 ++++++++++- Processors/Z80/Z80AllRAM.hpp | 2 ++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h index b935e51ce..cbb1a9c60 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h @@ -59,6 +59,7 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { @property(nonatomic, readonly, nonnull) NSArray *busOperationCaptures; @property(nonatomic, readonly) BOOL isHalted; +@property(nonatomic, readonly) int completedCycles; @property(nonatomic) BOOL nmiLine; @property(nonatomic) BOOL irqLine; diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm index 0fac2def5..9284c6917 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm @@ -149,6 +149,10 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { return _processor->get_halt_line() ? YES : NO; } +- (int)completedCycles { + return _processor->get_length_of_completed_machine_cycles(); +} + - (void)setNmiLine:(BOOL)nmiLine { _nmiLine = nmiLine; _processor->set_non_maskable_interrupt_line(nmiLine ? true : false); diff --git a/OSBindings/Mac/Clock SignalTests/FUSETests.swift b/OSBindings/Mac/Clock SignalTests/FUSETests.swift index 14b4290e3..3f2d0e26b 100644 --- a/OSBindings/Mac/Clock SignalTests/FUSETests.swift +++ b/OSBindings/Mac/Clock SignalTests/FUSETests.swift @@ -194,6 +194,10 @@ class FUSETests: XCTestCase { machine.runForNumber(ofCycles: Int32(targetState.tStates)) + // Verify that exactly the right number of cycles was hit; this is a primitive cycle length tester. + let cyclesRun = machine.completedCycles + XCTAssert(cyclesRun == Int32(targetState.tStates), "Instruction length off; was \(machine.completedCycles) but should be \(targetState.tStates): \(name)") + let finalState = RegisterState(machine: machine) // Compare processor state. diff --git a/Processors/Z80/Z80.hpp b/Processors/Z80/Z80.hpp index 04cdbc65a..7e4a2ab71 100644 --- a/Processors/Z80/Z80.hpp +++ b/Processors/Z80/Z80.hpp @@ -285,6 +285,13 @@ template class Processor { Program(INDEX(), FETCHL(temp8_, INDEX_ADDR()), {MicroOp::op, &temp8_}), \ Program({MicroOp::op, &a_}) +#define READ_OP_GROUP_D(op) \ + Program({MicroOp::op, &bc_.bytes.high}), Program({MicroOp::op, &bc_.bytes.low}), \ + Program({MicroOp::op, &de_.bytes.high}), Program({MicroOp::op, &de_.bytes.low}), \ + Program({MicroOp::op, &index.bytes.high}), Program({MicroOp::op, &index.bytes.low}), \ + Program(INDEX(), FETCHL(temp8_, INDEX_ADDR()), WAIT(1), {MicroOp::op, &temp8_}), \ + Program({MicroOp::op, &a_}) + #define RMW(x, op, ...) Program(INDEX(), FETCHL(x, INDEX_ADDR()), {MicroOp::op, &x}, WAIT(1), STOREL(x, INDEX_ADDR())) #define RMWI(x, op, ...) Program(WAIT(2), FETCHL(x, INDEX_ADDR()), {MicroOp::op, &x}, WAIT(1), STOREL(x, INDEX_ADDR())) @@ -461,7 +468,7 @@ template class Processor { /* 0x40 – 0x7f: BIT */ /* 0x80 – 0xcf: RES */ /* 0xd0 – 0xdf: SET */ - CB_PAGE(MODIFY_OP_GROUP, READ_OP_GROUP) + CB_PAGE(MODIFY_OP_GROUP, READ_OP_GROUP_D) }; InstructionTable offsets_cb_program_table = { CB_PAGE(IX_MODIFY_OP_GROUP, IX_READ_OP_GROUP) diff --git a/Processors/Z80/Z80AllRAM.cpp b/Processors/Z80/Z80AllRAM.cpp index 9ad4f46c2..8594a2fbf 100644 --- a/Processors/Z80/Z80AllRAM.cpp +++ b/Processors/Z80/Z80AllRAM.cpp @@ -14,9 +14,10 @@ namespace { class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor { public: - ConcreteAllRAMProcessor() : AllRAMProcessor() {} + ConcreteAllRAMProcessor() : AllRAMProcessor(), completed_cycles(0) {} inline int perform_machine_cycle(const MachineCycle &cycle) { + completed_cycles += cycle.length; uint16_t address = cycle.address ? *cycle.address : 0x0000; switch(cycle.operation) { case BusOperation::ReadOpcode: @@ -88,6 +89,14 @@ class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor::set_non_maskable_interrupt_line(value); } + + int get_length_of_completed_machine_cycles() { + return completed_cycles; + } + + private: + int completed_cycles; + }; } diff --git a/Processors/Z80/Z80AllRAM.hpp b/Processors/Z80/Z80AllRAM.hpp index e31e41768..8999fc5bb 100644 --- a/Processors/Z80/Z80AllRAM.hpp +++ b/Processors/Z80/Z80AllRAM.hpp @@ -36,6 +36,8 @@ class AllRAMProcessor: virtual void set_interrupt_line(bool value) = 0; virtual void set_non_maskable_interrupt_line(bool value) = 0; + virtual int get_length_of_completed_machine_cycles() = 0; + protected: MemoryAccessDelegate *delegate_; AllRAMProcessor() : ::CPU::AllRAMProcessor(65536), delegate_(nullptr) {}