1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-09 05:25:01 +00:00

Makes an effort to factor out the 6502's [lazy] flags.

This is preparatory to deciding which instructions, if any, are worth factoring out.
This commit is contained in:
Thomas Harte
2020-10-05 22:23:33 -04:00
parent b7ba0d4327
commit 18e8d6ce06
12 changed files with 262 additions and 179 deletions

View File

@@ -210,9 +210,9 @@
4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; }; 4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; };
4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; }; 4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; };
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; }; 4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; };
4B4DEBED2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; }; 4B4DEC06252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
4B4DEBEE2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; }; 4B4DEC07252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
4B4DEBEF2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; }; 4B4DEC08252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
4B50AF80242817F40099BBD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B50AF7F242817F40099BBD7 /* QuartzCore.framework */; }; 4B50AF80242817F40099BBD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B50AF7F242817F40099BBD7 /* QuartzCore.framework */; };
4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; }; 4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; };
4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* Keyboard.cpp */; }; 4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* Keyboard.cpp */; };
@@ -1122,7 +1122,11 @@
4B4DC8271D2C2470003C5BF8 /* C1540.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = C1540.hpp; sourceTree = "<group>"; }; 4B4DC8271D2C2470003C5BF8 /* C1540.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = C1540.hpp; sourceTree = "<group>"; };
4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialBus.cpp; sourceTree = "<group>"; }; 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialBus.cpp; sourceTree = "<group>"; };
4B4DC82A1D2C27A4003C5BF8 /* SerialBus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialBus.hpp; sourceTree = "<group>"; }; 4B4DC82A1D2C27A4003C5BF8 /* SerialBus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialBus.hpp; sourceTree = "<group>"; };
4B4DEBEC2522C03F004583AC /* 65816Base.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = 65816Base.cpp; path = ../../Processors/65816/Implementation/65816Base.cpp; sourceTree = "<group>"; }; 4B4DEC04252BFA56004583AC /* 65816Implementation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 65816Implementation.hpp; sourceTree = "<group>"; };
4B4DEC05252BFA56004583AC /* 65816Base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 65816Base.cpp; sourceTree = "<group>"; };
4B4DEC16252BFA9C004583AC /* 6502Selector.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502Selector.hpp; sourceTree = "<group>"; };
4B4DEC18252BFA9C004583AC /* 6502Esque.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 6502Esque.hpp; sourceTree = "<group>"; };
4B4DEC19252BFB5A004583AC /* LazyFlags.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LazyFlags.hpp; sourceTree = "<group>"; };
4B4F2B7024DF99D4000DA6B0 /* CSScanTarget+CppScanTarget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CSScanTarget+CppScanTarget.h"; sourceTree = "<group>"; }; 4B4F2B7024DF99D4000DA6B0 /* CSScanTarget+CppScanTarget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CSScanTarget+CppScanTarget.h"; sourceTree = "<group>"; };
4B50AF7F242817F40099BBD7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 4B50AF7F242817F40099BBD7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
4B51F70920A521D700AFA2C1 /* Source.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Source.hpp; sourceTree = "<group>"; }; 4B51F70920A521D700AFA2C1 /* Source.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Source.hpp; sourceTree = "<group>"; };
@@ -1346,9 +1350,6 @@
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; }; 4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; };
4BAF2B4C2004580C00480230 /* DMK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DMK.cpp; sourceTree = "<group>"; }; 4BAF2B4C2004580C00480230 /* DMK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DMK.cpp; sourceTree = "<group>"; };
4BAF2B4D2004580C00480230 /* DMK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DMK.hpp; sourceTree = "<group>"; }; 4BAF2B4D2004580C00480230 /* DMK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DMK.hpp; sourceTree = "<group>"; };
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = 65816Implementation.hpp; path = ../../Processors/65816/Implementation/65816Implementation.hpp; sourceTree = "<group>"; };
4BB0240425229C6E009F8D90 /* 6502Esque.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Esque.hpp; sourceTree = "<group>"; };
4BB024092522B7BE009F8D90 /* 6502Selector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Selector.hpp; sourceTree = "<group>"; };
4BB06B211F316A3F00600C7A /* ForceInline.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ForceInline.hpp; sourceTree = "<group>"; }; 4BB06B211F316A3F00600C7A /* ForceInline.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ForceInline.hpp; sourceTree = "<group>"; };
4BB0A6592044FD3000FB3688 /* SN76489.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SN76489.cpp; sourceTree = "<group>"; }; 4BB0A6592044FD3000FB3688 /* SN76489.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SN76489.cpp; sourceTree = "<group>"; };
4BB0A65A2044FD3000FB3688 /* SN76489.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SN76489.hpp; sourceTree = "<group>"; }; 4BB0A65A2044FD3000FB3688 /* SN76489.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SN76489.hpp; sourceTree = "<group>"; };
@@ -2463,6 +2464,24 @@
path = 1540; path = 1540;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
4B4DEC15252BFA9C004583AC /* 6502Esque */ = {
isa = PBXGroup;
children = (
4B4DEC18252BFA9C004583AC /* 6502Esque.hpp */,
4B4DEC16252BFA9C004583AC /* 6502Selector.hpp */,
4B4DEC17252BFA9C004583AC /* Implementation */,
);
path = 6502Esque;
sourceTree = "<group>";
};
4B4DEC17252BFA9C004583AC /* Implementation */ = {
isa = PBXGroup;
children = (
4B4DEC19252BFB5A004583AC /* LazyFlags.hpp */,
);
path = Implementation;
sourceTree = "<group>";
};
4B51F70820A521D700AFA2C1 /* Activity */ = { 4B51F70820A521D700AFA2C1 /* Activity */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -3337,8 +3356,6 @@
4BB73E951B587A5100552FC2 = { 4BB73E951B587A5100552FC2 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4B4DEBEC2522C03F004583AC /* 65816Base.cpp */,
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */,
4B51F70820A521D700AFA2C1 /* Activity */, 4B51F70820A521D700AFA2C1 /* Activity */,
4B8944E2201967B4007DE474 /* Analyser */, 4B8944E2201967B4007DE474 /* Analyser */,
4BB73EA01B587A5100552FC2 /* Clock Signal */, 4BB73EA01B587A5100552FC2 /* Clock Signal */,
@@ -3496,11 +3513,10 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */, 4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */,
4BB0240425229C6E009F8D90 /* 6502Esque.hpp */,
4BB024092522B7BE009F8D90 /* 6502Selector.hpp */,
4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */, 4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */,
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */, 4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */,
4B1414561B58879D00E04248 /* 6502 */, 4B1414561B58879D00E04248 /* 6502 */,
4B4DEC15252BFA9C004583AC /* 6502Esque */,
4BF8D4CC251C0C9C00BBE21B /* 65816 */, 4BF8D4CC251C0C9C00BBE21B /* 65816 */,
4BFF1D332233778C00838EA1 /* 68000 */, 4BFF1D332233778C00838EA1 /* 68000 */,
4B77069E1EC9045B0053B588 /* Z80 */, 4B77069E1EC9045B0053B588 /* Z80 */,
@@ -3921,8 +3937,10 @@
4BF8D4D2251C0D9F00BBE21B /* Implementation */ = { 4BF8D4D2251C0D9F00BBE21B /* Implementation */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4BF8D4D3251C0D9F00BBE21B /* 65816Storage.hpp */, 4B4DEC05252BFA56004583AC /* 65816Base.cpp */,
4BF8D4D4251C11DD00BBE21B /* 65816Storage.cpp */, 4BF8D4D4251C11DD00BBE21B /* 65816Storage.cpp */,
4B4DEC04252BFA56004583AC /* 65816Implementation.hpp */,
4BF8D4D3251C0D9F00BBE21B /* 65816Storage.hpp */,
); );
path = Implementation; path = Implementation;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -4503,7 +4521,7 @@
4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */, 4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */,
4BC131772346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */, 4BC131772346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */,
4B055ACF1FAE9B030060FFFF /* SoundGenerator.cpp in Sources */, 4B055ACF1FAE9B030060FFFF /* SoundGenerator.cpp in Sources */,
4B4DEBEF2522C03F004583AC /* 65816Base.cpp in Sources */, 4B4DEC08252BFA56004583AC /* 65816Base.cpp in Sources */,
4B894519201967B4007DE474 /* ConfidenceCounter.cpp in Sources */, 4B894519201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */, 4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */,
4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */, 4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */,
@@ -4786,7 +4804,7 @@
4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */, 4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */,
4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */, 4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */,
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */, 4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
4B4DEBED2522C03F004583AC /* 65816Base.cpp in Sources */, 4B4DEC06252BFA56004583AC /* 65816Base.cpp in Sources */,
4B894524201967B4007DE474 /* Tape.cpp in Sources */, 4B894524201967B4007DE474 /* Tape.cpp in Sources */,
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */, 4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */,
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */, 4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */,
@@ -4934,7 +4952,7 @@
4B778F4123A5F19A0000D260 /* MemoryPacker.cpp in Sources */, 4B778F4123A5F19A0000D260 /* MemoryPacker.cpp in Sources */,
4B778F4423A5F1BE0000D260 /* CommodoreGCR.cpp in Sources */, 4B778F4423A5F1BE0000D260 /* CommodoreGCR.cpp in Sources */,
4B778EF923A5EB740000D260 /* MSA.cpp in Sources */, 4B778EF923A5EB740000D260 /* MSA.cpp in Sources */,
4B4DEBEE2522C03F004583AC /* 65816Base.cpp in Sources */, 4B4DEC07252BFA56004583AC /* 65816Base.cpp in Sources */,
4B778F2323A5EDE40000D260 /* Tape.cpp in Sources */, 4B778F2323A5EDE40000D260 /* Tape.cpp in Sources */,
4B778F4F23A5F21C0000D260 /* StaticAnalyser.cpp in Sources */, 4B778F4F23A5F21C0000D260 /* StaticAnalyser.cpp in Sources */,
4B778EEF23A5D6680000D260 /* AsyncTaskQueue.cpp in Sources */, 4B778EEF23A5D6680000D260 /* AsyncTaskQueue.cpp in Sources */,

View File

@@ -13,16 +13,19 @@
#include <cstdio> #include <cstdio>
#include <cstdint> #include <cstdint>
#include "../6502Esque/6502Esque.hpp"
#include "../6502Esque/Implementation/LazyFlags.hpp"
#include "../RegisterSizes.hpp" #include "../RegisterSizes.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp" #include "../../ClockReceiver/ClockReceiver.hpp"
#include "../6502Esque.hpp"
namespace CPU { namespace CPU {
namespace MOS6502 { namespace MOS6502 {
// Adopt a bunch of things from MOS6502Esque.
using BusOperation = CPU::MOS6502Esque::BusOperation; using BusOperation = CPU::MOS6502Esque::BusOperation;
using BusHandler = CPU::MOS6502Esque::BusHandler<uint16_t>; using BusHandler = CPU::MOS6502Esque::BusHandler<uint16_t>;
using Register = CPU::MOS6502Esque::Register; using Register = CPU::MOS6502Esque::Register;
using Flag = CPU::MOS6502Esque::Flag;
/* /*
The list of 6502 variants supported by this implementation. The list of 6502 variants supported by this implementation.
@@ -40,21 +43,6 @@ enum Personality {
#define has_bbrbbsrmbsmb(p) ((p) >= Personality::PRockwell65C02) #define has_bbrbbsrmbsmb(p) ((p) >= Personality::PRockwell65C02)
#define has_stpwai(p) ((p) >= Personality::PWDC65C02) #define has_stpwai(p) ((p) >= Personality::PWDC65C02)
/*
Flags as defined on the 6502; can be used to decode the result of @c get_value_of_register(Flags) or to form a value for
the corresponding set.
*/
enum Flag: uint8_t {
Sign = 0x80,
Overflow = 0x40,
Always = 0x20,
Break = 0x10,
Decimal = 0x08,
Interrupt = 0x04,
Zero = 0x02,
Carry = 0x01
};
/*! /*!
An opcode that is guaranteed to cause the CPU to jam. An opcode that is guaranteed to cause the CPU to jam.
*/ */

View File

@@ -9,7 +9,7 @@
#ifndef MOS6502AllRAM_cpp #ifndef MOS6502AllRAM_cpp
#define MOS6502AllRAM_cpp #define MOS6502AllRAM_cpp
#include "../../6502Selector.hpp" #include "../../6502Esque/6502Selector.hpp"
#include "../../AllRAMProcessor.hpp" #include "../../AllRAMProcessor.hpp"
namespace CPU { namespace CPU {

View File

@@ -13,7 +13,7 @@
*/ */
template <Personality personality, typename T, bool uses_ready_line> void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) { template <Personality personality, typename T, bool uses_ready_line> void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
static uint8_t throwaway_target; uint8_t throwaway_target;
// 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
// without touching the class storage (i.e. it explicitly says they need be completely up // without touching the class storage (i.e. it explicitly says they need be completely up
@@ -42,7 +42,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
#define bus_access() \ #define bus_access() \
interrupt_requests_ = (interrupt_requests_ & ~InterruptRequestFlags::IRQ) | irq_request_history_; \ interrupt_requests_ = (interrupt_requests_ & ~InterruptRequestFlags::IRQ) | irq_request_history_; \
irq_request_history_ = irq_line_ & inverse_interrupt_flag_; \ irq_request_history_ = irq_line_ & flags_.inverse_interrupt; \
number_of_cycles -= bus_handler_.perform_bus_operation(nextBusOperation, busAddress, busValue); \ number_of_cycles -= bus_handler_.perform_bus_operation(nextBusOperation, busAddress, busValue); \
nextBusOperation = BusOperation::None; \ nextBusOperation = BusOperation::None; \
if(number_of_cycles <= Cycles(0)) break; if(number_of_cycles <= Cycles(0)) break;
@@ -70,7 +70,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// Deal with a potential WAI state, if this 6502 implements WAI. // Deal with a potential WAI state, if this 6502 implements WAI.
while(has_stpwai(personality) && wait_is_active_ && number_of_cycles > Cycles(0)) { while(has_stpwai(personality) && wait_is_active_ && number_of_cycles > Cycles(0)) {
number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, busAddress, busValue); number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, busAddress, busValue);
interrupt_requests_ |= (irq_line_ & inverse_interrupt_flag_); interrupt_requests_ |= (irq_line_ & flags_.inverse_interrupt);
if(interrupt_requests_ & InterruptRequestFlags::NMI || irq_line_) { if(interrupt_requests_ & InterruptRequestFlags::NMI || irq_line_) {
wait_is_active_ = false; wait_is_active_ = false;
checkSchedule(); checkSchedule();
@@ -167,25 +167,25 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
case CycleReadVectorLow: read_mem(pc_.halves.low, nextAddress.full); break; case CycleReadVectorLow: read_mem(pc_.halves.low, nextAddress.full); break;
case CycleReadVectorHigh: read_mem(pc_.halves.high, nextAddress.full+1); break; case CycleReadVectorHigh: read_mem(pc_.halves.high, nextAddress.full+1); break;
case OperationSetIRQFlags: case OperationSetIRQFlags:
inverse_interrupt_flag_ = 0; flags_.inverse_interrupt = 0;
if(is_65c02(personality)) decimal_flag_ = false; if(is_65c02(personality)) flags_.decimal = 0;
continue; continue;
case OperationSetNMIRSTFlags: case OperationSetNMIRSTFlags:
if(is_65c02(personality)) decimal_flag_ = false; if(is_65c02(personality)) flags_.decimal = 0;
continue; continue;
case CyclePullPCL: s_++; read_mem(pc_.halves.low, s_ | 0x100); break; case CyclePullPCL: s_++; read_mem(pc_.halves.low, s_ | 0x100); break;
case CyclePullPCH: s_++; read_mem(pc_.halves.high, s_ | 0x100); break; case CyclePullPCH: s_++; read_mem(pc_.halves.high, s_ | 0x100); break;
case CyclePullA: s_++; read_mem(a_, s_ | 0x100); break; case CyclePullA: s_++; read_mem(a_, s_ | 0x100); break;
case CyclePullX: s_++; read_mem(x_, s_ | 0x100); break; case CyclePullX: s_++; read_mem(x_, s_ | 0x100); break;
case CyclePullY: s_++; read_mem(y_, s_ | 0x100); break; case CyclePullY: s_++; read_mem(y_, s_ | 0x100); break;
case CyclePullOperand: s_++; read_mem(operand_, s_ | 0x100); break; case CyclePullOperand: s_++; read_mem(operand_, s_ | 0x100); break;
case OperationSetFlagsFromOperand: set_flags(operand_); continue; case OperationSetFlagsFromOperand: set_flags(operand_); continue;
case OperationSetOperandFromFlagsWithBRKSet: operand_ = get_flags() | Flag::Break; continue; case OperationSetOperandFromFlagsWithBRKSet: operand_ = flags_.get() | Flag::Break; continue;
case OperationSetOperandFromFlags: operand_ = get_flags(); continue; case OperationSetOperandFromFlags: operand_ = flags_.get(); continue;
case OperationSetFlagsFromA: zero_result_ = negative_result_ = a_; continue; case OperationSetFlagsFromA: flags_.set_nz(a_); continue;
case OperationSetFlagsFromX: zero_result_ = negative_result_ = x_; continue; case OperationSetFlagsFromX: flags_.set_nz(x_); continue;
case OperationSetFlagsFromY: zero_result_ = negative_result_ = y_; continue; case OperationSetFlagsFromY: flags_.set_nz(y_); continue;
case CycleIncrementPCAndReadStack: pc_.full++; throwaway_read(s_ | 0x100); break; case CycleIncrementPCAndReadStack: pc_.full++; throwaway_read(s_ | 0x100); break;
case CycleReadPCLFromAddress: read_mem(pc_.halves.low, address_.full); break; case CycleReadPCLFromAddress: read_mem(pc_.halves.low, address_.full); break;
@@ -216,17 +216,17 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// MARK: - Bitwise // MARK: - Bitwise
case OperationORA: a_ |= operand_; negative_result_ = zero_result_ = a_; continue; case OperationORA: a_ |= operand_; flags_.set_nz(a_); continue;
case OperationAND: a_ &= operand_; negative_result_ = zero_result_ = a_; continue; case OperationAND: a_ &= operand_; flags_.set_nz(a_); continue;
case OperationEOR: a_ ^= operand_; negative_result_ = zero_result_ = a_; continue; case OperationEOR: a_ ^= operand_; flags_.set_nz(a_); continue;
// MARK: - Load and Store // MARK: - Load and Store
case OperationLDA: a_ = negative_result_ = zero_result_ = operand_; continue; case OperationLDA: flags_.set_nz(a_ = operand_); continue;
case OperationLDX: x_ = negative_result_ = zero_result_ = operand_; continue; case OperationLDX: flags_.set_nz(x_ = operand_); continue;
case OperationLDY: y_ = negative_result_ = zero_result_ = operand_; continue; case OperationLDY: flags_.set_nz(y_ = operand_); continue;
case OperationLAX: a_ = x_ = negative_result_ = zero_result_ = operand_; continue; case OperationLAX: flags_.set_nz(a_ = x_ = operand_); continue;
case OperationCopyOperandToA: a_ = operand_; continue; case OperationCopyOperandToA: a_ = operand_; continue;
case OperationSTA: operand_ = a_; continue; case OperationSTA: operand_ = a_; continue;
case OperationSTX: operand_ = x_; continue; case OperationSTX: operand_ = x_; continue;
@@ -240,43 +240,43 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
case OperationLXA: case OperationLXA:
a_ = x_ = (a_ | 0xee) & operand_; a_ = x_ = (a_ | 0xee) & operand_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
continue; continue;
// MARK: - Compare // MARK: - Compare
case OperationCMP: { case OperationCMP: {
const uint16_t temp16 = a_ - operand_; const uint16_t temp16 = a_ - operand_;
negative_result_ = zero_result_ = uint8_t(temp16); flags_.set_nz(uint8_t(temp16));
carry_flag_ = ((~temp16) >> 8)&1; flags_.carry = ((~temp16) >> 8)&1;
} continue; } continue;
case OperationCPX: { case OperationCPX: {
const uint16_t temp16 = x_ - operand_; const uint16_t temp16 = x_ - operand_;
negative_result_ = zero_result_ = uint8_t(temp16); flags_.set_nz(uint8_t(temp16));
carry_flag_ = ((~temp16) >> 8)&1; flags_.carry = ((~temp16) >> 8)&1;
} continue; } continue;
case OperationCPY: { case OperationCPY: {
const uint16_t temp16 = y_ - operand_; const uint16_t temp16 = y_ - operand_;
negative_result_ = zero_result_ = uint8_t(temp16); flags_.set_nz(uint8_t(temp16));
carry_flag_ = ((~temp16) >> 8)&1; flags_.carry = ((~temp16) >> 8)&1;
} continue; } continue;
// MARK: - BIT, TSB, TRB // MARK: - BIT, TSB, TRB
case OperationBIT: case OperationBIT:
zero_result_ = operand_ & a_; flags_.zero_result = operand_ & a_;
negative_result_ = operand_; flags_.negative_result = operand_;
overflow_flag_ = operand_&Flag::Overflow; flags_.overflow = operand_ & Flag::Overflow;
continue; continue;
case OperationBITNoNV: case OperationBITNoNV:
zero_result_ = operand_ & a_; flags_.zero_result = operand_ & a_;
continue; continue;
case OperationTRB: case OperationTRB:
zero_result_ = operand_ & a_; flags_.zero_result = operand_ & a_;
operand_ &= ~a_; operand_ &= ~a_;
continue; continue;
case OperationTSB: case OperationTSB:
zero_result_ = operand_ & a_; flags_.zero_result = operand_ & a_;
operand_ |= a_; operand_ |= a_;
continue; continue;
@@ -295,8 +295,8 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
operand_++; operand_++;
[[fallthrough]]; [[fallthrough]];
case OperationSBC: case OperationSBC:
if(decimal_flag_ && has_decimal_mode(personality)) { if(flags_.decimal && has_decimal_mode(personality)) {
const uint16_t notCarry = carry_flag_ ^ 0x1; const uint16_t notCarry = flags_.carry ^ 0x1;
const uint16_t decimalResult = uint16_t(a_) - uint16_t(operand_) - notCarry; const uint16_t decimalResult = uint16_t(a_) - uint16_t(operand_) - notCarry;
uint16_t temp16; uint16_t temp16;
@@ -305,17 +305,17 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
temp16 = (temp16&0x0f) | ((temp16 > 0x0f) ? 0xfff0 : 0x00); temp16 = (temp16&0x0f) | ((temp16 > 0x0f) ? 0xfff0 : 0x00);
temp16 += (a_&0xf0) - (operand_&0xf0); temp16 += (a_&0xf0) - (operand_&0xf0);
overflow_flag_ = ( ( (decimalResult^a_)&(~decimalResult^operand_) )&0x80) >> 1; flags_.overflow = ( ( (decimalResult^a_)&(~decimalResult^operand_) )&0x80) >> 1;
negative_result_ = uint8_t(temp16); flags_.negative_result = uint8_t(temp16);
zero_result_ = uint8_t(decimalResult); flags_.zero_result = uint8_t(decimalResult);
if(temp16 > 0xff) temp16 -= 0x60; if(temp16 > 0xff) temp16 -= 0x60;
carry_flag_ = (temp16 > 0xff) ? 0 : Flag::Carry; flags_.carry = (temp16 > 0xff) ? 0 : Flag::Carry;
a_ = uint8_t(temp16); a_ = uint8_t(temp16);
if(is_65c02(personality)) { if(is_65c02(personality)) {
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
read_mem(operand_, address_.full); read_mem(operand_, address_.full);
break; break;
} }
@@ -326,30 +326,30 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
[[fallthrough]]; [[fallthrough]];
case OperationADC: case OperationADC:
if(decimal_flag_ && has_decimal_mode(personality)) { if(flags_.decimal && has_decimal_mode(personality)) {
const uint16_t decimalResult = uint16_t(a_) + uint16_t(operand_) + uint16_t(carry_flag_); const uint16_t decimalResult = uint16_t(a_) + uint16_t(operand_) + uint16_t(flags_.carry);
uint8_t low_nibble = (a_ & 0xf) + (operand_ & 0xf) + carry_flag_; uint8_t low_nibble = (a_ & 0xf) + (operand_ & 0xf) + flags_.carry;
if(low_nibble >= 0xa) low_nibble = ((low_nibble + 0x6) & 0xf) + 0x10; if(low_nibble >= 0xa) low_nibble = ((low_nibble + 0x6) & 0xf) + 0x10;
uint16_t result = uint16_t(a_ & 0xf0) + uint16_t(operand_ & 0xf0) + uint16_t(low_nibble); uint16_t result = uint16_t(a_ & 0xf0) + uint16_t(operand_ & 0xf0) + uint16_t(low_nibble);
negative_result_ = uint8_t(result); flags_.negative_result = uint8_t(result);
overflow_flag_ = (( (result^a_)&(result^operand_) )&0x80) >> 1; flags_.overflow = (( (result^a_)&(result^operand_) )&0x80) >> 1;
if(result >= 0xa0) result += 0x60; if(result >= 0xa0) result += 0x60;
carry_flag_ = (result >> 8) ? 1 : 0; flags_.carry = (result >> 8) ? 1 : 0;
a_ = uint8_t(result); a_ = uint8_t(result);
zero_result_ = uint8_t(decimalResult); flags_.zero_result = uint8_t(decimalResult);
if(is_65c02(personality)) { if(is_65c02(personality)) {
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
read_mem(operand_, address_.full); read_mem(operand_, address_.full);
break; break;
} }
} else { } else {
const uint16_t result = uint16_t(a_) + uint16_t(operand_) + uint16_t(carry_flag_); const uint16_t result = uint16_t(a_) + uint16_t(operand_) + uint16_t(flags_.carry);
overflow_flag_ = (( (result^a_)&(result^operand_) )&0x80) >> 1; flags_.overflow = (( (result^a_)&(result^operand_) )&0x80) >> 1;
negative_result_ = zero_result_ = a_ = uint8_t(result); flags_.set_nz(a_ = uint8_t(result));
carry_flag_ = (result >> 8)&1; flags_.carry = (result >> 8)&1;
} }
// fix up in case this was INS // fix up in case this was INS
@@ -359,99 +359,99 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// MARK: - Shifts and Rolls // MARK: - Shifts and Rolls
case OperationASL: case OperationASL:
carry_flag_ = operand_ >> 7; flags_.carry = operand_ >> 7;
operand_ <<= 1; operand_ <<= 1;
negative_result_ = zero_result_ = operand_; flags_.set_nz(operand_);
continue; continue;
case OperationASO: case OperationASO:
carry_flag_ = operand_ >> 7; flags_.carry = operand_ >> 7;
operand_ <<= 1; operand_ <<= 1;
a_ |= operand_; a_ |= operand_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
continue; continue;
case OperationROL: { case OperationROL: {
const uint8_t temp8 = uint8_t((operand_ << 1) | carry_flag_); const uint8_t temp8 = uint8_t((operand_ << 1) | flags_.carry);
carry_flag_ = operand_ >> 7; flags_.carry = operand_ >> 7;
operand_ = negative_result_ = zero_result_ = temp8; flags_.set_nz(operand_ = temp8);
} continue; } continue;
case OperationRLA: { case OperationRLA: {
const uint8_t temp8 = uint8_t((operand_ << 1) | carry_flag_); const uint8_t temp8 = uint8_t((operand_ << 1) | flags_.carry);
carry_flag_ = operand_ >> 7; flags_.carry = operand_ >> 7;
operand_ = temp8; operand_ = temp8;
a_ &= operand_; a_ &= operand_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
} continue; } continue;
case OperationLSR: case OperationLSR:
carry_flag_ = operand_ & 1; flags_.carry = operand_ & 1;
operand_ >>= 1; operand_ >>= 1;
negative_result_ = zero_result_ = operand_; flags_.set_nz(operand_);
continue; continue;
case OperationLSE: case OperationLSE:
carry_flag_ = operand_ & 1; flags_.carry = operand_ & 1;
operand_ >>= 1; operand_ >>= 1;
a_ ^= operand_; a_ ^= operand_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
continue; continue;
case OperationASR: case OperationASR:
a_ &= operand_; a_ &= operand_;
carry_flag_ = a_ & 1; flags_.carry = a_ & 1;
a_ >>= 1; a_ >>= 1;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
continue; continue;
case OperationROR: { case OperationROR: {
const uint8_t temp8 = uint8_t((operand_ >> 1) | (carry_flag_ << 7)); const uint8_t temp8 = uint8_t((operand_ >> 1) | (flags_.carry << 7));
carry_flag_ = operand_ & 1; flags_.carry = operand_ & 1;
operand_ = negative_result_ = zero_result_ = temp8; flags_.set_nz(operand_ = temp8);
} continue; } continue;
case OperationRRA: { case OperationRRA: {
const uint8_t temp8 = uint8_t((operand_ >> 1) | (carry_flag_ << 7)); const uint8_t temp8 = uint8_t((operand_ >> 1) | (flags_.carry << 7));
carry_flag_ = operand_ & 1; flags_.carry = operand_ & 1;
operand_ = temp8; operand_ = temp8;
} continue; } continue;
case OperationDecrementOperand: operand_--; continue; case OperationDecrementOperand: operand_--; continue;
case OperationIncrementOperand: operand_++; continue; case OperationIncrementOperand: operand_++; continue;
case OperationCLC: carry_flag_ = 0; continue; case OperationCLC: flags_.carry = 0; continue;
case OperationCLI: inverse_interrupt_flag_ = Flag::Interrupt; continue; case OperationCLI: flags_.inverse_interrupt = Flag::Interrupt; continue;
case OperationCLV: overflow_flag_ = 0; continue; case OperationCLV: flags_.overflow = 0; continue;
case OperationCLD: decimal_flag_ = 0; continue; case OperationCLD: flags_.decimal = 0; continue;
case OperationSEC: carry_flag_ = Flag::Carry; continue; case OperationSEC: flags_.carry = Flag::Carry; continue;
case OperationSEI: inverse_interrupt_flag_ = 0; continue; case OperationSEI: flags_.inverse_interrupt = 0; continue;
case OperationSED: decimal_flag_ = Flag::Decimal; continue; case OperationSED: flags_.decimal = Flag::Decimal; continue;
case OperationINC: operand_++; negative_result_ = zero_result_ = operand_; continue; case OperationINC: operand_++; flags_.set_nz(operand_); continue;
case OperationDEC: operand_--; negative_result_ = zero_result_ = operand_; continue; case OperationDEC: operand_--; flags_.set_nz(operand_); continue;
case OperationINA: a_++; negative_result_ = zero_result_ = a_; continue; case OperationINA: a_++; flags_.set_nz(a_); continue;
case OperationDEA: a_--; negative_result_ = zero_result_ = a_; continue; case OperationDEA: a_--; flags_.set_nz(a_); continue;
case OperationINX: x_++; negative_result_ = zero_result_ = x_; continue; case OperationINX: x_++; flags_.set_nz(x_); continue;
case OperationDEX: x_--; negative_result_ = zero_result_ = x_; continue; case OperationDEX: x_--; flags_.set_nz(x_); continue;
case OperationINY: y_++; negative_result_ = zero_result_ = y_; continue; case OperationINY: y_++; flags_.set_nz(y_); continue;
case OperationDEY: y_--; negative_result_ = zero_result_ = y_; continue; case OperationDEY: y_--; flags_.set_nz(y_); continue;
case OperationANE: case OperationANE:
a_ = (a_ | 0xee) & operand_ & x_; a_ = (a_ | 0xee) & operand_ & x_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
continue; continue;
case OperationANC: case OperationANC:
a_ &= operand_; a_ &= operand_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
carry_flag_ = a_ >> 7; flags_.carry = a_ >> 7;
continue; continue;
case OperationLAS: case OperationLAS:
a_ = x_ = s_ = s_ & operand_; a_ = x_ = s_ = s_ & operand_;
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
continue; continue;
// MARK: - Addressing Mode Work // MARK: - Addressing Mode Work
@@ -548,7 +548,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
throwaway_read(operand_); throwaway_read(operand_);
break; break;
case OperationIncrementPC: pc_.full++; continue; case OperationIncrementPC: pc_.full++; continue;
case CycleFetchOperandFromAddress: read_mem(operand_, address_.full); break; case CycleFetchOperandFromAddress: read_mem(operand_, address_.full); break;
case CycleWriteOperandToAddress: write_mem(operand_, address_.full); break; case CycleWriteOperandToAddress: write_mem(operand_, address_.full); break;
@@ -560,14 +560,14 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
scheduled_program_counter_ = operations_[size_t(OperationsSlot::DoBRA)]; \ scheduled_program_counter_ = operations_[size_t(OperationsSlot::DoBRA)]; \
} }
case OperationBPL: BRA(!(negative_result_&0x80)); continue; case OperationBPL: BRA(!(flags_.negative_result&0x80)); continue;
case OperationBMI: BRA(negative_result_&0x80); continue; case OperationBMI: BRA(flags_.negative_result&0x80); continue;
case OperationBVC: BRA(!overflow_flag_); continue; case OperationBVC: BRA(!flags_.overflow); continue;
case OperationBVS: BRA(overflow_flag_); continue; case OperationBVS: BRA(flags_.overflow); continue;
case OperationBCC: BRA(!carry_flag_); continue; case OperationBCC: BRA(!flags_.carry); continue;
case OperationBCS: BRA(carry_flag_); continue; case OperationBCS: BRA(flags_.carry); continue;
case OperationBNE: BRA(zero_result_); continue; case OperationBNE: BRA(flags_.zero_result); continue;
case OperationBEQ: BRA(!zero_result_); continue; case OperationBEQ: BRA(!flags_.zero_result); continue;
case OperationBRA: BRA(true); continue; case OperationBRA: BRA(true); continue;
#undef BRA #undef BRA
@@ -610,31 +610,31 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// MARK: - Transfers // MARK: - Transfers
case OperationTXA: zero_result_ = negative_result_ = a_ = x_; continue; case OperationTXA: flags_.set_nz(a_ = x_); continue;
case OperationTYA: zero_result_ = negative_result_ = a_ = y_; continue; case OperationTYA: flags_.set_nz(a_ = y_); continue;
case OperationTXS: s_ = x_; continue; case OperationTXS: s_ = x_; continue;
case OperationTAY: zero_result_ = negative_result_ = y_ = a_; continue; case OperationTAY: flags_.set_nz(y_ = a_); continue;
case OperationTAX: zero_result_ = negative_result_ = x_ = a_; continue; case OperationTAX: flags_.set_nz(x_ = a_); continue;
case OperationTSX: zero_result_ = negative_result_ = x_ = s_; continue; case OperationTSX: flags_.set_nz(x_ = s_); continue;
case OperationARR: case OperationARR:
if(decimal_flag_) { if(flags_.decimal) {
a_ &= operand_; a_ &= operand_;
uint8_t unshiftedA = a_; uint8_t unshiftedA = a_;
a_ = uint8_t((a_ >> 1) | (carry_flag_ << 7)); a_ = uint8_t((a_ >> 1) | (flags_.carry << 7));
zero_result_ = negative_result_ = a_; flags_.set_nz(a_);
overflow_flag_ = (a_^(a_ << 1))&Flag::Overflow; flags_.overflow = (a_^(a_ << 1))&Flag::Overflow;
if((unshiftedA&0xf) + (unshiftedA&0x1) > 5) a_ = ((a_ + 6)&0xf) | (a_ & 0xf0); if((unshiftedA&0xf) + (unshiftedA&0x1) > 5) a_ = ((a_ + 6)&0xf) | (a_ & 0xf0);
carry_flag_ = ((unshiftedA&0xf0) + (unshiftedA&0x10) > 0x50) ? 1 : 0; flags_.carry = ((unshiftedA&0xf0) + (unshiftedA&0x10) > 0x50) ? 1 : 0;
if(carry_flag_) a_ += 0x60; if(flags_.carry) a_ += 0x60;
} else { } else {
a_ &= operand_; a_ &= operand_;
a_ = uint8_t((a_ >> 1) | (carry_flag_ << 7)); a_ = uint8_t((a_ >> 1) | (flags_.carry << 7));
negative_result_ = zero_result_ = a_; flags_.set_nz(a_);
carry_flag_ = (a_ >> 6)&1; flags_.carry = (a_ >> 6)&1;
overflow_flag_ = (a_^(a_ << 1))&Flag::Overflow; flags_.overflow = (a_^(a_ << 1))&Flag::Overflow;
} }
continue; continue;
@@ -642,8 +642,8 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
x_ &= a_; x_ &= a_;
uint16_t difference = x_ - operand_; uint16_t difference = x_ - operand_;
x_ = uint8_t(difference); x_ = uint8_t(difference);
negative_result_ = zero_result_ = x_; flags_.set_nz(x_);
carry_flag_ = ((difference >> 8)&1)^1; flags_.carry = ((difference >> 8)&1)^1;
continue; continue;
} }
@@ -691,13 +691,13 @@ void ProcessorBase::set_power_on(bool active) {
} }
void ProcessorBase::set_irq_line(bool active) { void ProcessorBase::set_irq_line(bool active) {
irq_line_ = active ? Flag::Interrupt : 0; irq_line_ = active ? MOS6502Esque::Flag::Interrupt : 0;
} }
void ProcessorBase::set_overflow_line(bool active) { void ProcessorBase::set_overflow_line(bool active) {
// a leading edge will set the overflow flag // a leading edge will set the overflow flag
if(active && !set_overflow_line_is_enabled_) if(active && !set_overflow_line_is_enabled_)
overflow_flag_ = Flag::Overflow; flags_.overflow = MOS6502Esque::Flag::Overflow;
set_overflow_line_is_enabled_ = active; set_overflow_line_is_enabled_ = active;
} }
@@ -709,14 +709,9 @@ void ProcessorBase::set_nmi_line(bool active) {
} }
uint8_t ProcessorStorage::get_flags() const { uint8_t ProcessorStorage::get_flags() const {
return carry_flag_ | overflow_flag_ | (inverse_interrupt_flag_ ^ Flag::Interrupt) | (negative_result_ & 0x80) | (zero_result_ ? 0 : Flag::Zero) | Flag::Always | decimal_flag_; return flags_.get();
} }
void ProcessorStorage::set_flags(uint8_t flags) { void ProcessorStorage::set_flags(uint8_t flags) {
carry_flag_ = flags & Flag::Carry; flags_.set(flags);
negative_result_ = flags & Flag::Sign;
zero_result_ = (~flags) & Flag::Zero;
overflow_flag_ = flags & Flag::Overflow;
inverse_interrupt_flag_ = (~flags) & Flag::Interrupt;
decimal_flag_ = flags & Flag::Decimal;
} }

View File

@@ -76,12 +76,6 @@ using namespace CPU::MOS6502;
#define JAM {CycleFetchOperand, OperationScheduleJam} #define JAM {CycleFetchOperand, OperationScheduleJam}
ProcessorStorage::ProcessorStorage(Personality personality) { ProcessorStorage::ProcessorStorage(Personality personality) {
// 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;
decimal_flag_ &= Flag::Decimal;
overflow_flag_ &= Flag::Overflow;
const InstructionList operations_6502[] = { const InstructionList operations_6502[] = {
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetIRQFlags, CycleReadVectorLow, CycleReadVectorHigh), /* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetIRQFlags, CycleReadVectorLow, CycleReadVectorHigh),
/* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA), /* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA),

View File

@@ -228,7 +228,7 @@ class ProcessorStorage {
*/ */
RegisterPair16 pc_, last_operation_pc_; RegisterPair16 pc_, last_operation_pc_;
uint8_t a_, x_, y_, s_ = 0; uint8_t a_, x_, y_, s_ = 0;
uint8_t carry_flag_, negative_result_, zero_result_, decimal_flag_, overflow_flag_, inverse_interrupt_flag_ = 0; MOS6502Esque::LazyFlags flags_;
/* /*
Temporary state for the micro programs. Temporary state for the micro programs.
@@ -267,7 +267,7 @@ class ProcessorStorage {
enum InterruptRequestFlags: uint8_t { enum InterruptRequestFlags: uint8_t {
Reset = 0x80, Reset = 0x80,
IRQ = Flag::Interrupt, IRQ = MOS6502Esque::Flag::Interrupt,
NMI = 0x20, NMI = 0x20,
PowerOn = 0x10, PowerOn = 0x10,

View File

@@ -9,6 +9,8 @@
#ifndef m6502Esque_h #ifndef m6502Esque_h
#define m6502Esque_h #define m6502Esque_h
#include "../../ClockReceiver/ClockReceiver.hpp"
/* /*
This file defines how the CPU-controlled part of a bus looks for the 6502 and This file defines how the CPU-controlled part of a bus looks for the 6502 and
for other processors with a sufficiently-similar bus. for other processors with a sufficiently-similar bus.
@@ -35,6 +37,21 @@ enum Register {
Y Y
}; };
/*
Flags as defined on the 6502; can be used to decode the result of @c get_value_of_register(Flags) or to form a value for
the corresponding set.
*/
enum Flag: uint8_t {
Sign = 0x80,
Overflow = 0x40,
Always = 0x20,
Break = 0x10,
Decimal = 0x08,
Interrupt = 0x04,
Zero = 0x02,
Carry = 0x01
};
/*! /*!
Bus handlers will be given the task of performing bus operations, allowing them to provide whatever interface they like Bus handlers will be given the task of performing bus operations, allowing them to provide whatever interface they like
between a 6502 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested. between a 6502 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.

View File

@@ -9,8 +9,8 @@
#ifndef _502Selector_h #ifndef _502Selector_h
#define _502Selector_h #define _502Selector_h
#include "6502/6502.hpp" #include "../6502/6502.hpp"
#include "65816/65816.hpp" #include "../65816/65816.hpp"
namespace CPU { namespace CPU {
namespace MOS6502Esque { namespace MOS6502Esque {

View File

@@ -0,0 +1,66 @@
//
// LazyFlags.hpp
// Clock Signal
//
// Created by Thomas Harte on 05/10/2020.
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef LazyFlags_h
#define LazyFlags_h
#include "../6502Esque.hpp"
namespace CPU {
namespace MOS6502Esque {
struct LazyFlags {
/// Bit 7 is set if the negative flag is set; otherwise it is clear.
uint8_t negative_result;
/// Non-zero if the zero flag is clear, zero if it is set.
uint8_t zero_result;
/// Contains Flag::Carry.
uint8_t carry;
/// Contains Flag::Decimal.
uint8_t decimal;
/// Contains Flag::Overflow.
uint8_t overflow;
/// Contains Flag::Interrupt, complemented.
uint8_t inverse_interrupt = 0;
void set_nz(uint8_t value) {
zero_result = negative_result = value;
}
void set(uint8_t flags) {
carry = flags & Flag::Carry;
negative_result = flags & Flag::Sign;
zero_result = (~flags) & Flag::Zero;
overflow = flags & Flag::Overflow;
inverse_interrupt = (~flags) & Flag::Interrupt;
decimal = flags & Flag::Decimal;
}
uint8_t get() const {
return carry | overflow | (inverse_interrupt ^ Flag::Interrupt) | (negative_result & 0x80) | (zero_result ? 0 : Flag::Zero) | Flag::Always | decimal;
}
LazyFlags() {
// 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::Carry;
decimal &= Flag::Decimal;
overflow &= Flag::Overflow;
}
};
}
}
#endif /* LazyFlags_h */

View File

@@ -0,0 +1,3 @@
# 6502Esque
This folder contains common code for CPUs for a 6502-esque bus interface; it also contains a special template, the 6502Selector, which allows a consumer to select between the 6502-esque chips by enum.

View File

@@ -16,7 +16,7 @@
#include "../RegisterSizes.hpp" #include "../RegisterSizes.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp" #include "../../ClockReceiver/ClockReceiver.hpp"
#include "../6502Esque.hpp" #include "../6502Esque/6502Esque.hpp"
namespace CPU { namespace CPU {
namespace WDC65816 { namespace WDC65816 {

View File

@@ -372,8 +372,10 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
} }
break; break;
// default: // TODO: OperationCopyPBRToData, OperationPrepareException
// assert(false);
default:
assert(false);
} }
number_of_cycles -= bus_handler_.perform_bus_operation(bus_operation, bus_address, bus_value); number_of_cycles -= bus_handler_.perform_bus_operation(bus_operation, bus_address, bus_value);