mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 15:31:09 +00:00
Merge pull request #128 from TomHarte/Scheduling
Eliminates the micro-op scheduler
This commit is contained in:
commit
0b2a3f18bc
@ -559,7 +559,6 @@
|
|||||||
4B6C73BC1D387AE500AFCFCA /* DiskController.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskController.hpp; sourceTree = "<group>"; };
|
4B6C73BC1D387AE500AFCFCA /* DiskController.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DiskController.hpp; sourceTree = "<group>"; };
|
||||||
4B77069B1EC904570053B588 /* Z80.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Z80.cpp; path = Z80/Z80.cpp; sourceTree = "<group>"; };
|
4B77069B1EC904570053B588 /* Z80.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Z80.cpp; path = Z80/Z80.cpp; sourceTree = "<group>"; };
|
||||||
4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80.hpp; path = Z80/Z80.hpp; sourceTree = "<group>"; };
|
4B77069C1EC904570053B588 /* Z80.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Z80.hpp; path = Z80/Z80.hpp; sourceTree = "<group>"; };
|
||||||
4B7706A01EC9398D0053B588 /* MicroOpScheduler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MicroOpScheduler.hpp; sourceTree = "<group>"; };
|
|
||||||
4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = Electron/Video.cpp; sourceTree = "<group>"; };
|
4B7913CA1DFCD80E00175A82 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = Electron/Video.cpp; sourceTree = "<group>"; };
|
||||||
4B7913CB1DFCD80E00175A82 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = Electron/Video.hpp; sourceTree = "<group>"; };
|
4B7913CB1DFCD80E00175A82 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = Electron/Video.hpp; sourceTree = "<group>"; };
|
||||||
4B79E4411E3AF38600141F11 /* cassette.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cassette.png; sourceTree = "<group>"; };
|
4B79E4411E3AF38600141F11 /* cassette.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = cassette.png; sourceTree = "<group>"; };
|
||||||
@ -1838,7 +1837,6 @@
|
|||||||
children = (
|
children = (
|
||||||
4B1414561B58879D00E04248 /* 6502 */,
|
4B1414561B58879D00E04248 /* 6502 */,
|
||||||
4B77069E1EC9045B0053B588 /* Z80 */,
|
4B77069E1EC9045B0053B588 /* Z80 */,
|
||||||
4B7706A01EC9398D0053B588 /* MicroOpScheduler.hpp */,
|
|
||||||
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */,
|
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */,
|
||||||
4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */,
|
4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */,
|
||||||
4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */,
|
4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */,
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../MicroOpScheduler.hpp"
|
|
||||||
#include "../RegisterSizes.hpp"
|
#include "../RegisterSizes.hpp"
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
@ -67,12 +66,33 @@ enum BusOperation {
|
|||||||
*/
|
*/
|
||||||
extern const uint8_t JamOpcode;
|
extern const uint8_t JamOpcode;
|
||||||
|
|
||||||
/*
|
/*!
|
||||||
|
@abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism.
|
||||||
|
|
||||||
|
@discussion Subclasses should implement @c perform_bus_operation(BusOperation operation, uint16_t address, uint8_t *value) in
|
||||||
|
order to provide the bus on which the 6502 operates and @c flush(), which is called upon completion of a continuous run
|
||||||
|
of cycles to allow a subclass to bring any on-demand activities up to date.
|
||||||
|
|
||||||
|
Additional functionality can be provided by the host machine by providing a jam handler and inserting jam opcodes where appropriate;
|
||||||
|
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 T> class Processor {
|
||||||
|
public:
|
||||||
|
|
||||||
|
class JamHandler {
|
||||||
|
public:
|
||||||
|
virtual void processor_did_jam(Processor *processor, uint16_t address) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
This emulation functions by decomposing instructions into micro programs, consisting of the micro operations
|
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
|
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).
|
to perform whereas those called OperationX occur for free (so, in effect, their cost is loaded onto the next cycle).
|
||||||
*/
|
*/
|
||||||
enum MicroOp {
|
enum MicroOp {
|
||||||
CycleFetchOperation, CycleFetchOperand, OperationDecodeOperation, CycleIncPCPushPCH,
|
CycleFetchOperation, CycleFetchOperand, OperationDecodeOperation, CycleIncPCPushPCH,
|
||||||
CyclePushPCH, CyclePushPCL, CyclePushA, CyclePushOperand,
|
CyclePushPCH, CyclePushPCL, CyclePushA, CyclePushOperand,
|
||||||
OperationSetI,
|
OperationSetI,
|
||||||
@ -110,30 +130,10 @@ enum MicroOp {
|
|||||||
OperationSetOperandFromFlags,
|
OperationSetOperandFromFlags,
|
||||||
OperationSetFlagsFromA,
|
OperationSetFlagsFromA,
|
||||||
CycleScheduleJam
|
CycleScheduleJam
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism.
|
|
||||||
|
|
||||||
@discussion Subclasses should implement @c perform_bus_operation(BusOperation operation, uint16_t address, uint8_t *value) in
|
|
||||||
order to provide the bus on which the 6502 operates and @c flush(), which is called upon completion of a continuous run
|
|
||||||
of cycles to allow a subclass to bring any on-demand activities up to date.
|
|
||||||
|
|
||||||
Additional functionality can be provided by the host machine by providing a jam handler and inserting jam opcodes where appropriate;
|
|
||||||
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 T> class Processor: public MicroOpScheduler<MicroOp> {
|
|
||||||
public:
|
|
||||||
|
|
||||||
class JamHandler {
|
|
||||||
public:
|
|
||||||
virtual void processor_did_jam(Processor *processor, uint16_t address) = 0;
|
|
||||||
};
|
};
|
||||||
|
const MicroOp *scheduled_program_counter_;
|
||||||
|
|
||||||
private:
|
#define JAM {CycleFetchOperand, CycleScheduleJam}
|
||||||
|
|
||||||
#define JAM {CycleFetchOperand, CycleScheduleJam, OperationMoveToNextProgram}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Storage for the 6502 registers; F is stored as individual flags.
|
Storage for the 6502 registers; F is stored as individual flags.
|
||||||
@ -422,7 +422,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
#undef Immediate
|
#undef Immediate
|
||||||
#undef Implied
|
#undef Implied
|
||||||
|
|
||||||
schedule_program(operations[operation]);
|
scheduled_program_counter_ = operations[operation];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_jammed_;
|
bool is_jammed_;
|
||||||
@ -522,7 +522,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
interrupt_requests_(InterruptRequestFlags::PowerOn),
|
interrupt_requests_(InterruptRequestFlags::PowerOn),
|
||||||
irq_line_(0),
|
irq_line_(0),
|
||||||
nmi_line_is_enabled_(false),
|
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
|
// 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
|
// mask the other flags so we need to do that, at least
|
||||||
carry_flag_ &= Flag::Carry;
|
carry_flag_ &= Flag::Carry;
|
||||||
@ -550,8 +551,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
static const MicroOp fetch_decode_execute[] = {
|
static const MicroOp fetch_decode_execute[] = {
|
||||||
CycleFetchOperation,
|
CycleFetchOperation,
|
||||||
CycleFetchOperand,
|
CycleFetchOperand,
|
||||||
OperationDecodeOperation,
|
OperationDecodeOperation
|
||||||
OperationMoveToNextProgram
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// These plus program below act to give the compiler permission to update these values
|
// These plus program below act to give the compiler permission to update these values
|
||||||
@ -564,19 +564,18 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
|
|
||||||
#define checkSchedule(op) \
|
#define checkSchedule(op) \
|
||||||
if(!scheduled_program_counter_) {\
|
if(!scheduled_program_counter_) {\
|
||||||
schedule_programs_read_pointer_ = schedule_programs_write_pointer_ = 0; \
|
|
||||||
if(interrupt_requests_) {\
|
if(interrupt_requests_) {\
|
||||||
if(interrupt_requests_ & (InterruptRequestFlags::Reset | InterruptRequestFlags::PowerOn)) {\
|
if(interrupt_requests_ & (InterruptRequestFlags::Reset | InterruptRequestFlags::PowerOn)) {\
|
||||||
interrupt_requests_ &= ~InterruptRequestFlags::PowerOn;\
|
interrupt_requests_ &= ~InterruptRequestFlags::PowerOn;\
|
||||||
schedule_program(get_reset_program());\
|
scheduled_program_counter_ = get_reset_program();\
|
||||||
} else if(interrupt_requests_ & InterruptRequestFlags::NMI) {\
|
} else if(interrupt_requests_ & InterruptRequestFlags::NMI) {\
|
||||||
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) {\
|
} else if(interrupt_requests_ & InterruptRequestFlags::IRQ) {\
|
||||||
schedule_program(get_irq_program());\
|
scheduled_program_counter_ = get_irq_program();\
|
||||||
} \
|
} \
|
||||||
} else {\
|
} else {\
|
||||||
schedule_program(fetch_decode_execute);\
|
scheduled_program_counter_ = fetch_decode_execute;\
|
||||||
}\
|
}\
|
||||||
op;\
|
op;\
|
||||||
}
|
}
|
||||||
@ -644,7 +643,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OperationMoveToNextProgram:
|
case OperationMoveToNextProgram:
|
||||||
move_to_next_program();
|
scheduled_program_counter_ = nullptr;
|
||||||
checkSchedule();
|
checkSchedule();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -704,7 +703,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
case CycleScheduleJam: {
|
case CycleScheduleJam: {
|
||||||
is_jammed_ = true;
|
is_jammed_ = true;
|
||||||
static const MicroOp jam[] = JAM;
|
static const MicroOp jam[] = JAM;
|
||||||
schedule_program(jam);
|
scheduled_program_counter_ = jam;
|
||||||
|
|
||||||
if(jam_handler_) {
|
if(jam_handler_) {
|
||||||
jam_handler_->processor_did_jam(this, pc_.full - 1);
|
jam_handler_->processor_did_jam(this, pc_.full - 1);
|
||||||
@ -1003,7 +1002,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
|
|
||||||
#pragma mark - Branching
|
#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 OperationBPL: BRA(!(negative_result_&0x80)); continue;
|
||||||
case OperationBMI: BRA(negative_result_&0x80); continue;
|
case OperationBMI: BRA(negative_result_&0x80); continue;
|
||||||
@ -1145,7 +1144,6 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
pc_.full++;
|
pc_.full++;
|
||||||
|
|
||||||
if(is_jammed_) {
|
if(is_jammed_) {
|
||||||
scheduled_programs_[0] = scheduled_programs_[1] = scheduled_programs_[2] = scheduled_programs_[3] = nullptr;
|
|
||||||
scheduled_program_counter_ = nullptr;
|
scheduled_program_counter_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ AllRAMProcessor::AllRAMProcessor() : ::CPU::AllRAMProcessor(65536) {
|
|||||||
int AllRAMProcessor::perform_bus_operation(MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
int AllRAMProcessor::perform_bus_operation(MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
|
||||||
timestamp_++;
|
timestamp_++;
|
||||||
|
|
||||||
|
// if(operation == MOS6502::BusOperation::ReadOpcode) printf("%04x\n", address);
|
||||||
|
|
||||||
if(isReadOperation(operation)) {
|
if(isReadOperation(operation)) {
|
||||||
*value = memory_[address];
|
*value = memory_[address];
|
||||||
} else {
|
} else {
|
||||||
|
@ -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 T> 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 */
|
|
@ -14,7 +14,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../MicroOpScheduler.hpp"
|
|
||||||
#include "../RegisterSizes.hpp"
|
#include "../RegisterSizes.hpp"
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
@ -79,7 +78,49 @@ struct MachineCycle {
|
|||||||
uint8_t *value;
|
uint8_t *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MicroOp {
|
/*!
|
||||||
|
@abstact An abstract base class for emulation of a Z80 processor via the curiously recurring template pattern/f-bounded polymorphism.
|
||||||
|
|
||||||
|
@discussion Subclasses should implement @c perform_machine_cycle in
|
||||||
|
order to provide the bus on which the Z80 operates and @c flush(), which is called upon completion of a continuous run
|
||||||
|
of cycles to allow a subclass to bring any on-demand activities up to date.
|
||||||
|
*/
|
||||||
|
template <class T> class Processor {
|
||||||
|
private:
|
||||||
|
uint8_t a_, i_, r_;
|
||||||
|
RegisterPair bc_, de_, hl_;
|
||||||
|
RegisterPair afDash_, bcDash_, deDash_, hlDash_;
|
||||||
|
RegisterPair ix_, iy_, pc_, sp_;
|
||||||
|
bool iff1_, iff2_;
|
||||||
|
int interrupt_mode_;
|
||||||
|
uint16_t pc_increment_;
|
||||||
|
uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative
|
||||||
|
uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero
|
||||||
|
uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set
|
||||||
|
uint8_t bit53_result_; // the bit 3 and 5 flags are set if the corresponding bits of bit53_result_ are set
|
||||||
|
uint8_t parity_overflow_result_; // the parity/overflow flag is set if the corresponding bit of parity_overflow_result_ is set
|
||||||
|
uint8_t subtract_flag_; // contains a copy of the subtract flag in isolation
|
||||||
|
uint8_t carry_result_; // the carry flag is set if bit 0 of carry_result_ is set
|
||||||
|
uint8_t halt_mask_;
|
||||||
|
|
||||||
|
int number_of_cycles_;
|
||||||
|
|
||||||
|
enum Interrupt: uint8_t {
|
||||||
|
IRQ = 0x01,
|
||||||
|
NMI = 0x02,
|
||||||
|
Reset = 0x04,
|
||||||
|
PowerOn = 0x08
|
||||||
|
};
|
||||||
|
uint8_t request_status_;
|
||||||
|
uint8_t last_request_status_;
|
||||||
|
bool irq_line_;
|
||||||
|
bool bus_request_line_;
|
||||||
|
|
||||||
|
uint8_t operation_;
|
||||||
|
RegisterPair temp16_;
|
||||||
|
uint8_t temp8_;
|
||||||
|
|
||||||
|
struct MicroOp {
|
||||||
enum Type {
|
enum Type {
|
||||||
BusOperation,
|
BusOperation,
|
||||||
DecodeOperation,
|
DecodeOperation,
|
||||||
@ -163,49 +204,9 @@ struct MicroOp {
|
|||||||
void *source;
|
void *source;
|
||||||
void *destination;
|
void *destination;
|
||||||
MachineCycle machine_cycle;
|
MachineCycle machine_cycle;
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@abstact An abstract base class for emulation of a Z80 processor via the curiously recurring template pattern/f-bounded polymorphism.
|
|
||||||
|
|
||||||
@discussion Subclasses should implement @c perform_machine_cycle in
|
|
||||||
order to provide the bus on which the Z80 operates and @c flush(), which is called upon completion of a continuous run
|
|
||||||
of cycles to allow a subclass to bring any on-demand activities up to date.
|
|
||||||
*/
|
|
||||||
template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|
||||||
private:
|
|
||||||
uint8_t a_, i_, r_;
|
|
||||||
RegisterPair bc_, de_, hl_;
|
|
||||||
RegisterPair afDash_, bcDash_, deDash_, hlDash_;
|
|
||||||
RegisterPair ix_, iy_, pc_, sp_;
|
|
||||||
bool iff1_, iff2_;
|
|
||||||
int interrupt_mode_;
|
|
||||||
uint16_t pc_increment_;
|
|
||||||
uint8_t sign_result_; // the sign flag is set if the value in sign_result_ is negative
|
|
||||||
uint8_t zero_result_; // the zero flag is set if the value in zero_result_ is zero
|
|
||||||
uint8_t half_carry_result_; // the half-carry flag is set if bit 4 of half_carry_result_ is set
|
|
||||||
uint8_t bit53_result_; // the bit 3 and 5 flags are set if the corresponding bits of bit53_result_ are set
|
|
||||||
uint8_t parity_overflow_result_; // the parity/overflow flag is set if the corresponding bit of parity_overflow_result_ is set
|
|
||||||
uint8_t subtract_flag_; // contains a copy of the subtract flag in isolation
|
|
||||||
uint8_t carry_result_; // the carry flag is set if bit 0 of carry_result_ is set
|
|
||||||
uint8_t halt_mask_;
|
|
||||||
|
|
||||||
int number_of_cycles_;
|
|
||||||
|
|
||||||
enum Interrupt: uint8_t {
|
|
||||||
IRQ = 0x01,
|
|
||||||
NMI = 0x02,
|
|
||||||
Reset = 0x04,
|
|
||||||
PowerOn = 0x08
|
|
||||||
};
|
};
|
||||||
uint8_t request_status_;
|
const MicroOp *scheduled_program_counter_;
|
||||||
uint8_t last_request_status_;
|
|
||||||
bool irq_line_;
|
|
||||||
bool bus_request_line_;
|
|
||||||
|
|
||||||
uint8_t operation_;
|
|
||||||
RegisterPair temp16_;
|
|
||||||
uint8_t temp8_;
|
|
||||||
|
|
||||||
struct InstructionPage {
|
struct InstructionPage {
|
||||||
std::vector<MicroOp *> instructions;
|
std::vector<MicroOp *> instructions;
|
||||||
@ -665,14 +666,15 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Processor() : MicroOpScheduler(),
|
Processor() :
|
||||||
halt_mask_(0xff),
|
halt_mask_(0xff),
|
||||||
number_of_cycles_(0),
|
number_of_cycles_(0),
|
||||||
request_status_(Interrupt::PowerOn),
|
request_status_(Interrupt::PowerOn),
|
||||||
last_request_status_(Interrupt::PowerOn),
|
last_request_status_(Interrupt::PowerOn),
|
||||||
irq_line_(false),
|
irq_line_(false),
|
||||||
bus_request_line_(false),
|
bus_request_line_(false),
|
||||||
pc_increment_(1) {
|
pc_increment_(1),
|
||||||
|
scheduled_program_counter_(nullptr) {
|
||||||
set_flags(0xff);
|
set_flags(0xff);
|
||||||
|
|
||||||
assemble_base_page(base_page_, hl_, false, cb_page_);
|
assemble_base_page(base_page_, hl_, false, cb_page_);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user