mirror of
https://github.com/TomHarte/CLK.git
synced 2025-03-03 11:31:47 +00:00
Adds basic Z80 state.
This commit is contained in:
parent
e4335577ca
commit
7c9d9ee048
@ -141,6 +141,8 @@
|
||||
4B15A9FD208249BB005E6C8D /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B15A9FA208249BB005E6C8D /* StaticAnalyser.cpp */; };
|
||||
4B17B58B20A8A9D9007CCA8F /* StringSerialiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B17B58920A8A9D9007CCA8F /* StringSerialiser.cpp */; };
|
||||
4B17B58C20A8A9D9007CCA8F /* StringSerialiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B17B58920A8A9D9007CCA8F /* StringSerialiser.cpp */; };
|
||||
4B1B58F6246CC4E8009C171E /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1B58F4246CC4E8009C171E /* State.cpp */; };
|
||||
4B1B58F7246CC4E8009C171E /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1B58F4246CC4E8009C171E /* State.cpp */; };
|
||||
4B1B88BB202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1B88B9202E2EC100B67DFF /* MultiKeyboardMachine.cpp */; };
|
||||
4B1B88BC202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1B88B9202E2EC100B67DFF /* MultiKeyboardMachine.cpp */; };
|
||||
4B1B88BD202E3D3D00B67DFF /* MultiMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FCC3F201EC24200960631 /* MultiMachine.cpp */; };
|
||||
@ -984,6 +986,8 @@
|
||||
4B1667FB1FFF215F00A16032 /* KonamiWithSCC.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = KonamiWithSCC.hpp; path = MSX/Cartridges/KonamiWithSCC.hpp; sourceTree = "<group>"; };
|
||||
4B17B58920A8A9D9007CCA8F /* StringSerialiser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StringSerialiser.cpp; sourceTree = "<group>"; };
|
||||
4B17B58A20A8A9D9007CCA8F /* StringSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StringSerialiser.hpp; sourceTree = "<group>"; };
|
||||
4B1B58F4246CC4E8009C171E /* State.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = State.cpp; sourceTree = "<group>"; };
|
||||
4B1B58F5246CC4E8009C171E /* State.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = State.hpp; sourceTree = "<group>"; };
|
||||
4B1B88B9202E2EC100B67DFF /* MultiKeyboardMachine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiKeyboardMachine.cpp; sourceTree = "<group>"; };
|
||||
4B1B88BA202E2EC100B67DFF /* MultiKeyboardMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MultiKeyboardMachine.hpp; sourceTree = "<group>"; };
|
||||
4B1B88BE202E3DB200B67DFF /* MultiConfigurable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MultiConfigurable.cpp; sourceTree = "<group>"; };
|
||||
@ -2008,6 +2012,16 @@
|
||||
name = Cartridges;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B1B58F3246CC4E8009C171E /* State */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B1B58F4246CC4E8009C171E /* State.cpp */,
|
||||
4B1B58F5246CC4E8009C171E /* State.hpp */,
|
||||
);
|
||||
name = State;
|
||||
path = Z80/State;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4B1E85791D174DEC001EF87D /* 6532 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2630,6 +2644,7 @@
|
||||
4B77069C1EC904570053B588 /* Z80.hpp */,
|
||||
4B322DFC1F5A2981004EB04C /* AllRAM */,
|
||||
4B322DFF1F5A2981004EB04C /* Implementation */,
|
||||
4B1B58F3246CC4E8009C171E /* State */,
|
||||
);
|
||||
name = Z80;
|
||||
sourceTree = "<group>";
|
||||
@ -4441,6 +4456,7 @@
|
||||
4B055ACC1FAE9B030060FFFF /* Electron.cpp in Sources */,
|
||||
4B74CF822312FA9C00500CE8 /* HFV.cpp in Sources */,
|
||||
4B8318B022D3E531006DB630 /* AppleII.cpp in Sources */,
|
||||
4B1B58F7246CC4E8009C171E /* State.cpp in Sources */,
|
||||
4B0ACC03237756F6008902D0 /* Line.cpp in Sources */,
|
||||
4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */,
|
||||
4BC1317B2346DF2B00E4FF3D /* MSA.cpp in Sources */,
|
||||
@ -4555,6 +4571,7 @@
|
||||
4B9BE400203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */,
|
||||
4B894538201967B4007DE474 /* Tape.cpp in Sources */,
|
||||
4B54C0CB1F8D92590050900F /* Keyboard.cpp in Sources */,
|
||||
4B1B58F6246CC4E8009C171E /* State.cpp in Sources */,
|
||||
4BEA525E1DF33323007E74F2 /* Tape.cpp in Sources */,
|
||||
4B2BF19623E10F0100C3AD60 /* CSHighPrecisionTimer.m in Sources */,
|
||||
4B8334951F5E25B60097E338 /* C1540.cpp in Sources */,
|
||||
|
@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Clock Signal.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
@ -285,7 +285,7 @@ class ProcessorStorage {
|
||||
uint8_t irq_line_ = 0, irq_request_history_ = 0;
|
||||
bool nmi_line_is_enabled_ = false, set_overflow_line_is_enabled_ = false;
|
||||
|
||||
// Allow state objects to capture and install state.
|
||||
// Allow state objects to capture and apply state.
|
||||
friend class State;
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
using namespace CPU::MOS6502;
|
||||
|
||||
State::State(const ProcessorBase &src): State() {
|
||||
// Fill in registers.
|
||||
// Registers.
|
||||
registers.program_counter = src.pc_.full;
|
||||
registers.stack_pointer = src.s_;
|
||||
registers.flags = src.get_flags();
|
||||
@ -19,13 +19,13 @@ State::State(const ProcessorBase &src): State() {
|
||||
registers.x = src.x_;
|
||||
registers.y = src.y_;
|
||||
|
||||
// Fill in other inputs.
|
||||
// Inputs.
|
||||
inputs.ready = src.ready_line_is_enabled_;
|
||||
inputs.irq = src.irq_line_;
|
||||
inputs.nmi = src.nmi_line_is_enabled_;
|
||||
inputs.reset = src.interrupt_requests_ & (ProcessorStorage::InterruptRequestFlags::Reset | ProcessorStorage::InterruptRequestFlags::PowerOn);
|
||||
|
||||
// Fill in execution state.
|
||||
// Execution state.
|
||||
execution_state.operation = src.operation_;
|
||||
execution_state.operand = src.operand_;
|
||||
execution_state.address = src.address_.full;
|
||||
@ -51,7 +51,7 @@ State::State(const ProcessorBase &src): State() {
|
||||
}
|
||||
|
||||
void State::apply(ProcessorBase &target) {
|
||||
// Grab registers.
|
||||
// Registers.
|
||||
target.pc_.full = registers.program_counter;
|
||||
target.s_ = registers.stack_pointer;
|
||||
target.set_flags(registers.flags);
|
||||
@ -59,13 +59,13 @@ void State::apply(ProcessorBase &target) {
|
||||
target.x_ = registers.x;
|
||||
target.y_ = registers.y;
|
||||
|
||||
// Grab other inputs.
|
||||
// Inputs.
|
||||
target.ready_line_is_enabled_ = inputs.ready;
|
||||
target.set_irq_line(inputs.irq);
|
||||
target.set_nmi_line(inputs.nmi);
|
||||
target.set_reset_line(inputs.reset);
|
||||
|
||||
// Set execution state.
|
||||
// Execution state.
|
||||
target.ready_is_active_ = target.is_jammed_ = target.wait_is_active_ = target.stop_is_active_ = false;
|
||||
switch(execution_state.phase) {
|
||||
case State::ExecutionState::Phase::Ready: target.ready_is_active_ = true; break;
|
||||
|
@ -1,13 +1,13 @@
|
||||
//
|
||||
// State.h
|
||||
// State.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 02/04/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef State_h
|
||||
#define State_h
|
||||
#ifndef State_hpp
|
||||
#define State_hpp
|
||||
|
||||
#include "../../../Reflection/Enum.hpp"
|
||||
#include "../../../Reflection/Struct.hpp"
|
||||
@ -93,4 +93,4 @@ struct State: public Reflection::StructImpl<State> {
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* State_h */
|
||||
#endif /* State_hpp */
|
||||
|
@ -195,8 +195,8 @@ class ProcessorStorage {
|
||||
|
||||
@returns The current value of the flags register.
|
||||
*/
|
||||
uint8_t get_flags() {
|
||||
uint8_t result =
|
||||
uint8_t get_flags() const {
|
||||
return
|
||||
(sign_result_ & Flag::Sign) |
|
||||
(zero_result_ ? 0 : Flag::Zero) |
|
||||
(bit53_result_ & (Flag::Bit5 | Flag::Bit3)) |
|
||||
@ -204,7 +204,6 @@ class ProcessorStorage {
|
||||
(parity_overflow_result_ & Flag::Parity) |
|
||||
subtract_flag_ |
|
||||
(carry_result_ & Flag::Carry);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -232,4 +231,6 @@ class ProcessorStorage {
|
||||
void assemble_cb_page(InstructionPage &target, RegisterPair16 &index, bool add_offsets);
|
||||
void assemble_base_page(InstructionPage &target, RegisterPair16 &index, bool add_offsets, InstructionPage &cb_page);
|
||||
|
||||
// Allos state objects to capture and apply state.
|
||||
friend class State;
|
||||
};
|
||||
|
110
Processors/Z80/State/State.cpp
Normal file
110
Processors/Z80/State/State.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
//
|
||||
// State.cpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 13/05/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#include "State.hpp"
|
||||
|
||||
using namespace CPU::Z80;
|
||||
|
||||
State::State(const ProcessorBase &src): State() {
|
||||
// Registers.
|
||||
registers.a = src.a_;
|
||||
registers.flags = src.get_flags();
|
||||
registers.bc = src.bc_.full;
|
||||
registers.de = src.de_.full;
|
||||
registers.hl = src.hl_.full;
|
||||
registers.bcDash = src.bcDash_.full;
|
||||
registers.deDash = src.deDash_.full;
|
||||
registers.hlDash = src.hlDash_.full;
|
||||
registers.ix = src.ix_.full;
|
||||
registers.iy = src.iy_.full;
|
||||
registers.ir = src.ir_.full;
|
||||
registers.program_counter = src.pc_.full;
|
||||
registers.stack_pointer = src.sp_.full;
|
||||
registers.memptr = src.memptr_.full;
|
||||
registers.interrupt_mode = src.interrupt_mode_;
|
||||
registers.iff1 = src.iff1_;
|
||||
registers.iff2 = src.iff2_;
|
||||
|
||||
// Inputs.
|
||||
inputs.irq = src.irq_line_;
|
||||
inputs.nmi = src.nmi_line_;
|
||||
inputs.wait = src.wait_line_;
|
||||
inputs.bus_request = src.bus_request_line_;
|
||||
}
|
||||
|
||||
void State::apply(ProcessorBase &target) {
|
||||
// Registers.
|
||||
target.a_ = registers.a;
|
||||
target.set_flags(registers.flags);
|
||||
target.bc_.full = registers.bc;
|
||||
target.de_.full = registers.de;
|
||||
target.hl_.full = registers.hl;
|
||||
target.bcDash_.full = registers.bcDash;
|
||||
target.deDash_.full = registers.deDash;
|
||||
target.hlDash_.full = registers.hlDash;
|
||||
target.ix_.full = registers.ix;
|
||||
target.iy_.full = registers.iy;
|
||||
target.ir_.full = registers.ir;
|
||||
target.pc_.full = registers.program_counter;
|
||||
target.sp_.full = registers.stack_pointer;
|
||||
target.memptr_.full = registers.memptr;
|
||||
target.interrupt_mode_ = registers.interrupt_mode;
|
||||
target.iff1_ = registers.iff1;
|
||||
target.iff2_ = registers.iff2;
|
||||
|
||||
// Inputs.
|
||||
target.irq_line_ = inputs.irq;
|
||||
target.nmi_line_ = inputs.nmi;
|
||||
target.wait_line_ = inputs.wait;
|
||||
target.bus_request_line_ = inputs.bus_request;
|
||||
}
|
||||
|
||||
// Boilerplate follows here, to establish 'reflection'.
|
||||
State::State() {
|
||||
if(needs_declare()) {
|
||||
DeclareField(registers);
|
||||
DeclareField(execution_state);
|
||||
DeclareField(inputs);
|
||||
}
|
||||
}
|
||||
|
||||
State::Registers::Registers() {
|
||||
if(needs_declare()) {
|
||||
DeclareField(a);
|
||||
DeclareField(flags);
|
||||
DeclareField(bc);
|
||||
DeclareField(de);
|
||||
DeclareField(hl);
|
||||
DeclareField(bcDash);
|
||||
DeclareField(deDash);
|
||||
DeclareField(hlDash);
|
||||
DeclareField(ix);
|
||||
DeclareField(iy);
|
||||
DeclareField(ir);
|
||||
DeclareField(program_counter);
|
||||
DeclareField(stack_pointer);
|
||||
DeclareField(interrupt_mode);
|
||||
DeclareField(iff1);
|
||||
DeclareField(iff2);
|
||||
DeclareField(memptr);
|
||||
}
|
||||
}
|
||||
|
||||
State::ExecutionState::ExecutionState() {
|
||||
if(needs_declare()) {
|
||||
}
|
||||
}
|
||||
|
||||
State::Inputs::Inputs() {
|
||||
if(needs_declare()) {
|
||||
DeclareField(irq);
|
||||
DeclareField(nmi);
|
||||
DeclareField(bus_request);
|
||||
DeclareField(wait);
|
||||
}
|
||||
}
|
80
Processors/Z80/State/State.hpp
Normal file
80
Processors/Z80/State/State.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
//
|
||||
// State.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 13/05/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef State_hpp
|
||||
#define State_hpp
|
||||
|
||||
#include "../../../Reflection/Enum.hpp"
|
||||
#include "../../../Reflection/Struct.hpp"
|
||||
#include "../Z80.hpp"
|
||||
|
||||
namespace CPU {
|
||||
namespace Z80 {
|
||||
|
||||
/*!
|
||||
Provides a means for capturing or restoring complete Z80 state.
|
||||
|
||||
This is an optional adjunct to the Z80 class. If you want to take the rest of the Z80
|
||||
implementation but don't want any of the overhead of my sort-of half-reflection as
|
||||
encapsulated in Reflection/[Enum/Struct].hpp just don't use this class.
|
||||
*/
|
||||
struct State: public Reflection::StructImpl<State> {
|
||||
/*!
|
||||
Provides the current state of the well-known, published internal registers.
|
||||
*/
|
||||
struct Registers: public Reflection::StructImpl<Registers> {
|
||||
uint8_t a;
|
||||
uint8_t flags;
|
||||
uint16_t bc, de, hl;
|
||||
uint16_t bcDash, deDash, hlDash;
|
||||
uint16_t ix, iy, ir;
|
||||
uint16_t program_counter, stack_pointer;
|
||||
uint16_t memptr;
|
||||
int interrupt_mode;
|
||||
bool iff1, iff2;
|
||||
|
||||
Registers();
|
||||
} registers;
|
||||
|
||||
/*!
|
||||
Provides the current state of the processor's various input lines that aren't
|
||||
related to an access cycle.
|
||||
*/
|
||||
struct Inputs: public Reflection::StructImpl<Inputs> {
|
||||
bool irq;
|
||||
bool nmi;
|
||||
bool bus_request;
|
||||
bool wait;
|
||||
|
||||
Inputs();
|
||||
} inputs;
|
||||
|
||||
/*!
|
||||
Contains internal state used by this particular implementation of a 6502. Most of it
|
||||
does not necessarily correlate with anything in a real 6502, and some of it very
|
||||
obviously doesn't.
|
||||
*/
|
||||
struct ExecutionState: public Reflection::StructImpl<ExecutionState> {
|
||||
|
||||
ExecutionState();
|
||||
} execution_state;
|
||||
|
||||
/// Default constructor; makes no guarantees as to field values beyond those given above.
|
||||
State();
|
||||
|
||||
/// Instantiates a new State based on the processor @c src.
|
||||
State(const ProcessorBase &src);
|
||||
|
||||
/// Applies this state to @c target.
|
||||
void apply(ProcessorBase &target);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* State_hpp */
|
Loading…
x
Reference in New Issue
Block a user