mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 18:30:21 +00:00
Plumbed through to allow interrupt tests, wrote an NMI test, corrected the error revealed.
This commit is contained in:
parent
a2ec902773
commit
3e9212aaff
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
4B049CDD1DA3C82F00322067 /* BCDTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B049CDC1DA3C82F00322067 /* BCDTest.swift */; };
|
4B049CDD1DA3C82F00322067 /* BCDTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B049CDC1DA3C82F00322067 /* BCDTest.swift */; };
|
||||||
|
4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */; };
|
||||||
4B0BE4281D3481E700D5256B /* DigitalPhaseLockedLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0BE4261D3481E700D5256B /* DigitalPhaseLockedLoop.cpp */; };
|
4B0BE4281D3481E700D5256B /* DigitalPhaseLockedLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0BE4261D3481E700D5256B /* DigitalPhaseLockedLoop.cpp */; };
|
||||||
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; };
|
4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; };
|
||||||
4B121F951E05E66800BFDA12 /* PCMPatchedTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B121F941E05E66800BFDA12 /* PCMPatchedTrackTests.mm */; };
|
4B121F951E05E66800BFDA12 /* PCMPatchedTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B121F941E05E66800BFDA12 /* PCMPatchedTrackTests.mm */; };
|
||||||
@ -442,6 +443,7 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = "<group>"; };
|
4B046DC31CFE651500E9E45E /* CRTMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRTMachine.hpp; sourceTree = "<group>"; };
|
||||||
4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = "<group>"; };
|
4B049CDC1DA3C82F00322067 /* BCDTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BCDTest.swift; sourceTree = "<group>"; };
|
||||||
|
4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80InterruptTests.swift; sourceTree = "<group>"; };
|
||||||
4B0B6E121C9DBD5D00FFB60D /* CRTConstants.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CRTConstants.hpp; sourceTree = "<group>"; };
|
4B0B6E121C9DBD5D00FFB60D /* CRTConstants.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CRTConstants.hpp; sourceTree = "<group>"; };
|
||||||
4B0BE4261D3481E700D5256B /* DigitalPhaseLockedLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DigitalPhaseLockedLoop.cpp; sourceTree = "<group>"; };
|
4B0BE4261D3481E700D5256B /* DigitalPhaseLockedLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DigitalPhaseLockedLoop.cpp; sourceTree = "<group>"; };
|
||||||
4B0BE4271D3481E700D5256B /* DigitalPhaseLockedLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DigitalPhaseLockedLoop.hpp; sourceTree = "<group>"; };
|
4B0BE4271D3481E700D5256B /* DigitalPhaseLockedLoop.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DigitalPhaseLockedLoop.hpp; sourceTree = "<group>"; };
|
||||||
@ -1795,6 +1797,7 @@
|
|||||||
4BBF49AE1ED2880200AB3669 /* FUSETests.swift */,
|
4BBF49AE1ED2880200AB3669 /* FUSETests.swift */,
|
||||||
4B1414611B58888700E04248 /* KlausDormannTests.swift */,
|
4B1414611B58888700E04248 /* KlausDormannTests.swift */,
|
||||||
4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */,
|
4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */,
|
||||||
|
4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */,
|
||||||
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */,
|
4BFCA12A1ECBE7C400AC40C1 /* ZexallTests.swift */,
|
||||||
4B3BA0C41D318B44005DD7A7 /* Bridges */,
|
4B3BA0C41D318B44005DD7A7 /* Bridges */,
|
||||||
4B1414631B588A1100E04248 /* Test Binaries */,
|
4B1414631B588A1100E04248 /* Test Binaries */,
|
||||||
@ -2599,6 +2602,7 @@
|
|||||||
4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */,
|
4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */,
|
||||||
4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */,
|
4BEF6AAA1D35CE9E00E73575 /* DigitalPhaseLockedLoopBridge.mm in Sources */,
|
||||||
4B924E991E74D22700B76AF1 /* AtariStaticAnalyserTests.mm in Sources */,
|
4B924E991E74D22700B76AF1 /* AtariStaticAnalyserTests.mm in Sources */,
|
||||||
|
4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */,
|
||||||
4BFCA1241ECBDCB400AC40C1 /* AllRAMProcessor.cpp in Sources */,
|
4BFCA1241ECBDCB400AC40C1 /* AllRAMProcessor.cpp in Sources */,
|
||||||
4B50730A1DDFCFDF00C48FBD /* ArrayBuilderTests.mm in Sources */,
|
4B50730A1DDFCFDF00C48FBD /* ArrayBuilderTests.mm in Sources */,
|
||||||
4BBF49AF1ED2880200AB3669 /* FUSETests.swift in Sources */,
|
4BBF49AF1ED2880200AB3669 /* FUSETests.swift in Sources */,
|
||||||
|
@ -66,4 +66,7 @@ typedef NS_ENUM(NSInteger, CSTestMachineZ80Register) {
|
|||||||
|
|
||||||
@property(nonatomic, readonly) BOOL isHalted;
|
@property(nonatomic, readonly) BOOL isHalted;
|
||||||
|
|
||||||
|
@property(nonatomic) BOOL nmiLine;
|
||||||
|
@property(nonatomic) BOOL irqLine;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -173,6 +173,16 @@ static CPU::Z80::Register registerForRegister(CSTestMachineZ80Register reg) {
|
|||||||
return _processor->get_halt_line() ? YES : NO;
|
return _processor->get_halt_line() ? YES : NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setNmiLine:(BOOL)nmiLine {
|
||||||
|
_nmiLine = nmiLine;
|
||||||
|
_processor->set_non_maskable_interrupt_line(nmiLine ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setIrqLine:(BOOL)irqLine {
|
||||||
|
_irqLine = irqLine;
|
||||||
|
_processor->set_interrupt_line(irqLine ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Z80-specific Runner
|
#pragma mark - Z80-specific Runner
|
||||||
|
|
||||||
- (void)runToNextInstruction {
|
- (void)runToNextInstruction {
|
||||||
|
45
OSBindings/Mac/Clock SignalTests/Z80InterruptTests.swift
Normal file
45
OSBindings/Mac/Clock SignalTests/Z80InterruptTests.swift
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// Z80InterruptTests.swift
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 03/06/2017.
|
||||||
|
// Copyright © 2017 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
class Z80InterruptTests: XCTestCase {
|
||||||
|
|
||||||
|
func testNMI() {
|
||||||
|
let machine = CSTestMachineZ80()
|
||||||
|
|
||||||
|
// start the PC at 0x0100 and install two NOPs for it
|
||||||
|
machine.setValue(0x0100, for: .programCounter)
|
||||||
|
machine.setValue(0, for: .IFF1)
|
||||||
|
machine.setValue(1, for: .IFF2)
|
||||||
|
machine.setValue(0x00, atAddress: 0x0100)
|
||||||
|
machine.setValue(0x00, atAddress: 0x0101)
|
||||||
|
|
||||||
|
// put the stack at the top of memory
|
||||||
|
machine.setValue(0, for: .stackPointer)
|
||||||
|
|
||||||
|
// run for four cycles, and signal an NMI
|
||||||
|
machine.runForNumber(ofCycles: 4)
|
||||||
|
machine.nmiLine = true
|
||||||
|
|
||||||
|
// run for four more cycles to get to where the NMI should be recognised
|
||||||
|
machine.runForNumber(ofCycles: 4)
|
||||||
|
XCTAssertEqual(machine.value(for: .programCounter), 0x0102)
|
||||||
|
|
||||||
|
// run for eleven more cycles to allow the NMI to begin
|
||||||
|
machine.runForNumber(ofCycles: 11)
|
||||||
|
|
||||||
|
// confirm that the PC is now at 0x66, that the old is on the stack and
|
||||||
|
// that IFF1 has migrated to IFF2
|
||||||
|
XCTAssertEqual(machine.value(for: .programCounter), 0x66)
|
||||||
|
XCTAssertEqual(machine.value(atAddress: 0xffff), 0x01)
|
||||||
|
XCTAssertEqual(machine.value(atAddress: 0xfffe), 0x02)
|
||||||
|
XCTAssertEqual(machine.value(for: .IFF2), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -136,6 +136,7 @@ struct MicroOp {
|
|||||||
BeginIRQ,
|
BeginIRQ,
|
||||||
BeginIRQMode0,
|
BeginIRQMode0,
|
||||||
RETN,
|
RETN,
|
||||||
|
JumpTo66,
|
||||||
HALT,
|
HALT,
|
||||||
|
|
||||||
DJNZ,
|
DJNZ,
|
||||||
@ -701,6 +702,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
{ MicroOp::BeginNMI },
|
{ MicroOp::BeginNMI },
|
||||||
{ MicroOp::BusOperation, nullptr, nullptr, {ReadOpcode, 5, &pc_.full, &operation_}},
|
{ MicroOp::BusOperation, nullptr, nullptr, {ReadOpcode, 5, &pc_.full, &operation_}},
|
||||||
PUSH(pc_),
|
PUSH(pc_),
|
||||||
|
{ MicroOp::JumpTo66, nullptr, nullptr},
|
||||||
{ MicroOp::MoveToNextProgram }
|
{ MicroOp::MoveToNextProgram }
|
||||||
};
|
};
|
||||||
MicroOp irq_mode0_program[] = {
|
MicroOp irq_mode0_program[] = {
|
||||||
@ -1476,6 +1478,10 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
request_status_ &= ~Interrupt::IRQ;
|
request_status_ &= ~Interrupt::IRQ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MicroOp::JumpTo66:
|
||||||
|
pc_.full = 0x66;
|
||||||
|
break;
|
||||||
|
|
||||||
case MicroOp::RETN:
|
case MicroOp::RETN:
|
||||||
iff1_ = iff2_;
|
iff1_ = iff2_;
|
||||||
if(irq_line_ && iff1_) request_status_ |= Interrupt::IRQ;
|
if(irq_line_ && iff1_) request_status_ |= Interrupt::IRQ;
|
||||||
|
@ -74,6 +74,14 @@ class ConcreteAllRAMProcessor: public AllRAMProcessor, public Processor<Concrete
|
|||||||
void reset_power_on() {
|
void reset_power_on() {
|
||||||
return CPU::Z80::Processor<ConcreteAllRAMProcessor>::reset_power_on();
|
return CPU::Z80::Processor<ConcreteAllRAMProcessor>::reset_power_on();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_interrupt_line(bool value) {
|
||||||
|
CPU::Z80::Processor<ConcreteAllRAMProcessor>::set_interrupt_line(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_non_maskable_interrupt_line(bool value) {
|
||||||
|
CPU::Z80::Processor<ConcreteAllRAMProcessor>::set_non_maskable_interrupt_line(value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ class AllRAMProcessor:
|
|||||||
virtual void set_value_of_register(Register r, uint16_t value) = 0;
|
virtual void set_value_of_register(Register r, uint16_t value) = 0;
|
||||||
virtual bool get_halt_line() = 0;
|
virtual bool get_halt_line() = 0;
|
||||||
virtual void reset_power_on() = 0;
|
virtual void reset_power_on() = 0;
|
||||||
|
virtual void set_interrupt_line(bool value) = 0;
|
||||||
|
virtual void set_non_maskable_interrupt_line(bool value) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MemoryAccessDelegate *delegate_;
|
MemoryAccessDelegate *delegate_;
|
||||||
|
Loading…
Reference in New Issue
Block a user