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:
@@ -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 */,
|
||||||
|
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
@@ -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),
|
||||||
|
@@ -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,
|
||||||
|
@@ -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.
|
@@ -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 {
|
66
Processors/6502Esque/Implementation/LazyFlags.hpp
Normal file
66
Processors/6502Esque/Implementation/LazyFlags.hpp
Normal 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 */
|
3
Processors/6502Esque/README.md
Normal file
3
Processors/6502Esque/README.md
Normal 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.
|
@@ -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 {
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user