mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +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:
parent
b7ba0d4327
commit
18e8d6ce06
@ -210,9 +210,9 @@
|
||||
4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; };
|
||||
4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; };
|
||||
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; };
|
||||
4B4DEBED2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; };
|
||||
4B4DEBEE2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; };
|
||||
4B4DEBEF2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; };
|
||||
4B4DEC06252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
|
||||
4B4DEC07252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
|
||||
4B4DEC08252BFA56004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEC05252BFA56004583AC /* 65816Base.cpp */; };
|
||||
4B50AF80242817F40099BBD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B50AF7F242817F40099BBD7 /* QuartzCore.framework */; };
|
||||
4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -1346,9 +1350,6 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -2463,6 +2464,24 @@
|
||||
path = 1540;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3337,8 +3356,6 @@
|
||||
4BB73E951B587A5100552FC2 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B4DEBEC2522C03F004583AC /* 65816Base.cpp */,
|
||||
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */,
|
||||
4B51F70820A521D700AFA2C1 /* Activity */,
|
||||
4B8944E2201967B4007DE474 /* Analyser */,
|
||||
4BB73EA01B587A5100552FC2 /* Clock Signal */,
|
||||
@ -3496,11 +3513,10 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */,
|
||||
4BB0240425229C6E009F8D90 /* 6502Esque.hpp */,
|
||||
4BB024092522B7BE009F8D90 /* 6502Selector.hpp */,
|
||||
4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */,
|
||||
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */,
|
||||
4B1414561B58879D00E04248 /* 6502 */,
|
||||
4B4DEC15252BFA9C004583AC /* 6502Esque */,
|
||||
4BF8D4CC251C0C9C00BBE21B /* 65816 */,
|
||||
4BFF1D332233778C00838EA1 /* 68000 */,
|
||||
4B77069E1EC9045B0053B588 /* Z80 */,
|
||||
@ -3921,8 +3937,10 @@
|
||||
4BF8D4D2251C0D9F00BBE21B /* Implementation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BF8D4D3251C0D9F00BBE21B /* 65816Storage.hpp */,
|
||||
4B4DEC05252BFA56004583AC /* 65816Base.cpp */,
|
||||
4BF8D4D4251C11DD00BBE21B /* 65816Storage.cpp */,
|
||||
4B4DEC04252BFA56004583AC /* 65816Implementation.hpp */,
|
||||
4BF8D4D3251C0D9F00BBE21B /* 65816Storage.hpp */,
|
||||
);
|
||||
path = Implementation;
|
||||
sourceTree = "<group>";
|
||||
@ -4503,7 +4521,7 @@
|
||||
4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */,
|
||||
4BC131772346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */,
|
||||
4B055ACF1FAE9B030060FFFF /* SoundGenerator.cpp in Sources */,
|
||||
4B4DEBEF2522C03F004583AC /* 65816Base.cpp in Sources */,
|
||||
4B4DEC08252BFA56004583AC /* 65816Base.cpp in Sources */,
|
||||
4B894519201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
|
||||
4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */,
|
||||
4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */,
|
||||
@ -4786,7 +4804,7 @@
|
||||
4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */,
|
||||
4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */,
|
||||
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
|
||||
4B4DEBED2522C03F004583AC /* 65816Base.cpp in Sources */,
|
||||
4B4DEC06252BFA56004583AC /* 65816Base.cpp in Sources */,
|
||||
4B894524201967B4007DE474 /* Tape.cpp in Sources */,
|
||||
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */,
|
||||
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */,
|
||||
@ -4934,7 +4952,7 @@
|
||||
4B778F4123A5F19A0000D260 /* MemoryPacker.cpp in Sources */,
|
||||
4B778F4423A5F1BE0000D260 /* CommodoreGCR.cpp in Sources */,
|
||||
4B778EF923A5EB740000D260 /* MSA.cpp in Sources */,
|
||||
4B4DEBEE2522C03F004583AC /* 65816Base.cpp in Sources */,
|
||||
4B4DEC07252BFA56004583AC /* 65816Base.cpp in Sources */,
|
||||
4B778F2323A5EDE40000D260 /* Tape.cpp in Sources */,
|
||||
4B778F4F23A5F21C0000D260 /* StaticAnalyser.cpp in Sources */,
|
||||
4B778EEF23A5D6680000D260 /* AsyncTaskQueue.cpp in Sources */,
|
||||
|
@ -13,16 +13,19 @@
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../6502Esque/6502Esque.hpp"
|
||||
#include "../6502Esque/Implementation/LazyFlags.hpp"
|
||||
#include "../RegisterSizes.hpp"
|
||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../6502Esque.hpp"
|
||||
|
||||
namespace CPU {
|
||||
namespace MOS6502 {
|
||||
|
||||
// Adopt a bunch of things from MOS6502Esque.
|
||||
using BusOperation = CPU::MOS6502Esque::BusOperation;
|
||||
using BusHandler = CPU::MOS6502Esque::BusHandler<uint16_t>;
|
||||
using Register = CPU::MOS6502Esque::Register;
|
||||
using Flag = CPU::MOS6502Esque::Flag;
|
||||
|
||||
/*
|
||||
The list of 6502 variants supported by this implementation.
|
||||
@ -40,21 +43,6 @@ enum Personality {
|
||||
#define has_bbrbbsrmbsmb(p) ((p) >= Personality::PRockwell65C02)
|
||||
#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.
|
||||
*/
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef MOS6502AllRAM_cpp
|
||||
#define MOS6502AllRAM_cpp
|
||||
|
||||
#include "../../6502Selector.hpp"
|
||||
#include "../../6502Esque/6502Selector.hpp"
|
||||
#include "../../AllRAMProcessor.hpp"
|
||||
|
||||
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) {
|
||||
static uint8_t throwaway_target;
|
||||
uint8_t throwaway_target;
|
||||
|
||||
// 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
|
||||
@ -42,7 +42,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
|
||||
#define bus_access() \
|
||||
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); \
|
||||
nextBusOperation = BusOperation::None; \
|
||||
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.
|
||||
while(has_stpwai(personality) && wait_is_active_ && number_of_cycles > Cycles(0)) {
|
||||
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_) {
|
||||
wait_is_active_ = false;
|
||||
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 CycleReadVectorHigh: read_mem(pc_.halves.high, nextAddress.full+1); break;
|
||||
case OperationSetIRQFlags:
|
||||
inverse_interrupt_flag_ = 0;
|
||||
if(is_65c02(personality)) decimal_flag_ = false;
|
||||
flags_.inverse_interrupt = 0;
|
||||
if(is_65c02(personality)) flags_.decimal = 0;
|
||||
continue;
|
||||
case OperationSetNMIRSTFlags:
|
||||
if(is_65c02(personality)) decimal_flag_ = false;
|
||||
if(is_65c02(personality)) flags_.decimal = 0;
|
||||
continue;
|
||||
|
||||
case CyclePullPCL: s_++; read_mem(pc_.halves.low, s_ | 0x100); break;
|
||||
case CyclePullPCH: s_++; read_mem(pc_.halves.high, s_ | 0x100); break;
|
||||
case CyclePullA: s_++; read_mem(a_, s_ | 0x100); break;
|
||||
case CyclePullX: s_++; read_mem(x_, s_ | 0x100); break;
|
||||
case CyclePullY: s_++; read_mem(y_, s_ | 0x100); break;
|
||||
case CyclePullOperand: s_++; read_mem(operand_, s_ | 0x100); break;
|
||||
case OperationSetFlagsFromOperand: set_flags(operand_); continue;
|
||||
case OperationSetOperandFromFlagsWithBRKSet: operand_ = get_flags() | Flag::Break; continue;
|
||||
case OperationSetOperandFromFlags: operand_ = get_flags(); continue;
|
||||
case OperationSetFlagsFromA: zero_result_ = negative_result_ = a_; continue;
|
||||
case OperationSetFlagsFromX: zero_result_ = negative_result_ = x_; continue;
|
||||
case OperationSetFlagsFromY: zero_result_ = negative_result_ = y_; continue;
|
||||
case CyclePullPCL: s_++; read_mem(pc_.halves.low, s_ | 0x100); break;
|
||||
case CyclePullPCH: s_++; read_mem(pc_.halves.high, s_ | 0x100); break;
|
||||
case CyclePullA: s_++; read_mem(a_, s_ | 0x100); break;
|
||||
case CyclePullX: s_++; read_mem(x_, s_ | 0x100); break;
|
||||
case CyclePullY: s_++; read_mem(y_, s_ | 0x100); break;
|
||||
case CyclePullOperand: s_++; read_mem(operand_, s_ | 0x100); break;
|
||||
case OperationSetFlagsFromOperand: set_flags(operand_); continue;
|
||||
case OperationSetOperandFromFlagsWithBRKSet: operand_ = flags_.get() | Flag::Break; continue;
|
||||
case OperationSetOperandFromFlags: operand_ = flags_.get(); continue;
|
||||
case OperationSetFlagsFromA: flags_.set_nz(a_); continue;
|
||||
case OperationSetFlagsFromX: flags_.set_nz(x_); continue;
|
||||
case OperationSetFlagsFromY: flags_.set_nz(y_); continue;
|
||||
|
||||
case CycleIncrementPCAndReadStack: pc_.full++; throwaway_read(s_ | 0x100); 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
|
||||
|
||||
case OperationORA: a_ |= operand_; negative_result_ = zero_result_ = a_; continue;
|
||||
case OperationAND: a_ &= operand_; negative_result_ = zero_result_ = a_; continue;
|
||||
case OperationEOR: a_ ^= operand_; negative_result_ = zero_result_ = a_; continue;
|
||||
case OperationORA: a_ |= operand_; flags_.set_nz(a_); continue;
|
||||
case OperationAND: a_ &= operand_; flags_.set_nz(a_); continue;
|
||||
case OperationEOR: a_ ^= operand_; flags_.set_nz(a_); continue;
|
||||
|
||||
// MARK: - Load and Store
|
||||
|
||||
case OperationLDA: a_ = negative_result_ = zero_result_ = operand_; continue;
|
||||
case OperationLDX: x_ = negative_result_ = zero_result_ = operand_; continue;
|
||||
case OperationLDY: y_ = negative_result_ = zero_result_ = operand_; continue;
|
||||
case OperationLAX: a_ = x_ = negative_result_ = zero_result_ = operand_; continue;
|
||||
case OperationCopyOperandToA: a_ = operand_; continue;
|
||||
case OperationLDA: flags_.set_nz(a_ = operand_); continue;
|
||||
case OperationLDX: flags_.set_nz(x_ = operand_); continue;
|
||||
case OperationLDY: flags_.set_nz(y_ = operand_); continue;
|
||||
case OperationLAX: flags_.set_nz(a_ = x_ = operand_); continue;
|
||||
case OperationCopyOperandToA: a_ = operand_; continue;
|
||||
|
||||
case OperationSTA: operand_ = a_; continue;
|
||||
case OperationSTX: operand_ = x_; continue;
|
||||
@ -240,43 +240,43 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
|
||||
case OperationLXA:
|
||||
a_ = x_ = (a_ | 0xee) & operand_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
continue;
|
||||
|
||||
// MARK: - Compare
|
||||
|
||||
case OperationCMP: {
|
||||
const uint16_t temp16 = a_ - operand_;
|
||||
negative_result_ = zero_result_ = uint8_t(temp16);
|
||||
carry_flag_ = ((~temp16) >> 8)&1;
|
||||
flags_.set_nz(uint8_t(temp16));
|
||||
flags_.carry = ((~temp16) >> 8)&1;
|
||||
} continue;
|
||||
case OperationCPX: {
|
||||
const uint16_t temp16 = x_ - operand_;
|
||||
negative_result_ = zero_result_ = uint8_t(temp16);
|
||||
carry_flag_ = ((~temp16) >> 8)&1;
|
||||
flags_.set_nz(uint8_t(temp16));
|
||||
flags_.carry = ((~temp16) >> 8)&1;
|
||||
} continue;
|
||||
case OperationCPY: {
|
||||
const uint16_t temp16 = y_ - operand_;
|
||||
negative_result_ = zero_result_ = uint8_t(temp16);
|
||||
carry_flag_ = ((~temp16) >> 8)&1;
|
||||
flags_.set_nz(uint8_t(temp16));
|
||||
flags_.carry = ((~temp16) >> 8)&1;
|
||||
} continue;
|
||||
|
||||
// MARK: - BIT, TSB, TRB
|
||||
|
||||
case OperationBIT:
|
||||
zero_result_ = operand_ & a_;
|
||||
negative_result_ = operand_;
|
||||
overflow_flag_ = operand_&Flag::Overflow;
|
||||
flags_.zero_result = operand_ & a_;
|
||||
flags_.negative_result = operand_;
|
||||
flags_.overflow = operand_ & Flag::Overflow;
|
||||
continue;
|
||||
case OperationBITNoNV:
|
||||
zero_result_ = operand_ & a_;
|
||||
flags_.zero_result = operand_ & a_;
|
||||
continue;
|
||||
case OperationTRB:
|
||||
zero_result_ = operand_ & a_;
|
||||
flags_.zero_result = operand_ & a_;
|
||||
operand_ &= ~a_;
|
||||
continue;
|
||||
case OperationTSB:
|
||||
zero_result_ = operand_ & a_;
|
||||
flags_.zero_result = operand_ & a_;
|
||||
operand_ |= a_;
|
||||
continue;
|
||||
|
||||
@ -295,8 +295,8 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
operand_++;
|
||||
[[fallthrough]];
|
||||
case OperationSBC:
|
||||
if(decimal_flag_ && has_decimal_mode(personality)) {
|
||||
const uint16_t notCarry = carry_flag_ ^ 0x1;
|
||||
if(flags_.decimal && has_decimal_mode(personality)) {
|
||||
const uint16_t notCarry = flags_.carry ^ 0x1;
|
||||
const uint16_t decimalResult = uint16_t(a_) - uint16_t(operand_) - notCarry;
|
||||
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 += (a_&0xf0) - (operand_&0xf0);
|
||||
|
||||
overflow_flag_ = ( ( (decimalResult^a_)&(~decimalResult^operand_) )&0x80) >> 1;
|
||||
negative_result_ = uint8_t(temp16);
|
||||
zero_result_ = uint8_t(decimalResult);
|
||||
flags_.overflow = ( ( (decimalResult^a_)&(~decimalResult^operand_) )&0x80) >> 1;
|
||||
flags_.negative_result = uint8_t(temp16);
|
||||
flags_.zero_result = uint8_t(decimalResult);
|
||||
|
||||
if(temp16 > 0xff) temp16 -= 0x60;
|
||||
|
||||
carry_flag_ = (temp16 > 0xff) ? 0 : Flag::Carry;
|
||||
flags_.carry = (temp16 > 0xff) ? 0 : Flag::Carry;
|
||||
a_ = uint8_t(temp16);
|
||||
|
||||
if(is_65c02(personality)) {
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
read_mem(operand_, address_.full);
|
||||
break;
|
||||
}
|
||||
@ -326,30 +326,30 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
[[fallthrough]];
|
||||
|
||||
case OperationADC:
|
||||
if(decimal_flag_ && has_decimal_mode(personality)) {
|
||||
const uint16_t decimalResult = uint16_t(a_) + uint16_t(operand_) + uint16_t(carry_flag_);
|
||||
if(flags_.decimal && has_decimal_mode(personality)) {
|
||||
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;
|
||||
uint16_t result = uint16_t(a_ & 0xf0) + uint16_t(operand_ & 0xf0) + uint16_t(low_nibble);
|
||||
negative_result_ = uint8_t(result);
|
||||
overflow_flag_ = (( (result^a_)&(result^operand_) )&0x80) >> 1;
|
||||
flags_.negative_result = uint8_t(result);
|
||||
flags_.overflow = (( (result^a_)&(result^operand_) )&0x80) >> 1;
|
||||
if(result >= 0xa0) result += 0x60;
|
||||
|
||||
carry_flag_ = (result >> 8) ? 1 : 0;
|
||||
flags_.carry = (result >> 8) ? 1 : 0;
|
||||
a_ = uint8_t(result);
|
||||
zero_result_ = uint8_t(decimalResult);
|
||||
flags_.zero_result = uint8_t(decimalResult);
|
||||
|
||||
if(is_65c02(personality)) {
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
read_mem(operand_, address_.full);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
const uint16_t result = uint16_t(a_) + uint16_t(operand_) + uint16_t(carry_flag_);
|
||||
overflow_flag_ = (( (result^a_)&(result^operand_) )&0x80) >> 1;
|
||||
negative_result_ = zero_result_ = a_ = uint8_t(result);
|
||||
carry_flag_ = (result >> 8)&1;
|
||||
const uint16_t result = uint16_t(a_) + uint16_t(operand_) + uint16_t(flags_.carry);
|
||||
flags_.overflow = (( (result^a_)&(result^operand_) )&0x80) >> 1;
|
||||
flags_.set_nz(a_ = uint8_t(result));
|
||||
flags_.carry = (result >> 8)&1;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
case OperationASL:
|
||||
carry_flag_ = operand_ >> 7;
|
||||
flags_.carry = operand_ >> 7;
|
||||
operand_ <<= 1;
|
||||
negative_result_ = zero_result_ = operand_;
|
||||
flags_.set_nz(operand_);
|
||||
continue;
|
||||
|
||||
case OperationASO:
|
||||
carry_flag_ = operand_ >> 7;
|
||||
flags_.carry = operand_ >> 7;
|
||||
operand_ <<= 1;
|
||||
a_ |= operand_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
continue;
|
||||
|
||||
case OperationROL: {
|
||||
const uint8_t temp8 = uint8_t((operand_ << 1) | carry_flag_);
|
||||
carry_flag_ = operand_ >> 7;
|
||||
operand_ = negative_result_ = zero_result_ = temp8;
|
||||
const uint8_t temp8 = uint8_t((operand_ << 1) | flags_.carry);
|
||||
flags_.carry = operand_ >> 7;
|
||||
flags_.set_nz(operand_ = temp8);
|
||||
} continue;
|
||||
|
||||
case OperationRLA: {
|
||||
const uint8_t temp8 = uint8_t((operand_ << 1) | carry_flag_);
|
||||
carry_flag_ = operand_ >> 7;
|
||||
const uint8_t temp8 = uint8_t((operand_ << 1) | flags_.carry);
|
||||
flags_.carry = operand_ >> 7;
|
||||
operand_ = temp8;
|
||||
a_ &= operand_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
} continue;
|
||||
|
||||
case OperationLSR:
|
||||
carry_flag_ = operand_ & 1;
|
||||
flags_.carry = operand_ & 1;
|
||||
operand_ >>= 1;
|
||||
negative_result_ = zero_result_ = operand_;
|
||||
flags_.set_nz(operand_);
|
||||
continue;
|
||||
|
||||
case OperationLSE:
|
||||
carry_flag_ = operand_ & 1;
|
||||
flags_.carry = operand_ & 1;
|
||||
operand_ >>= 1;
|
||||
a_ ^= operand_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
continue;
|
||||
|
||||
case OperationASR:
|
||||
a_ &= operand_;
|
||||
carry_flag_ = a_ & 1;
|
||||
flags_.carry = a_ & 1;
|
||||
a_ >>= 1;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
continue;
|
||||
|
||||
case OperationROR: {
|
||||
const uint8_t temp8 = uint8_t((operand_ >> 1) | (carry_flag_ << 7));
|
||||
carry_flag_ = operand_ & 1;
|
||||
operand_ = negative_result_ = zero_result_ = temp8;
|
||||
const uint8_t temp8 = uint8_t((operand_ >> 1) | (flags_.carry << 7));
|
||||
flags_.carry = operand_ & 1;
|
||||
flags_.set_nz(operand_ = temp8);
|
||||
} continue;
|
||||
|
||||
case OperationRRA: {
|
||||
const uint8_t temp8 = uint8_t((operand_ >> 1) | (carry_flag_ << 7));
|
||||
carry_flag_ = operand_ & 1;
|
||||
const uint8_t temp8 = uint8_t((operand_ >> 1) | (flags_.carry << 7));
|
||||
flags_.carry = operand_ & 1;
|
||||
operand_ = temp8;
|
||||
} continue;
|
||||
|
||||
case OperationDecrementOperand: operand_--; continue;
|
||||
case OperationIncrementOperand: operand_++; continue;
|
||||
|
||||
case OperationCLC: carry_flag_ = 0; continue;
|
||||
case OperationCLI: inverse_interrupt_flag_ = Flag::Interrupt; continue;
|
||||
case OperationCLV: overflow_flag_ = 0; continue;
|
||||
case OperationCLD: decimal_flag_ = 0; continue;
|
||||
case OperationCLC: flags_.carry = 0; continue;
|
||||
case OperationCLI: flags_.inverse_interrupt = Flag::Interrupt; continue;
|
||||
case OperationCLV: flags_.overflow = 0; continue;
|
||||
case OperationCLD: flags_.decimal = 0; continue;
|
||||
|
||||
case OperationSEC: carry_flag_ = Flag::Carry; continue;
|
||||
case OperationSEI: inverse_interrupt_flag_ = 0; continue;
|
||||
case OperationSED: decimal_flag_ = Flag::Decimal; continue;
|
||||
case OperationSEC: flags_.carry = Flag::Carry; continue;
|
||||
case OperationSEI: flags_.inverse_interrupt = 0; continue;
|
||||
case OperationSED: flags_.decimal = Flag::Decimal; continue;
|
||||
|
||||
case OperationINC: operand_++; negative_result_ = zero_result_ = operand_; continue;
|
||||
case OperationDEC: operand_--; negative_result_ = zero_result_ = operand_; continue;
|
||||
case OperationINA: a_++; negative_result_ = zero_result_ = a_; continue;
|
||||
case OperationDEA: a_--; negative_result_ = zero_result_ = a_; continue;
|
||||
case OperationINX: x_++; negative_result_ = zero_result_ = x_; continue;
|
||||
case OperationDEX: x_--; negative_result_ = zero_result_ = x_; continue;
|
||||
case OperationINY: y_++; negative_result_ = zero_result_ = y_; continue;
|
||||
case OperationDEY: y_--; negative_result_ = zero_result_ = y_; continue;
|
||||
case OperationINC: operand_++; flags_.set_nz(operand_); continue;
|
||||
case OperationDEC: operand_--; flags_.set_nz(operand_); continue;
|
||||
case OperationINA: a_++; flags_.set_nz(a_); continue;
|
||||
case OperationDEA: a_--; flags_.set_nz(a_); continue;
|
||||
case OperationINX: x_++; flags_.set_nz(x_); continue;
|
||||
case OperationDEX: x_--; flags_.set_nz(x_); continue;
|
||||
case OperationINY: y_++; flags_.set_nz(y_); continue;
|
||||
case OperationDEY: y_--; flags_.set_nz(y_); continue;
|
||||
|
||||
case OperationANE:
|
||||
a_ = (a_ | 0xee) & operand_ & x_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
continue;
|
||||
|
||||
case OperationANC:
|
||||
a_ &= operand_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
carry_flag_ = a_ >> 7;
|
||||
flags_.set_nz(a_);
|
||||
flags_.carry = a_ >> 7;
|
||||
continue;
|
||||
|
||||
case OperationLAS:
|
||||
a_ = x_ = s_ = s_ & operand_;
|
||||
negative_result_ = zero_result_ = a_;
|
||||
flags_.set_nz(a_);
|
||||
continue;
|
||||
|
||||
// MARK: - Addressing Mode Work
|
||||
@ -548,7 +548,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
throwaway_read(operand_);
|
||||
break;
|
||||
|
||||
case OperationIncrementPC: pc_.full++; continue;
|
||||
case OperationIncrementPC: pc_.full++; continue;
|
||||
case CycleFetchOperandFromAddress: read_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)]; \
|
||||
}
|
||||
|
||||
case OperationBPL: BRA(!(negative_result_&0x80)); continue;
|
||||
case OperationBMI: BRA(negative_result_&0x80); continue;
|
||||
case OperationBVC: BRA(!overflow_flag_); continue;
|
||||
case OperationBVS: BRA(overflow_flag_); continue;
|
||||
case OperationBCC: BRA(!carry_flag_); continue;
|
||||
case OperationBCS: BRA(carry_flag_); continue;
|
||||
case OperationBNE: BRA(zero_result_); continue;
|
||||
case OperationBEQ: BRA(!zero_result_); continue;
|
||||
case OperationBPL: BRA(!(flags_.negative_result&0x80)); continue;
|
||||
case OperationBMI: BRA(flags_.negative_result&0x80); continue;
|
||||
case OperationBVC: BRA(!flags_.overflow); continue;
|
||||
case OperationBVS: BRA(flags_.overflow); continue;
|
||||
case OperationBCC: BRA(!flags_.carry); continue;
|
||||
case OperationBCS: BRA(flags_.carry); continue;
|
||||
case OperationBNE: BRA(flags_.zero_result); continue;
|
||||
case OperationBEQ: BRA(!flags_.zero_result); continue;
|
||||
case OperationBRA: BRA(true); continue;
|
||||
|
||||
#undef BRA
|
||||
@ -610,31 +610,31 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
|
||||
// MARK: - Transfers
|
||||
|
||||
case OperationTXA: zero_result_ = negative_result_ = a_ = x_; continue;
|
||||
case OperationTYA: zero_result_ = negative_result_ = a_ = y_; continue;
|
||||
case OperationTXS: s_ = x_; continue;
|
||||
case OperationTAY: zero_result_ = negative_result_ = y_ = a_; continue;
|
||||
case OperationTAX: zero_result_ = negative_result_ = x_ = a_; continue;
|
||||
case OperationTSX: zero_result_ = negative_result_ = x_ = s_; continue;
|
||||
case OperationTXA: flags_.set_nz(a_ = x_); continue;
|
||||
case OperationTYA: flags_.set_nz(a_ = y_); continue;
|
||||
case OperationTXS: s_ = x_; continue;
|
||||
case OperationTAY: flags_.set_nz(y_ = a_); continue;
|
||||
case OperationTAX: flags_.set_nz(x_ = a_); continue;
|
||||
case OperationTSX: flags_.set_nz(x_ = s_); continue;
|
||||
|
||||
case OperationARR:
|
||||
if(decimal_flag_) {
|
||||
if(flags_.decimal) {
|
||||
a_ &= operand_;
|
||||
uint8_t unshiftedA = a_;
|
||||
a_ = uint8_t((a_ >> 1) | (carry_flag_ << 7));
|
||||
zero_result_ = negative_result_ = a_;
|
||||
overflow_flag_ = (a_^(a_ << 1))&Flag::Overflow;
|
||||
a_ = uint8_t((a_ >> 1) | (flags_.carry << 7));
|
||||
flags_.set_nz(a_);
|
||||
flags_.overflow = (a_^(a_ << 1))&Flag::Overflow;
|
||||
|
||||
if((unshiftedA&0xf) + (unshiftedA&0x1) > 5) a_ = ((a_ + 6)&0xf) | (a_ & 0xf0);
|
||||
|
||||
carry_flag_ = ((unshiftedA&0xf0) + (unshiftedA&0x10) > 0x50) ? 1 : 0;
|
||||
if(carry_flag_) a_ += 0x60;
|
||||
flags_.carry = ((unshiftedA&0xf0) + (unshiftedA&0x10) > 0x50) ? 1 : 0;
|
||||
if(flags_.carry) a_ += 0x60;
|
||||
} else {
|
||||
a_ &= operand_;
|
||||
a_ = uint8_t((a_ >> 1) | (carry_flag_ << 7));
|
||||
negative_result_ = zero_result_ = a_;
|
||||
carry_flag_ = (a_ >> 6)&1;
|
||||
overflow_flag_ = (a_^(a_ << 1))&Flag::Overflow;
|
||||
a_ = uint8_t((a_ >> 1) | (flags_.carry << 7));
|
||||
flags_.set_nz(a_);
|
||||
flags_.carry = (a_ >> 6)&1;
|
||||
flags_.overflow = (a_^(a_ << 1))&Flag::Overflow;
|
||||
}
|
||||
continue;
|
||||
|
||||
@ -642,8 +642,8 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
|
||||
x_ &= a_;
|
||||
uint16_t difference = x_ - operand_;
|
||||
x_ = uint8_t(difference);
|
||||
negative_result_ = zero_result_ = x_;
|
||||
carry_flag_ = ((difference >> 8)&1)^1;
|
||||
flags_.set_nz(x_);
|
||||
flags_.carry = ((difference >> 8)&1)^1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -691,13 +691,13 @@ void ProcessorBase::set_power_on(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) {
|
||||
// a leading edge will set the overflow flag
|
||||
if(active && !set_overflow_line_is_enabled_)
|
||||
overflow_flag_ = Flag::Overflow;
|
||||
flags_.overflow = MOS6502Esque::Flag::Overflow;
|
||||
set_overflow_line_is_enabled_ = active;
|
||||
}
|
||||
|
||||
@ -709,14 +709,9 @@ void ProcessorBase::set_nmi_line(bool active) {
|
||||
}
|
||||
|
||||
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) {
|
||||
carry_flag_ = flags & Flag::Carry;
|
||||
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;
|
||||
flags_.set(flags);
|
||||
}
|
||||
|
@ -76,12 +76,6 @@ using namespace CPU::MOS6502;
|
||||
#define JAM {CycleFetchOperand, OperationScheduleJam}
|
||||
|
||||
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[] = {
|
||||
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetIRQFlags, CycleReadVectorLow, CycleReadVectorHigh),
|
||||
/* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA),
|
||||
|
@ -228,7 +228,7 @@ class ProcessorStorage {
|
||||
*/
|
||||
RegisterPair16 pc_, last_operation_pc_;
|
||||
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.
|
||||
@ -267,7 +267,7 @@ class ProcessorStorage {
|
||||
|
||||
enum InterruptRequestFlags: uint8_t {
|
||||
Reset = 0x80,
|
||||
IRQ = Flag::Interrupt,
|
||||
IRQ = MOS6502Esque::Flag::Interrupt,
|
||||
NMI = 0x20,
|
||||
|
||||
PowerOn = 0x10,
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifndef 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
|
||||
for other processors with a sufficiently-similar bus.
|
||||
@ -35,6 +37,21 @@ enum Register {
|
||||
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
|
||||
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
|
||||
#define _502Selector_h
|
||||
|
||||
#include "6502/6502.hpp"
|
||||
#include "65816/65816.hpp"
|
||||
#include "../6502/6502.hpp"
|
||||
#include "../65816/65816.hpp"
|
||||
|
||||
namespace CPU {
|
||||
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 "../../ClockReceiver/ClockReceiver.hpp"
|
||||
#include "../6502Esque.hpp"
|
||||
#include "../6502Esque/6502Esque.hpp"
|
||||
|
||||
namespace CPU {
|
||||
namespace WDC65816 {
|
||||
|
@ -372,8 +372,10 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
|
||||
}
|
||||
break;
|
||||
|
||||
// default:
|
||||
// assert(false);
|
||||
// TODO: OperationCopyPBRToData, OperationPrepareException
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
number_of_cycles -= bus_handler_.perform_bus_operation(bus_operation, bus_address, bus_value);
|
||||
|
Loading…
Reference in New Issue
Block a user