From ed7b07c8b1a8b1a883019847dfed4f8587d9cb17 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 29 May 2017 11:54:27 -0400 Subject: [PATCH] Made an attempt to implement HALT as an operation that merely leaves the PC in place, adding the Z80's output line. Included that flag in FUSE tests. Discovered that it does not think that HALT acts that way. Which is probably correct. --- .../Bridges/TestMachineZ80.h | 2 ++ .../Bridges/TestMachineZ80.mm | 4 ++++ .../Mac/Clock SignalTests/FUSETests.swift | 7 ++++--- Processors/Z80/Z80.hpp | 21 ++++++++++++++++--- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h index 5ffaf2ed6..a7e6d7612 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.h @@ -62,4 +62,6 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) { @property(nonatomic, assign) BOOL captureBusActivity; @property(nonatomic, readonly) NSArray *busOperationCaptures; +@property(nonatomic, readonly) BOOL isHalted; + @end diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm index 2dd3109a0..ab014dbe9 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachineZ80.mm @@ -154,6 +154,10 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) { [self.trapHandler testMachine:self didTrapAtAddress:address]; } +- (BOOL)isHalted { + return _processor.get_halt_line() ? YES : NO; +} + #pragma mark - Z80-specific Runner - (void)runToNextInstruction { diff --git a/OSBindings/Mac/Clock SignalTests/FUSETests.swift b/OSBindings/Mac/Clock SignalTests/FUSETests.swift index 68ce9a7ba..004bfed6e 100644 --- a/OSBindings/Mac/Clock SignalTests/FUSETests.swift +++ b/OSBindings/Mac/Clock SignalTests/FUSETests.swift @@ -113,8 +113,8 @@ fileprivate struct RegisterState { interruptMode = Int(machine.value(for: .IM)) - isHalted = false // TODO - tStates = 0 // TODO + isHalted = machine.isHalted + tStates = 0 // TODO (?) } } @@ -137,7 +137,8 @@ fileprivate func ==(lhs: RegisterState, rhs: RegisterState) -> Bool { lhs.r == rhs.r && lhs.iff1 == rhs.iff1 && lhs.iff2 == rhs.iff2 && - lhs.interruptMode == rhs.interruptMode + lhs.interruptMode == rhs.interruptMode && + lhs.isHalted == rhs.isHalted } class FUSETests: XCTestCase { diff --git a/Processors/Z80/Z80.hpp b/Processors/Z80/Z80.hpp index 95a86f0e4..116d4181a 100644 --- a/Processors/Z80/Z80.hpp +++ b/Processors/Z80/Z80.hpp @@ -129,7 +129,9 @@ struct MicroOp { SetInstructionPage, CalculateIndexAddress, + RETN, + HALT, DJNZ, DAA, @@ -177,6 +179,7 @@ template class Processor: public MicroOpScheduler { bool iff1_, iff2_; int interrupt_mode_; uint8_t sign_result_, zero_result_, bit5_result_, half_carry_flag_, bit3_result_, parity_overflow_flag_, subtract_flag_, carry_flag_; + bool is_halted_; int number_of_cycles_; @@ -547,7 +550,7 @@ template class Processor: public MicroOpScheduler { /* 0x73 LD (HL), E */ Program(INDEX(), STOREL(de_.bytes.low, INDEX_ADDR())), /* 0x74 LD (HL), H */ Program(INDEX(), STOREL(hl_.bytes.high, INDEX_ADDR())), // neither of these stores parts of the index register; /* 0x75 LD (HL), L */ Program(INDEX(), STOREL(hl_.bytes.low, INDEX_ADDR())), // they always store exactly H and L. - /* 0x76 HALT */ XX, + /* 0x76 HALT */ Program({MicroOp::HALT}), /* 0x77 LD (HL), A */ Program(INDEX(), STOREL(a_, INDEX_ADDR())), /* 0x78 LD A, B; 0x79 LD A, C; 0x7a LD A, D; 0x7b LD A, E; 0x7c LD A, H; 0x7d LD A, L; 0x7e LD A, (HL); 0x7f LD A, A */ @@ -641,7 +644,7 @@ template class Processor: public MicroOpScheduler { } public: - Processor() : MicroOpScheduler() { + Processor() : MicroOpScheduler(), is_halted_(false) { assemble_base_page(base_page_, hl_, false, cb_page_); assemble_base_page(dd_page_, ix_, true, ddcb_page_); assemble_base_page(fd_page_, iy_, true, fdcb_page_); @@ -1374,12 +1377,17 @@ template class Processor: public MicroOpScheduler { temp8_ = 0; break; -#pragma mark - Return +#pragma mark - Special-case Flow case MicroOp::RETN: iff1_ = iff2_; break; + case MicroOp::HALT: + is_halted_ = true; + pc_.full --; + break; + #pragma mark - Internal bookkeeping case MicroOp::SetInstructionPage: @@ -1570,6 +1578,13 @@ template class Processor: public MicroOpScheduler { default: break; } } + + /*! + Gets the value of the HALT output line. + */ + bool get_halt_line() { + return is_halted_; + } }; }