diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 8d2395e20..2b38f5ab1 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -559,7 +559,6 @@ 4B6C73BC1D387AE500AFCFCA /* DiskController.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskController.hpp; sourceTree = ""; }; 4B77069B1EC904570053B588 /* Z80.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Z80.cpp; path = Z80/Z80.cpp; sourceTree = ""; }; 4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80.hpp; path = Z80/Z80.hpp; sourceTree = ""; }; - 4B7706A01EC9398D0053B588 /* MicroOpScheduler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MicroOpScheduler.hpp; sourceTree = ""; }; 4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = Electron/Video.cpp; sourceTree = ""; }; 4B7913CB1DFCD80E00175A82 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = Electron/Video.hpp; sourceTree = ""; }; 4B79E4411E3AF38600141F11 /* cassette.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cassette.png; sourceTree = ""; }; @@ -1838,7 +1837,6 @@ children = ( 4B1414561B58879D00E04248 /* 6502 */, 4B77069E1EC9045B0053B588 /* Z80 */, - 4B7706A01EC9398D0053B588 /* MicroOpScheduler.hpp */, 4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */, 4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */, 4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */, diff --git a/Processors/6502/6502.hpp b/Processors/6502/6502.hpp index 80a288fd1..9250405e4 100644 --- a/Processors/6502/6502.hpp +++ b/Processors/6502/6502.hpp @@ -12,7 +12,6 @@ #include #include -#include "../MicroOpScheduler.hpp" #include "../RegisterSizes.hpp" namespace CPU { @@ -67,51 +66,6 @@ enum BusOperation { */ extern const uint8_t JamOpcode; -/* - This emulation functions by decomposing instructions into micro programs, consisting of the micro operations - as per the enum below. Each micro op takes at most one cycle. By convention, those called CycleX take a cycle - to perform whereas those called OperationX occur for free (so, in effect, their cost is loaded onto the next cycle). -*/ -enum MicroOp { - CycleFetchOperation, CycleFetchOperand, OperationDecodeOperation, CycleIncPCPushPCH, - CyclePushPCH, CyclePushPCL, CyclePushA, CyclePushOperand, - OperationSetI, - - OperationBRKPickVector, OperationNMIPickVector, OperationRSTPickVector, - CycleReadVectorLow, CycleReadVectorHigh, - - CycleReadFromS, CycleReadFromPC, - CyclePullOperand, CyclePullPCL, CyclePullPCH, CyclePullA, - CycleNoWritePush, - CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL, - CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute, - OperationLoadAddressZeroPage, CycleLoadAddessZeroX, CycleLoadAddessZeroY, CycleAddXToAddressLow, - CycleAddYToAddressLow, CycleAddXToAddressLowRead, OperationCorrectAddressHigh, CycleAddYToAddressLowRead, - OperationMoveToNextProgram, OperationIncrementPC, - CycleFetchOperandFromAddress, CycleWriteOperandToAddress, OperationCopyOperandFromA, OperationCopyOperandToA, - CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh, OperationDecrementOperand, - OperationIncrementOperand, OperationORA, OperationAND, OperationEOR, - OperationINS, OperationADC, OperationSBC, OperationLDA, - OperationLDX, OperationLDY, OperationLAX, OperationSTA, - OperationSTX, OperationSTY, OperationSAX, OperationSHA, - OperationSHX, OperationSHY, OperationSHS, OperationCMP, - OperationCPX, OperationCPY, OperationBIT, OperationASL, - OperationASO, OperationROL, OperationRLA, OperationLSR, - OperationLSE, OperationASR, OperationROR, OperationRRA, - OperationCLC, OperationCLI, OperationCLV, OperationCLD, - OperationSEC, OperationSEI, OperationSED, OperationINC, - OperationDEC, OperationINX, OperationDEX, OperationINY, - OperationDEY, OperationBPL, OperationBMI, OperationBVC, - OperationBVS, OperationBCC, OperationBCS, OperationBNE, - OperationBEQ, OperationTXA, OperationTYA, OperationTXS, - OperationTAY, OperationTAX, OperationTSX, OperationARR, - OperationSBX, OperationLXA, OperationANE, OperationANC, - OperationLAS, CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, - OperationSetOperandFromFlags, - OperationSetFlagsFromA, - CycleScheduleJam -}; - /*! @abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism. @@ -123,7 +77,7 @@ enum MicroOp { that will cause call outs when the program counter reaches those addresses. @c return_from_subroutine can be used to exit from a jammed state. */ -template class Processor: public MicroOpScheduler { +template class Processor { public: class JamHandler { @@ -133,7 +87,53 @@ template class Processor: public MicroOpScheduler { private: -#define JAM {CycleFetchOperand, CycleScheduleJam, OperationMoveToNextProgram} + /* + This emulation functions by decomposing instructions into micro programs, consisting of the micro operations + as per the enum below. Each micro op takes at most one cycle. By convention, those called CycleX take a cycle + to perform whereas those called OperationX occur for free (so, in effect, their cost is loaded onto the next cycle). + */ + enum MicroOp { + CycleFetchOperation, CycleFetchOperand, OperationDecodeOperation, CycleIncPCPushPCH, + CyclePushPCH, CyclePushPCL, CyclePushA, CyclePushOperand, + OperationSetI, + + OperationBRKPickVector, OperationNMIPickVector, OperationRSTPickVector, + CycleReadVectorLow, CycleReadVectorHigh, + + CycleReadFromS, CycleReadFromPC, + CyclePullOperand, CyclePullPCL, CyclePullPCH, CyclePullA, + CycleNoWritePush, + CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL, + CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute, + OperationLoadAddressZeroPage, CycleLoadAddessZeroX, CycleLoadAddessZeroY, CycleAddXToAddressLow, + CycleAddYToAddressLow, CycleAddXToAddressLowRead, OperationCorrectAddressHigh, CycleAddYToAddressLowRead, + OperationMoveToNextProgram, OperationIncrementPC, + CycleFetchOperandFromAddress, CycleWriteOperandToAddress, OperationCopyOperandFromA, OperationCopyOperandToA, + CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh, OperationDecrementOperand, + OperationIncrementOperand, OperationORA, OperationAND, OperationEOR, + OperationINS, OperationADC, OperationSBC, OperationLDA, + OperationLDX, OperationLDY, OperationLAX, OperationSTA, + OperationSTX, OperationSTY, OperationSAX, OperationSHA, + OperationSHX, OperationSHY, OperationSHS, OperationCMP, + OperationCPX, OperationCPY, OperationBIT, OperationASL, + OperationASO, OperationROL, OperationRLA, OperationLSR, + OperationLSE, OperationASR, OperationROR, OperationRRA, + OperationCLC, OperationCLI, OperationCLV, OperationCLD, + OperationSEC, OperationSEI, OperationSED, OperationINC, + OperationDEC, OperationINX, OperationDEX, OperationINY, + OperationDEY, OperationBPL, OperationBMI, OperationBVC, + OperationBVS, OperationBCC, OperationBCS, OperationBNE, + OperationBEQ, OperationTXA, OperationTYA, OperationTXS, + OperationTAY, OperationTAX, OperationTSX, OperationARR, + OperationSBX, OperationLXA, OperationANE, OperationANC, + OperationLAS, CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, + OperationSetOperandFromFlags, + OperationSetFlagsFromA, + CycleScheduleJam + }; + const MicroOp *scheduled_program_counter_; + +#define JAM {CycleFetchOperand, CycleScheduleJam} /* Storage for the 6502 registers; F is stored as individual flags. @@ -422,7 +422,7 @@ template class Processor: public MicroOpScheduler { #undef Immediate #undef Implied - schedule_program(operations[operation]); + scheduled_program_counter_ = operations[operation]; } bool is_jammed_; @@ -522,7 +522,8 @@ template class Processor: public MicroOpScheduler { interrupt_requests_(InterruptRequestFlags::PowerOn), irq_line_(0), nmi_line_is_enabled_(false), - set_overflow_line_is_enabled_(false) { + set_overflow_line_is_enabled_(false), + scheduled_program_counter_(nullptr) { // only the interrupt flag is defined upon reset but get_flags isn't going to // mask the other flags so we need to do that, at least carry_flag_ &= Flag::Carry; @@ -550,8 +551,7 @@ template class Processor: public MicroOpScheduler { static const MicroOp fetch_decode_execute[] = { CycleFetchOperation, CycleFetchOperand, - OperationDecodeOperation, - OperationMoveToNextProgram + OperationDecodeOperation }; // These plus program below act to give the compiler permission to update these values @@ -564,19 +564,18 @@ template class Processor: public MicroOpScheduler { #define checkSchedule(op) \ if(!scheduled_program_counter_) {\ - schedule_programs_read_pointer_ = schedule_programs_write_pointer_ = 0; \ if(interrupt_requests_) {\ if(interrupt_requests_ & (InterruptRequestFlags::Reset | InterruptRequestFlags::PowerOn)) {\ interrupt_requests_ &= ~InterruptRequestFlags::PowerOn;\ - schedule_program(get_reset_program());\ + scheduled_program_counter_ = get_reset_program();\ } else if(interrupt_requests_ & InterruptRequestFlags::NMI) {\ interrupt_requests_ &= ~InterruptRequestFlags::NMI;\ - schedule_program(get_nmi_program());\ + scheduled_program_counter_ = get_nmi_program();\ } else if(interrupt_requests_ & InterruptRequestFlags::IRQ) {\ - schedule_program(get_irq_program());\ + scheduled_program_counter_ = get_irq_program();\ } \ } else {\ - schedule_program(fetch_decode_execute);\ + scheduled_program_counter_ = fetch_decode_execute;\ }\ op;\ } @@ -644,7 +643,7 @@ template class Processor: public MicroOpScheduler { continue; case OperationMoveToNextProgram: - move_to_next_program(); + scheduled_program_counter_ = nullptr; checkSchedule(); continue; @@ -704,7 +703,7 @@ template class Processor: public MicroOpScheduler { case CycleScheduleJam: { is_jammed_ = true; static const MicroOp jam[] = JAM; - schedule_program(jam); + scheduled_program_counter_ = jam; if(jam_handler_) { jam_handler_->processor_did_jam(this, pc_.full - 1); @@ -1003,7 +1002,7 @@ template class Processor: public MicroOpScheduler { #pragma mark - Branching -#define BRA(condition) pc_.full++; if(condition) schedule_program(doBranch) +#define BRA(condition) pc_.full++; if(condition) scheduled_program_counter_ = doBranch case OperationBPL: BRA(!(negative_result_&0x80)); continue; case OperationBMI: BRA(negative_result_&0x80); continue; @@ -1145,7 +1144,6 @@ template class Processor: public MicroOpScheduler { pc_.full++; if(is_jammed_) { - scheduled_programs_[0] = scheduled_programs_[1] = scheduled_programs_[2] = scheduled_programs_[3] = nullptr; scheduled_program_counter_ = nullptr; } } diff --git a/Processors/6502/6502AllRAM.cpp b/Processors/6502/6502AllRAM.cpp index 66d386b8a..7c822616f 100644 --- a/Processors/6502/6502AllRAM.cpp +++ b/Processors/6502/6502AllRAM.cpp @@ -19,6 +19,8 @@ AllRAMProcessor::AllRAMProcessor() : ::CPU::AllRAMProcessor(65536) { int AllRAMProcessor::perform_bus_operation(MOS6502::BusOperation operation, uint16_t address, uint8_t *value) { timestamp_++; +// if(operation == MOS6502::BusOperation::ReadOpcode) printf("%04x\n", address); + if(isReadOperation(operation)) { *value = memory_[address]; } else { diff --git a/Processors/MicroOpScheduler.hpp b/Processors/MicroOpScheduler.hpp deleted file mode 100644 index 846fce754..000000000 --- a/Processors/MicroOpScheduler.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// MicroOpScheduler.hpp -// Clock Signal -// -// Created by Thomas Harte on 14/05/2017. -// Copyright © 2017 Thomas Harte. All rights reserved. -// - -#ifndef MicroOpScheduler_hpp -#define MicroOpScheduler_hpp - -namespace CPU { - -template class MicroOpScheduler { - public: - MicroOpScheduler() : - scheduled_programs_{nullptr, nullptr, nullptr, nullptr}, - schedule_programs_write_pointer_(0), - schedule_programs_read_pointer_(0), - scheduled_program_counter_(nullptr) {} - - protected: - /* - Up to four programs can be scheduled; each will be carried out in turn. This - storage maintains pointers to the scheduled list of programs. - - Programs should be terminated by an OperationMoveToNextProgram, causing this - queue to take that step. - */ - const T *scheduled_programs_[4]; - const T *scheduled_program_counter_; - unsigned int schedule_programs_write_pointer_, schedule_programs_read_pointer_; - - /*! - Schedules a new program, adding it to the end of the queue. Programs should be - terminated with a OperationMoveToNextProgram. No attempt to copy the program - is made; a non-owning reference is kept. - - @param program The program to schedule. - */ - inline void schedule_program(const T *program) { - scheduled_programs_[schedule_programs_write_pointer_] = program; - if(schedule_programs_write_pointer_ == schedule_programs_read_pointer_) scheduled_program_counter_ = program; - schedule_programs_write_pointer_ = (schedule_programs_write_pointer_+1)&3; - } - - inline void move_to_next_program() { - scheduled_programs_[schedule_programs_read_pointer_] = nullptr; - schedule_programs_read_pointer_ = (schedule_programs_read_pointer_+1)&3; - scheduled_program_counter_ = scheduled_programs_[schedule_programs_read_pointer_]; - } -}; - -} - -#endif /* MicroOpScheduler_hpp */