From 76a73c835cc59cbf23ae1ad1a6974291b5307342 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Aug 2018 20:06:07 -0400 Subject: [PATCH 01/18] =?UTF-8?q?Forces=206502=20consumers=20to=20declare?= =?UTF-8?q?=20which=20model=20=E2=80=94=20the=20original,=2065C02=20or=206?= =?UTF-8?q?5SC02.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All present machines use a regular 6502. --- Machines/AppleII/AppleII.cpp | 2 +- Machines/Atari2600/Cartridges/Cartridge.hpp | 2 +- Machines/Commodore/1540/Implementation/C1540.cpp | 2 +- Machines/Commodore/Vic-20/Vic20.cpp | 2 +- Machines/Electron/Electron.cpp | 2 +- Machines/Oric/Oric.cpp | 2 +- Processors/6502/6502.hpp | 8 +++++++- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Machines/AppleII/AppleII.cpp b/Machines/AppleII/AppleII.cpp index e2c3c26f1..2e876de93 100644 --- a/Machines/AppleII/AppleII.cpp +++ b/Machines/AppleII/AppleII.cpp @@ -298,7 +298,7 @@ template class ConcreteMachine: public: ConcreteMachine(const Analyser::Static::AppleII::Target &target, const ROMMachine::ROMFetcher &rom_fetcher): - m6502_(*this), + m6502_(CPU::MOS6502::Personality::P6502, *this), video_bus_handler_(ram_, aux_ram_), audio_toggle_(audio_queue_), speaker_(audio_toggle_) { diff --git a/Machines/Atari2600/Cartridges/Cartridge.hpp b/Machines/Atari2600/Cartridges/Cartridge.hpp index c52c47d26..f5e7987d9 100644 --- a/Machines/Atari2600/Cartridges/Cartridge.hpp +++ b/Machines/Atari2600/Cartridges/Cartridge.hpp @@ -32,7 +32,7 @@ template class Cartridge: public: Cartridge(const std::vector &rom) : - m6502_(*this), + m6502_(CPU::MOS6502::Personality::P6502, *this), rom_(rom), bus_extender_(rom_.data(), rom.size()) { // The above works because bus_extender_ is declared after rom_ in the instance storage list; diff --git a/Machines/Commodore/1540/Implementation/C1540.cpp b/Machines/Commodore/1540/Implementation/C1540.cpp index be61e8cb8..b6cf3416e 100644 --- a/Machines/Commodore/1540/Implementation/C1540.cpp +++ b/Machines/Commodore/1540/Implementation/C1540.cpp @@ -18,7 +18,7 @@ using namespace Commodore::C1540; MachineBase::MachineBase(Personality personality, const ROMMachine::ROMFetcher &rom_fetcher) : Storage::Disk::Controller(1000000), - m6502_(*this), + m6502_(CPU::MOS6502::Personality::P6502, *this), drive_(new Storage::Disk::Drive(1000000, 300, 2)), serial_port_VIA_port_handler_(new SerialPortVIA(serial_port_VIA_)), serial_port_(new SerialPort), diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index f4eb15ef7..027fec716 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -293,7 +293,7 @@ class ConcreteMachine: public Activity::Source { public: ConcreteMachine(const Analyser::Static::Commodore::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : - m6502_(*this), + m6502_(CPU::MOS6502::Personality::P6502, *this), user_port_via_port_handler_(new UserPortVIA), keyboard_via_port_handler_(new KeyboardVIA), serial_port_(new SerialPort), diff --git a/Machines/Electron/Electron.cpp b/Machines/Electron/Electron.cpp index 584e066ad..4cb17c68e 100644 --- a/Machines/Electron/Electron.cpp +++ b/Machines/Electron/Electron.cpp @@ -50,7 +50,7 @@ class ConcreteMachine: public Activity::Source { public: ConcreteMachine(const Analyser::Static::Acorn::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : - m6502_(*this), + m6502_(CPU::MOS6502::Personality::P6502, *this), sound_generator_(audio_queue_), speaker_(sound_generator_) { memset(key_states_, 0, sizeof(key_states_)); diff --git a/Machines/Oric/Oric.cpp b/Machines/Oric/Oric.cpp index 1dd153f58..62ee0afbe 100644 --- a/Machines/Oric/Oric.cpp +++ b/Machines/Oric/Oric.cpp @@ -207,7 +207,7 @@ template class Co public: ConcreteMachine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) : - m6502_(*this), + m6502_(CPU::MOS6502::Personality::P6502, *this), ay8910_(audio_queue_), speaker_(ay8910_), via_port_handler_(audio_queue_, ay8910_, speaker_, tape_player_, keyboard_), diff --git a/Processors/6502/6502.hpp b/Processors/6502/6502.hpp index ffe19f53b..075f70c2b 100644 --- a/Processors/6502/6502.hpp +++ b/Processors/6502/6502.hpp @@ -180,6 +180,12 @@ class ProcessorBase: public ProcessorStorage { bool is_jammed(); }; +enum Personality { + P6502, // the original 6502, replete with various undocumented instructions + P65C02, // the 65C02; an extended 6502 with a few extra instructions and addressing modes for existing instructions + P65SC02, // like the 65C02, but lacking bit instructions +}; + /*! @abstact Template providing emulation of a 6502 processor. @@ -193,7 +199,7 @@ template class Processor: public ProcessorBas /*! Constructs an instance of the 6502 that will use @c bus_handler for all bus communications. */ - Processor(T &bus_handler) : bus_handler_(bus_handler) {} + Processor(Personality personality, T &bus_handler) : bus_handler_(bus_handler) {} /*! Runs the 6502 for a supplied number of cycles. From 633af4d404a01a563b8d4bec94096a07f7dc955e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Aug 2018 20:47:14 -0400 Subject: [PATCH 02/18] The operations table is now per-instance. --- Processors/6502/6502.hpp | 19 +- .../Implementation/6502Implementation.hpp | 4 +- .../6502/Implementation/6502Storage.cpp | 294 +++++++++--------- .../6502/Implementation/6502Storage.hpp | 4 +- 4 files changed, 165 insertions(+), 156 deletions(-) diff --git a/Processors/6502/6502.hpp b/Processors/6502/6502.hpp index 075f70c2b..37a2e6eca 100644 --- a/Processors/6502/6502.hpp +++ b/Processors/6502/6502.hpp @@ -33,6 +33,15 @@ enum Register { S }; +/* + The list of 6502 variants supported by this implementation. +*/ +enum Personality { + P6502, // the original 6502, replete with various undocumented instructions + P65C02, // the 65C02; an extended 6502 with a few extra instructions and addressing modes for existing instructions + P65SC02, // like the 65C02, but lacking bit instructions +}; + /* 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. @@ -110,6 +119,8 @@ class BusHandler { */ class ProcessorBase: public ProcessorStorage { public: + ProcessorBase(Personality personality) : ProcessorStorage(personality) {} + /*! Gets the value of a register. @@ -180,12 +191,6 @@ class ProcessorBase: public ProcessorStorage { bool is_jammed(); }; -enum Personality { - P6502, // the original 6502, replete with various undocumented instructions - P65C02, // the 65C02; an extended 6502 with a few extra instructions and addressing modes for existing instructions - P65SC02, // like the 65C02, but lacking bit instructions -}; - /*! @abstact Template providing emulation of a 6502 processor. @@ -199,7 +204,7 @@ template class Processor: public ProcessorBas /*! Constructs an instance of the 6502 that will use @c bus_handler for all bus communications. */ - Processor(Personality personality, T &bus_handler) : bus_handler_(bus_handler) {} + Processor(Personality personality, T &bus_handler) : ProcessorBase(personality), bus_handler_(bus_handler) {} /*! Runs the 6502 for a supplied number of cycles. diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index e491e93e7..7f999bde8 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -97,7 +97,7 @@ if(number_of_cycles <= Cycles(0)) break; break; case OperationDecodeOperation: - scheduled_program_counter_ = operations[operation_]; + scheduled_program_counter_ = operations_[operation_]; continue; case OperationMoveToNextProgram: @@ -160,7 +160,7 @@ if(number_of_cycles <= Cycles(0)) break; case CycleScheduleJam: { is_jammed_ = true; - scheduled_program_counter_ = operations[CPU::MOS6502::JamOpcode]; + scheduled_program_counter_ = operations_[CPU::MOS6502::JamOpcode]; } continue; // MARK: - Bitwise diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 5d589af7f..c6a916b22 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -8,6 +8,8 @@ #include "../6502.hpp" +#include + using namespace CPU::MOS6502; #define Program(...) {__VA_ARGS__, OperationMoveToNextProgram} @@ -67,143 +69,153 @@ using namespace CPU::MOS6502; #define JAM {CycleFetchOperand, CycleScheduleJam} -const ProcessorStorage::MicroOp ProcessorStorage::operations[256][10] = { - /* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetI, CycleReadVectorLow, CycleReadVectorHigh), - /* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA), - /* 0x02 JAM */ JAM, /* 0x03 ASO x, ind */ IndexedIndirectReadModifyWrite(OperationASO), - /* 0x04 NOP zpg */ ZeroNop(), /* 0x05 ORA zpg */ ZeroRead(OperationORA), - /* 0x06 ASL zpg */ ZeroReadModifyWrite(OperationASL), /* 0x07 ASO zpg */ ZeroReadModifyWrite(OperationASO), - /* 0x08 PHP */ Program(OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand), - /* 0x09 ORA # */ Immediate(OperationORA), - /* 0x0a ASL A */ Implied(OperationASL), /* 0x0b ANC # */ Immediate(OperationANC), - /* 0x0c NOP abs */ AbsoluteNop(), /* 0x0d ORA abs */ AbsoluteRead(OperationORA), - /* 0x0e ASL abs */ AbsoluteReadModifyWrite(OperationASL), /* 0x0f ASO abs */ AbsoluteReadModifyWrite(OperationASO), - /* 0x10 BPL */ Program(OperationBPL), /* 0x11 ORA ind, y */ IndirectIndexedRead(OperationORA), - /* 0x12 JAM */ JAM, /* 0x13 ASO ind, y */ IndirectIndexedReadModifyWrite(OperationASO), - /* 0x14 NOP zpg, x */ ZeroXNop(), /* 0x15 ORA zpg, x */ ZeroXRead(OperationORA), - /* 0x16 ASL zpg, x */ ZeroXReadModifyWrite(OperationASL), /* 0x17 ASO zpg, x */ ZeroXReadModifyWrite(OperationASO), - /* 0x18 CLC */ Program(OperationCLC), /* 0x19 ORA abs, y */ AbsoluteYRead(OperationORA), - /* 0x1a NOP # */ ImpliedNop(), /* 0x1b ASO abs, y */ AbsoluteYReadModifyWrite(OperationASO), - /* 0x1c NOP abs, x */ AbsoluteXNop(), /* 0x1d ORA abs, x */ AbsoluteXRead(OperationORA), - /* 0x1e ASL abs, x */ AbsoluteXReadModifyWrite(OperationASL), /* 0x1f ASO abs, x */ AbsoluteXReadModifyWrite(OperationASO), - /* 0x20 JSR abs */ Program(CycleIncrementPCAndReadStack, CyclePushPCH, CyclePushPCL, CycleReadPCHLoadPCL), - /* 0x21 AND x, ind */ IndexedIndirectRead(OperationAND), - /* 0x22 JAM */ JAM, /* 0x23 RLA x, ind */ IndexedIndirectReadModifyWrite(OperationRLA), - /* 0x24 BIT zpg */ ZeroRead(OperationBIT), /* 0x25 AND zpg */ ZeroRead(OperationAND), - /* 0x26 ROL zpg */ ZeroReadModifyWrite(OperationROL), /* 0x27 RLA zpg */ ZeroReadModifyWrite(OperationRLA), - /* 0x28 PLP */ Program(CycleReadFromS, CyclePullOperand, OperationSetFlagsFromOperand), - /* 0x29 AND A # */ Immediate(OperationAND), - /* 0x2a ROL A */ Implied(OperationROL), /* 0x2b ANC # */ Immediate(OperationANC), - /* 0x2c BIT abs */ AbsoluteRead(OperationBIT), /* 0x2d AND abs */ AbsoluteRead(OperationAND), - /* 0x2e ROL abs */ AbsoluteReadModifyWrite(OperationROL), /* 0x2f RLA abs */ AbsoluteReadModifyWrite(OperationRLA), - /* 0x30 BMI */ Program(OperationBMI), /* 0x31 AND ind, y */ IndirectIndexedRead(OperationAND), - /* 0x32 JAM */ JAM, /* 0x33 RLA ind, y */ IndirectIndexedReadModifyWrite(OperationRLA), - /* 0x34 NOP zpg, x */ ZeroXNop(), /* 0x35 AND zpg, x */ ZeroXRead(OperationAND), - /* 0x36 ROL zpg, x */ ZeroXReadModifyWrite(OperationROL), /* 0x37 RLA zpg, x */ ZeroXReadModifyWrite(OperationRLA), - /* 0x38 SEC */ Program(OperationSEC), /* 0x39 AND abs, y */ AbsoluteYRead(OperationAND), - /* 0x3a NOP # */ ImpliedNop(), /* 0x3b RLA abs, y */ AbsoluteYReadModifyWrite(OperationRLA), - /* 0x3c NOP abs, x */ AbsoluteXNop(), /* 0x3d AND abs, x */ AbsoluteXRead(OperationAND), - /* 0x3e ROL abs, x */ AbsoluteXReadModifyWrite(OperationROL), /* 0x3f RLA abs, x */ AbsoluteXReadModifyWrite(OperationRLA), - /* 0x40 RTI */ Program(CycleReadFromS, CyclePullOperand, OperationSetFlagsFromOperand, CyclePullPCL, CyclePullPCH), - /* 0x41 EOR x, ind */ IndexedIndirectRead(OperationEOR), - /* 0x42 JAM */ JAM, /* 0x43 LSE x, ind */ IndexedIndirectReadModifyWrite(OperationLSE), - /* 0x44 NOP zpg */ ZeroNop(), /* 0x45 EOR zpg */ ZeroRead(OperationEOR), - /* 0x46 LSR zpg */ ZeroReadModifyWrite(OperationLSR), /* 0x47 LSE zpg */ ZeroReadModifyWrite(OperationLSE), - /* 0x48 PHA */ Program(CyclePushA), /* 0x49 EOR # */ Immediate(OperationEOR), - /* 0x4a LSR A */ Implied(OperationLSR), /* 0x4b ASR A */ Immediate(OperationASR), - /* 0x4c JMP abs */ Program(CycleIncrementPCReadPCHLoadPCL), /* 0x4d EOR abs */ AbsoluteRead(OperationEOR), - /* 0x4e LSR abs */ AbsoluteReadModifyWrite(OperationLSR), /* 0x4f LSE abs */ AbsoluteReadModifyWrite(OperationLSE), - /* 0x50 BVC */ Program(OperationBVC), /* 0x51 EOR ind, y */ IndirectIndexedRead(OperationEOR), - /* 0x52 JAM */ JAM, /* 0x53 LSE ind, y */ IndirectIndexedReadModifyWrite(OperationLSE), - /* 0x54 NOP zpg, x */ ZeroXNop(), /* 0x55 EOR zpg, x */ ZeroXRead(OperationEOR), - /* 0x56 LSR zpg, x */ ZeroXReadModifyWrite(OperationLSR), /* 0x57 LSE zpg, x */ ZeroXReadModifyWrite(OperationLSE), - /* 0x58 CLI */ Program(OperationCLI), /* 0x59 EOR abs, y */ AbsoluteYRead(OperationEOR), - /* 0x5a NOP # */ ImpliedNop(), /* 0x5b LSE abs, y */ AbsoluteYReadModifyWrite(OperationLSE), - /* 0x5c NOP abs, x */ AbsoluteXNop(), /* 0x5d EOR abs, x */ AbsoluteXRead(OperationEOR), - /* 0x5e LSR abs, x */ AbsoluteXReadModifyWrite(OperationLSR), /* 0x5f LSE abs, x */ AbsoluteXReadModifyWrite(OperationLSE), - /* 0x60 RTS */ Program(CycleReadFromS, CyclePullPCL, CyclePullPCH, CycleReadAndIncrementPC), - /* 0x61 ADC x, ind */ IndexedIndirectRead(OperationADC), - /* 0x62 JAM */ JAM, /* 0x63 RRA x, ind */ IndexedIndirectReadModifyWrite(OperationRRA, OperationADC), - /* 0x64 NOP zpg */ ZeroNop(), /* 0x65 ADC zpg */ ZeroRead(OperationADC), - /* 0x66 ROR zpg */ ZeroReadModifyWrite(OperationROR), /* 0x67 RRA zpg */ ZeroReadModifyWrite(OperationRRA, OperationADC), - /* 0x68 PLA */ Program(CycleReadFromS, CyclePullA, OperationSetFlagsFromA), /* 0x69 ADC # */ Immediate(OperationADC), - /* 0x6a ROR A */ Implied(OperationROR), /* 0x6b ARR # */ Immediate(OperationARR), - /* 0x6c JMP (abs) */ Program(CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress), - /* 0x6d ADC abs */ AbsoluteRead(OperationADC), - /* 0x6e ROR abs */ AbsoluteReadModifyWrite(OperationROR), /* 0x6f RRA abs */ AbsoluteReadModifyWrite(OperationRRA, OperationADC), - /* 0x70 BVS */ Program(OperationBVS), /* 0x71 ADC ind, y */ IndirectIndexedRead(OperationADC), - /* 0x72 JAM */ JAM, /* 0x73 RRA ind, y */ IndirectIndexedReadModifyWrite(OperationRRA, OperationADC), - /* 0x74 NOP zpg, x */ ZeroXNop(), /* 0x75 ADC zpg, x */ ZeroXRead(OperationADC), - /* 0x76 ROR zpg, x */ ZeroXReadModifyWrite(OperationROR), /* 0x77 RRA zpg, x */ ZeroXReadModifyWrite(OperationRRA, OperationADC), - /* 0x78 SEI */ Program(OperationSEI), /* 0x79 ADC abs, y */ AbsoluteYRead(OperationADC), - /* 0x7a NOP # */ ImpliedNop(), /* 0x7b RRA abs, y */ AbsoluteYReadModifyWrite(OperationRRA, OperationADC), - /* 0x7c NOP abs, x */ AbsoluteXNop(), /* 0x7d ADC abs, x */ AbsoluteXRead(OperationADC), - /* 0x7e ROR abs, x */ AbsoluteXReadModifyWrite(OperationROR), /* 0x7f RRA abs, x */ AbsoluteXReadModifyWrite(OperationRRA, OperationADC), - /* 0x80 NOP # */ ImmediateNop(), /* 0x81 STA x, ind */ IndexedIndirectWrite(OperationSTA), - /* 0x82 NOP # */ ImmediateNop(), /* 0x83 SAX x, ind */ IndexedIndirectWrite(OperationSAX), - /* 0x84 STY zpg */ ZeroWrite(OperationSTY), /* 0x85 STA zpg */ ZeroWrite(OperationSTA), - /* 0x86 STX zpg */ ZeroWrite(OperationSTX), /* 0x87 SAX zpg */ ZeroWrite(OperationSAX), - /* 0x88 DEY */ Program(OperationDEY), /* 0x89 NOP # */ ImmediateNop(), - /* 0x8a TXA */ Program(OperationTXA), /* 0x8b ANE # */ Immediate(OperationANE), - /* 0x8c STY abs */ AbsoluteWrite(OperationSTY), /* 0x8d STA abs */ AbsoluteWrite(OperationSTA), - /* 0x8e STX abs */ AbsoluteWrite(OperationSTX), /* 0x8f SAX abs */ AbsoluteWrite(OperationSAX), - /* 0x90 BCC */ Program(OperationBCC), /* 0x91 STA ind, y */ IndirectIndexedWrite(OperationSTA), - /* 0x92 JAM */ JAM, /* 0x93 SHA ind, y */ IndirectIndexedWrite(OperationSHA), - /* 0x94 STY zpg, x */ ZeroXWrite(OperationSTY), /* 0x95 STA zpg, x */ ZeroXWrite(OperationSTA), - /* 0x96 STX zpg, y */ ZeroYWrite(OperationSTX), /* 0x97 SAX zpg, y */ ZeroYWrite(OperationSAX), - /* 0x98 TYA */ Program(OperationTYA), /* 0x99 STA abs, y */ AbsoluteYWrite(OperationSTA), - /* 0x9a TXS */ Program(OperationTXS), /* 0x9b SHS abs, y */ AbsoluteYWrite(OperationSHS), - /* 0x9c SHY abs, x */ AbsoluteXWrite(OperationSHY), /* 0x9d STA abs, x */ AbsoluteXWrite(OperationSTA), - /* 0x9e SHX abs, y */ AbsoluteYWrite(OperationSHX), /* 0x9f SHA abs, y */ AbsoluteYWrite(OperationSHA), - /* 0xa0 LDY # */ Immediate(OperationLDY), /* 0xa1 LDA x, ind */ IndexedIndirectRead(OperationLDA), - /* 0xa2 LDX # */ Immediate(OperationLDX), /* 0xa3 LAX x, ind */ IndexedIndirectRead(OperationLAX), - /* 0xa4 LDY zpg */ ZeroRead(OperationLDY), /* 0xa5 LDA zpg */ ZeroRead(OperationLDA), - /* 0xa6 LDX zpg */ ZeroRead(OperationLDX), /* 0xa7 LAX zpg */ ZeroRead(OperationLAX), - /* 0xa8 TAY */ Program(OperationTAY), /* 0xa9 LDA # */ Immediate(OperationLDA), - /* 0xaa TAX */ Program(OperationTAX), /* 0xab LXA # */ Immediate(OperationLXA), - /* 0xac LDY abs */ AbsoluteRead(OperationLDY), /* 0xad LDA abs */ AbsoluteRead(OperationLDA), - /* 0xae LDX abs */ AbsoluteRead(OperationLDX), /* 0xaf LAX abs */ AbsoluteRead(OperationLAX), - /* 0xb0 BCS */ Program(OperationBCS), /* 0xb1 LDA ind, y */ IndirectIndexedRead(OperationLDA), - /* 0xb2 JAM */ JAM, /* 0xb3 LAX ind, y */ IndirectIndexedRead(OperationLAX), - /* 0xb4 LDY zpg, x */ ZeroXRead(OperationLDY), /* 0xb5 LDA zpg, x */ ZeroXRead(OperationLDA), - /* 0xb6 LDX zpg, y */ ZeroYRead(OperationLDX), /* 0xb7 LAX zpg, x */ ZeroYRead(OperationLAX), - /* 0xb8 CLV */ Program(OperationCLV), /* 0xb9 LDA abs, y */ AbsoluteYRead(OperationLDA), - /* 0xba TSX */ Program(OperationTSX), /* 0xbb LAS abs, y */ AbsoluteYRead(OperationLAS), - /* 0xbc LDY abs, x */ AbsoluteXRead(OperationLDY), /* 0xbd LDA abs, x */ AbsoluteXRead(OperationLDA), - /* 0xbe LDX abs, y */ AbsoluteYRead(OperationLDX), /* 0xbf LAX abs, y */ AbsoluteYRead(OperationLAX), - /* 0xc0 CPY # */ Immediate(OperationCPY), /* 0xc1 CMP x, ind */ IndexedIndirectRead(OperationCMP), - /* 0xc2 NOP # */ ImmediateNop(), /* 0xc3 DCP x, ind */ IndexedIndirectReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xc4 CPY zpg */ ZeroRead(OperationCPY), /* 0xc5 CMP zpg */ ZeroRead(OperationCMP), - /* 0xc6 DEC zpg */ ZeroReadModifyWrite(OperationDEC), /* 0xc7 DCP zpg */ ZeroReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xc8 INY */ Program(OperationINY), /* 0xc9 CMP # */ Immediate(OperationCMP), - /* 0xca DEX */ Program(OperationDEX), /* 0xcb ARR # */ Immediate(OperationSBX), - /* 0xcc CPY abs */ AbsoluteRead(OperationCPY), /* 0xcd CMP abs */ AbsoluteRead(OperationCMP), - /* 0xce DEC abs */ AbsoluteReadModifyWrite(OperationDEC), /* 0xcf DCP abs */ AbsoluteReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xd0 BNE */ Program(OperationBNE), /* 0xd1 CMP ind, y */ IndirectIndexedRead(OperationCMP), - /* 0xd2 JAM */ JAM, /* 0xd3 DCP ind, y */ IndirectIndexedReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xd4 NOP zpg, x */ ZeroXNop(), /* 0xd5 CMP zpg, x */ ZeroXRead(OperationCMP), - /* 0xd6 DEC zpg, x */ ZeroXReadModifyWrite(OperationDEC), /* 0xd7 DCP zpg, x */ ZeroXReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xd8 CLD */ Program(OperationCLD), /* 0xd9 CMP abs, y */ AbsoluteYRead(OperationCMP), - /* 0xda NOP # */ ImpliedNop(), /* 0xdb DCP abs, y */ AbsoluteYReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xdc NOP abs, x */ AbsoluteXNop(), /* 0xdd CMP abs, x */ AbsoluteXRead(OperationCMP), - /* 0xde DEC abs, x */ AbsoluteXReadModifyWrite(OperationDEC), /* 0xdf DCP abs, x */ AbsoluteXReadModifyWrite(OperationDecrementOperand, OperationCMP), - /* 0xe0 CPX # */ Immediate(OperationCPX), /* 0xe1 SBC x, ind */ IndexedIndirectRead(OperationSBC), - /* 0xe2 NOP # */ ImmediateNop(), /* 0xe3 INS x, ind */ IndexedIndirectReadModifyWrite(OperationINS), - /* 0xe4 CPX zpg */ ZeroRead(OperationCPX), /* 0xe5 SBC zpg */ ZeroRead(OperationSBC), - /* 0xe6 INC zpg */ ZeroReadModifyWrite(OperationINC), /* 0xe7 INS zpg */ ZeroReadModifyWrite(OperationINS), - /* 0xe8 INX */ Program(OperationINX), /* 0xe9 SBC # */ Immediate(OperationSBC), - /* 0xea NOP # */ ImpliedNop(), /* 0xeb SBC # */ Immediate(OperationSBC), - /* 0xec CPX abs */ AbsoluteRead(OperationCPX), /* 0xed SBC abs */ AbsoluteRead(OperationSBC), - /* 0xee INC abs */ AbsoluteReadModifyWrite(OperationINC), /* 0xef INS abs */ AbsoluteReadModifyWrite(OperationINS), - /* 0xf0 BEQ */ Program(OperationBEQ), /* 0xf1 SBC ind, y */ IndirectIndexedRead(OperationSBC), - /* 0xf2 JAM */ JAM, /* 0xf3 INS ind, y */ IndirectIndexedReadModifyWrite(OperationINS), - /* 0xf4 NOP zpg, x */ ZeroXNop(), /* 0xf5 SBC zpg, x */ ZeroXRead(OperationSBC), - /* 0xf6 INC zpg, x */ ZeroXReadModifyWrite(OperationINC), /* 0xf7 INS zpg, x */ ZeroXReadModifyWrite(OperationINS), - /* 0xf8 SED */ Program(OperationSED), /* 0xf9 SBC abs, y */ AbsoluteYRead(OperationSBC), - /* 0xfa NOP # */ ImpliedNop(), /* 0xfb INS abs, y */ AbsoluteYReadModifyWrite(OperationINS), - /* 0xfc NOP abs, x */ AbsoluteXNop(), /* 0xfd SBC abs, x */ AbsoluteXRead(OperationSBC), - /* 0xfe INC abs, x */ AbsoluteXReadModifyWrite(OperationINC), /* 0xff INS abs, x */ AbsoluteXReadModifyWrite(OperationINS), -}; +ProcessorStorage::ProcessorStorage(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 ProcessorStorage::MicroOp operations_6502[256][10] = { + /* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetI, CycleReadVectorLow, CycleReadVectorHigh), + /* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA), + /* 0x02 JAM */ JAM, /* 0x03 ASO x, ind */ IndexedIndirectReadModifyWrite(OperationASO), + /* 0x04 NOP zpg */ ZeroNop(), /* 0x05 ORA zpg */ ZeroRead(OperationORA), + /* 0x06 ASL zpg */ ZeroReadModifyWrite(OperationASL), /* 0x07 ASO zpg */ ZeroReadModifyWrite(OperationASO), + /* 0x08 PHP */ Program(OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand), + /* 0x09 ORA # */ Immediate(OperationORA), + /* 0x0a ASL A */ Implied(OperationASL), /* 0x0b ANC # */ Immediate(OperationANC), + /* 0x0c NOP abs */ AbsoluteNop(), /* 0x0d ORA abs */ AbsoluteRead(OperationORA), + /* 0x0e ASL abs */ AbsoluteReadModifyWrite(OperationASL), /* 0x0f ASO abs */ AbsoluteReadModifyWrite(OperationASO), + /* 0x10 BPL */ Program(OperationBPL), /* 0x11 ORA ind, y */ IndirectIndexedRead(OperationORA), + /* 0x12 JAM */ JAM, /* 0x13 ASO ind, y */ IndirectIndexedReadModifyWrite(OperationASO), + /* 0x14 NOP zpg, x */ ZeroXNop(), /* 0x15 ORA zpg, x */ ZeroXRead(OperationORA), + /* 0x16 ASL zpg, x */ ZeroXReadModifyWrite(OperationASL), /* 0x17 ASO zpg, x */ ZeroXReadModifyWrite(OperationASO), + /* 0x18 CLC */ Program(OperationCLC), /* 0x19 ORA abs, y */ AbsoluteYRead(OperationORA), + /* 0x1a NOP # */ ImpliedNop(), /* 0x1b ASO abs, y */ AbsoluteYReadModifyWrite(OperationASO), + /* 0x1c NOP abs, x */ AbsoluteXNop(), /* 0x1d ORA abs, x */ AbsoluteXRead(OperationORA), + /* 0x1e ASL abs, x */ AbsoluteXReadModifyWrite(OperationASL), /* 0x1f ASO abs, x */ AbsoluteXReadModifyWrite(OperationASO), + /* 0x20 JSR abs */ Program(CycleIncrementPCAndReadStack, CyclePushPCH, CyclePushPCL, CycleReadPCHLoadPCL), + /* 0x21 AND x, ind */ IndexedIndirectRead(OperationAND), + /* 0x22 JAM */ JAM, /* 0x23 RLA x, ind */ IndexedIndirectReadModifyWrite(OperationRLA), + /* 0x24 BIT zpg */ ZeroRead(OperationBIT), /* 0x25 AND zpg */ ZeroRead(OperationAND), + /* 0x26 ROL zpg */ ZeroReadModifyWrite(OperationROL), /* 0x27 RLA zpg */ ZeroReadModifyWrite(OperationRLA), + /* 0x28 PLP */ Program(CycleReadFromS, CyclePullOperand, OperationSetFlagsFromOperand), + /* 0x29 AND A # */ Immediate(OperationAND), + /* 0x2a ROL A */ Implied(OperationROL), /* 0x2b ANC # */ Immediate(OperationANC), + /* 0x2c BIT abs */ AbsoluteRead(OperationBIT), /* 0x2d AND abs */ AbsoluteRead(OperationAND), + /* 0x2e ROL abs */ AbsoluteReadModifyWrite(OperationROL), /* 0x2f RLA abs */ AbsoluteReadModifyWrite(OperationRLA), + /* 0x30 BMI */ Program(OperationBMI), /* 0x31 AND ind, y */ IndirectIndexedRead(OperationAND), + /* 0x32 JAM */ JAM, /* 0x33 RLA ind, y */ IndirectIndexedReadModifyWrite(OperationRLA), + /* 0x34 NOP zpg, x */ ZeroXNop(), /* 0x35 AND zpg, x */ ZeroXRead(OperationAND), + /* 0x36 ROL zpg, x */ ZeroXReadModifyWrite(OperationROL), /* 0x37 RLA zpg, x */ ZeroXReadModifyWrite(OperationRLA), + /* 0x38 SEC */ Program(OperationSEC), /* 0x39 AND abs, y */ AbsoluteYRead(OperationAND), + /* 0x3a NOP # */ ImpliedNop(), /* 0x3b RLA abs, y */ AbsoluteYReadModifyWrite(OperationRLA), + /* 0x3c NOP abs, x */ AbsoluteXNop(), /* 0x3d AND abs, x */ AbsoluteXRead(OperationAND), + /* 0x3e ROL abs, x */ AbsoluteXReadModifyWrite(OperationROL), /* 0x3f RLA abs, x */ AbsoluteXReadModifyWrite(OperationRLA), + /* 0x40 RTI */ Program(CycleReadFromS, CyclePullOperand, OperationSetFlagsFromOperand, CyclePullPCL, CyclePullPCH), + /* 0x41 EOR x, ind */ IndexedIndirectRead(OperationEOR), + /* 0x42 JAM */ JAM, /* 0x43 LSE x, ind */ IndexedIndirectReadModifyWrite(OperationLSE), + /* 0x44 NOP zpg */ ZeroNop(), /* 0x45 EOR zpg */ ZeroRead(OperationEOR), + /* 0x46 LSR zpg */ ZeroReadModifyWrite(OperationLSR), /* 0x47 LSE zpg */ ZeroReadModifyWrite(OperationLSE), + /* 0x48 PHA */ Program(CyclePushA), /* 0x49 EOR # */ Immediate(OperationEOR), + /* 0x4a LSR A */ Implied(OperationLSR), /* 0x4b ASR A */ Immediate(OperationASR), + /* 0x4c JMP abs */ Program(CycleIncrementPCReadPCHLoadPCL), /* 0x4d EOR abs */ AbsoluteRead(OperationEOR), + /* 0x4e LSR abs */ AbsoluteReadModifyWrite(OperationLSR), /* 0x4f LSE abs */ AbsoluteReadModifyWrite(OperationLSE), + /* 0x50 BVC */ Program(OperationBVC), /* 0x51 EOR ind, y */ IndirectIndexedRead(OperationEOR), + /* 0x52 JAM */ JAM, /* 0x53 LSE ind, y */ IndirectIndexedReadModifyWrite(OperationLSE), + /* 0x54 NOP zpg, x */ ZeroXNop(), /* 0x55 EOR zpg, x */ ZeroXRead(OperationEOR), + /* 0x56 LSR zpg, x */ ZeroXReadModifyWrite(OperationLSR), /* 0x57 LSE zpg, x */ ZeroXReadModifyWrite(OperationLSE), + /* 0x58 CLI */ Program(OperationCLI), /* 0x59 EOR abs, y */ AbsoluteYRead(OperationEOR), + /* 0x5a NOP # */ ImpliedNop(), /* 0x5b LSE abs, y */ AbsoluteYReadModifyWrite(OperationLSE), + /* 0x5c NOP abs, x */ AbsoluteXNop(), /* 0x5d EOR abs, x */ AbsoluteXRead(OperationEOR), + /* 0x5e LSR abs, x */ AbsoluteXReadModifyWrite(OperationLSR), /* 0x5f LSE abs, x */ AbsoluteXReadModifyWrite(OperationLSE), + /* 0x60 RTS */ Program(CycleReadFromS, CyclePullPCL, CyclePullPCH, CycleReadAndIncrementPC), + /* 0x61 ADC x, ind */ IndexedIndirectRead(OperationADC), + /* 0x62 JAM */ JAM, /* 0x63 RRA x, ind */ IndexedIndirectReadModifyWrite(OperationRRA, OperationADC), + /* 0x64 NOP zpg */ ZeroNop(), /* 0x65 ADC zpg */ ZeroRead(OperationADC), + /* 0x66 ROR zpg */ ZeroReadModifyWrite(OperationROR), /* 0x67 RRA zpg */ ZeroReadModifyWrite(OperationRRA, OperationADC), + /* 0x68 PLA */ Program(CycleReadFromS, CyclePullA, OperationSetFlagsFromA), /* 0x69 ADC # */ Immediate(OperationADC), + /* 0x6a ROR A */ Implied(OperationROR), /* 0x6b ARR # */ Immediate(OperationARR), + /* 0x6c JMP (abs) */ Program(CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress), + /* 0x6d ADC abs */ AbsoluteRead(OperationADC), + /* 0x6e ROR abs */ AbsoluteReadModifyWrite(OperationROR), /* 0x6f RRA abs */ AbsoluteReadModifyWrite(OperationRRA, OperationADC), + /* 0x70 BVS */ Program(OperationBVS), /* 0x71 ADC ind, y */ IndirectIndexedRead(OperationADC), + /* 0x72 JAM */ JAM, /* 0x73 RRA ind, y */ IndirectIndexedReadModifyWrite(OperationRRA, OperationADC), + /* 0x74 NOP zpg, x */ ZeroXNop(), /* 0x75 ADC zpg, x */ ZeroXRead(OperationADC), + /* 0x76 ROR zpg, x */ ZeroXReadModifyWrite(OperationROR), /* 0x77 RRA zpg, x */ ZeroXReadModifyWrite(OperationRRA, OperationADC), + /* 0x78 SEI */ Program(OperationSEI), /* 0x79 ADC abs, y */ AbsoluteYRead(OperationADC), + /* 0x7a NOP # */ ImpliedNop(), /* 0x7b RRA abs, y */ AbsoluteYReadModifyWrite(OperationRRA, OperationADC), + /* 0x7c NOP abs, x */ AbsoluteXNop(), /* 0x7d ADC abs, x */ AbsoluteXRead(OperationADC), + /* 0x7e ROR abs, x */ AbsoluteXReadModifyWrite(OperationROR), /* 0x7f RRA abs, x */ AbsoluteXReadModifyWrite(OperationRRA, OperationADC), + /* 0x80 NOP # */ ImmediateNop(), /* 0x81 STA x, ind */ IndexedIndirectWrite(OperationSTA), + /* 0x82 NOP # */ ImmediateNop(), /* 0x83 SAX x, ind */ IndexedIndirectWrite(OperationSAX), + /* 0x84 STY zpg */ ZeroWrite(OperationSTY), /* 0x85 STA zpg */ ZeroWrite(OperationSTA), + /* 0x86 STX zpg */ ZeroWrite(OperationSTX), /* 0x87 SAX zpg */ ZeroWrite(OperationSAX), + /* 0x88 DEY */ Program(OperationDEY), /* 0x89 NOP # */ ImmediateNop(), + /* 0x8a TXA */ Program(OperationTXA), /* 0x8b ANE # */ Immediate(OperationANE), + /* 0x8c STY abs */ AbsoluteWrite(OperationSTY), /* 0x8d STA abs */ AbsoluteWrite(OperationSTA), + /* 0x8e STX abs */ AbsoluteWrite(OperationSTX), /* 0x8f SAX abs */ AbsoluteWrite(OperationSAX), + /* 0x90 BCC */ Program(OperationBCC), /* 0x91 STA ind, y */ IndirectIndexedWrite(OperationSTA), + /* 0x92 JAM */ JAM, /* 0x93 SHA ind, y */ IndirectIndexedWrite(OperationSHA), + /* 0x94 STY zpg, x */ ZeroXWrite(OperationSTY), /* 0x95 STA zpg, x */ ZeroXWrite(OperationSTA), + /* 0x96 STX zpg, y */ ZeroYWrite(OperationSTX), /* 0x97 SAX zpg, y */ ZeroYWrite(OperationSAX), + /* 0x98 TYA */ Program(OperationTYA), /* 0x99 STA abs, y */ AbsoluteYWrite(OperationSTA), + /* 0x9a TXS */ Program(OperationTXS), /* 0x9b SHS abs, y */ AbsoluteYWrite(OperationSHS), + /* 0x9c SHY abs, x */ AbsoluteXWrite(OperationSHY), /* 0x9d STA abs, x */ AbsoluteXWrite(OperationSTA), + /* 0x9e SHX abs, y */ AbsoluteYWrite(OperationSHX), /* 0x9f SHA abs, y */ AbsoluteYWrite(OperationSHA), + /* 0xa0 LDY # */ Immediate(OperationLDY), /* 0xa1 LDA x, ind */ IndexedIndirectRead(OperationLDA), + /* 0xa2 LDX # */ Immediate(OperationLDX), /* 0xa3 LAX x, ind */ IndexedIndirectRead(OperationLAX), + /* 0xa4 LDY zpg */ ZeroRead(OperationLDY), /* 0xa5 LDA zpg */ ZeroRead(OperationLDA), + /* 0xa6 LDX zpg */ ZeroRead(OperationLDX), /* 0xa7 LAX zpg */ ZeroRead(OperationLAX), + /* 0xa8 TAY */ Program(OperationTAY), /* 0xa9 LDA # */ Immediate(OperationLDA), + /* 0xaa TAX */ Program(OperationTAX), /* 0xab LXA # */ Immediate(OperationLXA), + /* 0xac LDY abs */ AbsoluteRead(OperationLDY), /* 0xad LDA abs */ AbsoluteRead(OperationLDA), + /* 0xae LDX abs */ AbsoluteRead(OperationLDX), /* 0xaf LAX abs */ AbsoluteRead(OperationLAX), + /* 0xb0 BCS */ Program(OperationBCS), /* 0xb1 LDA ind, y */ IndirectIndexedRead(OperationLDA), + /* 0xb2 JAM */ JAM, /* 0xb3 LAX ind, y */ IndirectIndexedRead(OperationLAX), + /* 0xb4 LDY zpg, x */ ZeroXRead(OperationLDY), /* 0xb5 LDA zpg, x */ ZeroXRead(OperationLDA), + /* 0xb6 LDX zpg, y */ ZeroYRead(OperationLDX), /* 0xb7 LAX zpg, x */ ZeroYRead(OperationLAX), + /* 0xb8 CLV */ Program(OperationCLV), /* 0xb9 LDA abs, y */ AbsoluteYRead(OperationLDA), + /* 0xba TSX */ Program(OperationTSX), /* 0xbb LAS abs, y */ AbsoluteYRead(OperationLAS), + /* 0xbc LDY abs, x */ AbsoluteXRead(OperationLDY), /* 0xbd LDA abs, x */ AbsoluteXRead(OperationLDA), + /* 0xbe LDX abs, y */ AbsoluteYRead(OperationLDX), /* 0xbf LAX abs, y */ AbsoluteYRead(OperationLAX), + /* 0xc0 CPY # */ Immediate(OperationCPY), /* 0xc1 CMP x, ind */ IndexedIndirectRead(OperationCMP), + /* 0xc2 NOP # */ ImmediateNop(), /* 0xc3 DCP x, ind */ IndexedIndirectReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xc4 CPY zpg */ ZeroRead(OperationCPY), /* 0xc5 CMP zpg */ ZeroRead(OperationCMP), + /* 0xc6 DEC zpg */ ZeroReadModifyWrite(OperationDEC), /* 0xc7 DCP zpg */ ZeroReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xc8 INY */ Program(OperationINY), /* 0xc9 CMP # */ Immediate(OperationCMP), + /* 0xca DEX */ Program(OperationDEX), /* 0xcb ARR # */ Immediate(OperationSBX), + /* 0xcc CPY abs */ AbsoluteRead(OperationCPY), /* 0xcd CMP abs */ AbsoluteRead(OperationCMP), + /* 0xce DEC abs */ AbsoluteReadModifyWrite(OperationDEC), /* 0xcf DCP abs */ AbsoluteReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xd0 BNE */ Program(OperationBNE), /* 0xd1 CMP ind, y */ IndirectIndexedRead(OperationCMP), + /* 0xd2 JAM */ JAM, /* 0xd3 DCP ind, y */ IndirectIndexedReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xd4 NOP zpg, x */ ZeroXNop(), /* 0xd5 CMP zpg, x */ ZeroXRead(OperationCMP), + /* 0xd6 DEC zpg, x */ ZeroXReadModifyWrite(OperationDEC), /* 0xd7 DCP zpg, x */ ZeroXReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xd8 CLD */ Program(OperationCLD), /* 0xd9 CMP abs, y */ AbsoluteYRead(OperationCMP), + /* 0xda NOP # */ ImpliedNop(), /* 0xdb DCP abs, y */ AbsoluteYReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xdc NOP abs, x */ AbsoluteXNop(), /* 0xdd CMP abs, x */ AbsoluteXRead(OperationCMP), + /* 0xde DEC abs, x */ AbsoluteXReadModifyWrite(OperationDEC), /* 0xdf DCP abs, x */ AbsoluteXReadModifyWrite(OperationDecrementOperand, OperationCMP), + /* 0xe0 CPX # */ Immediate(OperationCPX), /* 0xe1 SBC x, ind */ IndexedIndirectRead(OperationSBC), + /* 0xe2 NOP # */ ImmediateNop(), /* 0xe3 INS x, ind */ IndexedIndirectReadModifyWrite(OperationINS), + /* 0xe4 CPX zpg */ ZeroRead(OperationCPX), /* 0xe5 SBC zpg */ ZeroRead(OperationSBC), + /* 0xe6 INC zpg */ ZeroReadModifyWrite(OperationINC), /* 0xe7 INS zpg */ ZeroReadModifyWrite(OperationINS), + /* 0xe8 INX */ Program(OperationINX), /* 0xe9 SBC # */ Immediate(OperationSBC), + /* 0xea NOP # */ ImpliedNop(), /* 0xeb SBC # */ Immediate(OperationSBC), + /* 0xec CPX abs */ AbsoluteRead(OperationCPX), /* 0xed SBC abs */ AbsoluteRead(OperationSBC), + /* 0xee INC abs */ AbsoluteReadModifyWrite(OperationINC), /* 0xef INS abs */ AbsoluteReadModifyWrite(OperationINS), + /* 0xf0 BEQ */ Program(OperationBEQ), /* 0xf1 SBC ind, y */ IndirectIndexedRead(OperationSBC), + /* 0xf2 JAM */ JAM, /* 0xf3 INS ind, y */ IndirectIndexedReadModifyWrite(OperationINS), + /* 0xf4 NOP zpg, x */ ZeroXNop(), /* 0xf5 SBC zpg, x */ ZeroXRead(OperationSBC), + /* 0xf6 INC zpg, x */ ZeroXReadModifyWrite(OperationINC), /* 0xf7 INS zpg, x */ ZeroXReadModifyWrite(OperationINS), + /* 0xf8 SED */ Program(OperationSED), /* 0xf9 SBC abs, y */ AbsoluteYRead(OperationSBC), + /* 0xfa NOP # */ ImpliedNop(), /* 0xfb INS abs, y */ AbsoluteYReadModifyWrite(OperationINS), + /* 0xfc NOP abs, x */ AbsoluteXNop(), /* 0xfd SBC abs, x */ AbsoluteXRead(OperationSBC), + /* 0xfe INC abs, x */ AbsoluteXReadModifyWrite(OperationINC), /* 0xff INS abs, x */ AbsoluteXReadModifyWrite(OperationINS), + }; + + memcpy(operations_, operations_6502, sizeof(operations_)); +} #undef Program #undef Absolute @@ -243,11 +255,3 @@ const ProcessorStorage::MicroOp ProcessorStorage::operations[256][10] = { #undef IndirectIndexedReadModify #undef Immediate #undef Implied - -ProcessorStorage::ProcessorStorage() { - // 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; -} diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index 72509aba6..f9c47e866 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -15,7 +15,7 @@ */ class ProcessorStorage { protected: - ProcessorStorage(); + ProcessorStorage(Personality); /* This emulation functions by decomposing instructions into micro programs, consisting of the micro operations @@ -62,7 +62,7 @@ class ProcessorStorage { CycleScheduleJam }; - static const MicroOp operations[256][10]; + MicroOp operations_[256][10]; const MicroOp *scheduled_program_counter_ = nullptr; From ebce9a2e51e7aa1ffb92c864e7ce53b2a0bf94aa Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Aug 2018 21:15:13 -0400 Subject: [PATCH 03/18] Fixes test target. --- OSBindings/Mac/Clock SignalTests/Bridges/C1540Bridge.mm | 4 ++-- .../Mac/Clock SignalTests/Bridges/TestMachine6502.mm | 4 ++-- Processors/6502/AllRAM/6502AllRAM.cpp | 8 ++++---- Processors/6502/AllRAM/6502AllRAM.hpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/C1540Bridge.mm b/OSBindings/Mac/Clock SignalTests/Bridges/C1540Bridge.mm index 1aa3829d1..21c9da14e 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/C1540Bridge.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/C1540Bridge.mm @@ -32,8 +32,8 @@ class VanillaSerialPort: public Commodore::Serial::Port { _serialBus.reset(new ::Commodore::Serial::Bus); _serialPort.reset(new VanillaSerialPort); - _c1540.reset(new Commodore::C1540::Machine(Commodore::C1540::Machine::C1540)); - _c1540->set_rom_fetcher(CSROMFetcher()); + auto rom_fetcher = CSROMFetcher(); + _c1540.reset(new Commodore::C1540::Machine(Commodore::C1540::Personality::C1540, rom_fetcher)); _c1540->set_serial_bus(_serialBus); Commodore::Serial::AttachPortAndBus(_serialPort, _serialBus); } diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm index e4bbe2499..7477a0370 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm @@ -8,7 +8,7 @@ #import "TestMachine6502.h" #include -#include "6502AllRAM.hpp" +#include "../../../../Processors/6502/AllRAM/6502AllRAM.hpp" #import "TestMachine+ForSubclassEyesOnly.h" const uint8_t CSTestMachine6502JamOpcode = CPU::MOS6502::JamOpcode; @@ -39,7 +39,7 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) self = [super init]; if(self) { - _processor = CPU::MOS6502::AllRAMProcessor::Processor(); + _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502::Personality::P6502); } return self; diff --git a/Processors/6502/AllRAM/6502AllRAM.cpp b/Processors/6502/AllRAM/6502AllRAM.cpp index 8c9424576..a8c0f8a6b 100644 --- a/Processors/6502/AllRAM/6502AllRAM.cpp +++ b/Processors/6502/AllRAM/6502AllRAM.cpp @@ -17,8 +17,8 @@ namespace { class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler { public: - ConcreteAllRAMProcessor() : - mos6502_(*this) { + ConcreteAllRAMProcessor(Personality personality) : + mos6502_(personality, *this) { mos6502_.set_power_on(false); } @@ -68,6 +68,6 @@ class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler { } -AllRAMProcessor *AllRAMProcessor::Processor() { - return new ConcreteAllRAMProcessor; +AllRAMProcessor *AllRAMProcessor::Processor(Personality personality) { + return new ConcreteAllRAMProcessor(personality); } diff --git a/Processors/6502/AllRAM/6502AllRAM.hpp b/Processors/6502/AllRAM/6502AllRAM.hpp index 617edac36..41dc61245 100644 --- a/Processors/6502/AllRAM/6502AllRAM.hpp +++ b/Processors/6502/AllRAM/6502AllRAM.hpp @@ -19,7 +19,7 @@ class AllRAMProcessor: public ::CPU::AllRAMProcessor { public: - static AllRAMProcessor *Processor(); + static AllRAMProcessor *Processor(Personality personality); virtual ~AllRAMProcessor() {} virtual void run_for(const Cycles cycles) = 0; From 1a44ef046940e5ca12b20b3f76baa5e1a8fc5260 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Aug 2018 21:48:43 -0400 Subject: [PATCH 04/18] Introduces Klaus Dorman's 65C02 tests. All failing. --- .../Clock Signal.xcodeproj/project.pbxproj | 8 ++- .../6502InterruptTests.swift | 2 +- .../Clock SignalTests/6502TimingTests.swift | 2 +- .../Clock SignalTests/AllSuiteATests.swift | 2 +- .../Mac/Clock SignalTests/BCDTest.swift | 2 +- .../Bridges/TestMachine6502.h | 6 +- .../Bridges/TestMachine6502.mm | 5 +- .../65C02_extended_opcodes_test.bin | Bin 0 -> 65536 bytes .../Clock SignalTests/KlausDormannTests.swift | 66 +++++++++++++----- .../WolfgangLorenzTests.swift | 2 +- .../6502/Implementation/6502Storage.cpp | 8 ++- 11 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 OSBindings/Mac/Clock SignalTests/Klaus Dormann/65C02_extended_opcodes_test.bin diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 1cc8e6880..5a1ab50bb 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 4B018B89211930DE002A3937 /* 65C02_extended_opcodes_test.bin in Resources */ = {isa = PBXBuildFile; fileRef = 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */; }; 4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */; }; 4B0333AF2094081A0050B93D /* AppleDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0333AD2094081A0050B93D /* AppleDSK.cpp */; }; 4B0333B02094081A0050B93D /* AppleDSK.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0333AD2094081A0050B93D /* AppleDSK.cpp */; }; @@ -690,6 +691,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = 65C02_extended_opcodes_test.bin; path = "Klaus Dormann/65C02_extended_opcodes_test.bin"; sourceTree = ""; }; 4B01A6871F22F0DB001FD6E3 /* Z80MemptrTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MemptrTests.swift; sourceTree = ""; }; 4B0333AD2094081A0050B93D /* AppleDSK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDSK.cpp; sourceTree = ""; }; 4B0333AE2094081A0050B93D /* AppleDSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AppleDSK.hpp; sourceTree = ""; }; @@ -1545,14 +1547,15 @@ 4B1414631B588A1100E04248 /* Test Binaries */ = { isa = PBXGroup; children = ( - 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */, 4B9252CD1E74D28200B76AF1 /* Atari ROMs */, 4B44EBF81DC9898E00A7820C /* BCDTEST_beeb */, + 4B98A1CD1FFADEC400ADF63B /* MSX ROMs */, + 4B018B88211930DE002A3937 /* 65C02_extended_opcodes_test.bin */, 4B44EBF61DC9883B00A7820C /* 6502_functional_test.bin */, 4B44EBF41DC987AE00A7820C /* AllSuiteA.bin */, - 4BE9A6B21EDE294200CBCB47 /* Zexall */, 4BBF49B41ED2881600AB3669 /* FUSE */, 4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */, + 4BE9A6B21EDE294200CBCB47 /* Zexall */, ); name = "Test Binaries"; sourceTree = ""; @@ -3330,6 +3333,7 @@ 4BB2998A1B587D8400A49093 /* lseix in Resources */, 4BB2994E1B587D8400A49093 /* dexn in Resources */, 4BB299971B587D8400A49093 /* nopa in Resources */, + 4B018B89211930DE002A3937 /* 65C02_extended_opcodes_test.bin in Resources */, 4BFCA1291ECBE7A700AC40C1 /* zexall.com in Resources */, 4BB299521B587D8400A49093 /* eoray in Resources */, 4BB299411B587D8400A49093 /* cpyb in Resources */, diff --git a/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift b/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift index 98c9c6b8c..a6c0def50 100644 --- a/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift +++ b/OSBindings/Mac/Clock SignalTests/6502InterruptTests.swift @@ -15,7 +15,7 @@ class MOS6502InterruptTests: XCTestCase { super.setUp() // create a machine full of NOPs - machine = CSTestMachine6502() + machine = CSTestMachine6502(is65C02: false) for c in 0...65535 { machine.setValue(0xea, forAddress: UInt16(c)) } diff --git a/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift b/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift index fdccca3a7..514b41413 100644 --- a/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift +++ b/OSBindings/Mac/Clock SignalTests/6502TimingTests.swift @@ -12,7 +12,7 @@ import XCTest class MOS6502TimingTests: XCTestCase, CSTestMachineTrapHandler { private var endTime: UInt32 = 0 - private let machine = CSTestMachine6502() + private let machine = CSTestMachine6502(is65C02: false) func testImplied() { let code: [UInt8] = [ diff --git a/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift b/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift index 2aa7f992a..5c0a13607 100644 --- a/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift +++ b/OSBindings/Mac/Clock SignalTests/AllSuiteATests.swift @@ -13,7 +13,7 @@ class AllSuiteATests: XCTestCase { func testAllSuiteA() { if let filename = Bundle(for: type(of: self)).path(forResource: "AllSuiteA", ofType: "bin") { if let allSuiteA = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - let machine = CSTestMachine6502() + let machine = CSTestMachine6502(is65C02: false) machine.setData(allSuiteA, atAddress: 0x4000) machine.setValue(CSTestMachine6502JamOpcode, forAddress:0x45c0); // end diff --git a/OSBindings/Mac/Clock SignalTests/BCDTest.swift b/OSBindings/Mac/Clock SignalTests/BCDTest.swift index 7dbcfa435..6eb9850b0 100644 --- a/OSBindings/Mac/Clock SignalTests/BCDTest.swift +++ b/OSBindings/Mac/Clock SignalTests/BCDTest.swift @@ -14,7 +14,7 @@ class BCDTest: XCTestCase, CSTestMachineTrapHandler { func testBCD() { if let filename = Bundle(for: type(of: self)).path(forResource: "BCDTEST_beeb", ofType: nil) { if let bcdTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - let machine = CSTestMachine6502() + let machine = CSTestMachine6502(is65C02: false) machine.trapHandler = self machine.setData(bcdTest, atAddress: 0x2900) diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h index 5d78b5306..59b5f0aed 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.h @@ -23,7 +23,11 @@ extern const uint8_t CSTestMachine6502JamOpcode; @interface CSTestMachine6502 : CSTestMachine -- (void)setData:(NSData *)data atAddress:(uint16_t)startAddress; +- (nonnull instancetype)init NS_UNAVAILABLE; + +- (nonnull instancetype)initIs65C02:(BOOL)is65C02; + +- (void)setData:(nonnull NSData *)data atAddress:(uint16_t)startAddress; - (void)runForNumberOfCycles:(int)cycles; - (void)setValue:(uint8_t)value forAddress:(uint16_t)address; diff --git a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm index 7477a0370..d5a7787e9 100644 --- a/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm +++ b/OSBindings/Mac/Clock SignalTests/Bridges/TestMachine6502.mm @@ -35,11 +35,12 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg) #pragma mark - Lifecycle -- (instancetype)init { +- (instancetype)initIs65C02:(BOOL)is65C02 { self = [super init]; if(self) { - _processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502::Personality::P6502); + _processor = CPU::MOS6502::AllRAMProcessor::Processor( + is65C02 ? CPU::MOS6502::Personality::P65C02 : CPU::MOS6502::Personality::P6502); } return self; diff --git a/OSBindings/Mac/Clock SignalTests/Klaus Dormann/65C02_extended_opcodes_test.bin b/OSBindings/Mac/Clock SignalTests/Klaus Dormann/65C02_extended_opcodes_test.bin new file mode 100644 index 0000000000000000000000000000000000000000..b1ea946a1767f9b453325cf02df0bbbaba0cbf1e GIT binary patch literal 65536 zcmeI2dvH|M9mnsU?BgccSHg1?hYTP&6lb7dtMySJfFyDS%R?As22_e`rGr*ms~EF9 zw!{aeR$HJ#*;!n4c?eaiBS^D~glqxvDQrBOz$UV5820eGe69k0eG3efj{a@R{7;nm`oWJz74{qVGG(P_ zx$CBJHOl)h$D>PKQ3n4Mm*Qeeqf4W3YQWFYC{wJbit^b&r4y&!*%?yc^kGpY`Yo{V z-5uiFiNc>!$|}aTGnP@Z`IHNOPOXD#V&;*=mLn(gu55mH?p!v1UwR8}W@hsT3wo`P z&Bv2-;&bL4H2Zv$o0H9dlS^jvC(S;Yb=f?I1CwG99^aBG)F)j0h?;{^q&@>VJf+kp z6fD6IpfnOo(5rwYXt(sTfJQG1Xk=NyQm=1}ESQbH#{!3v*yE_;9`jfd<7za=Wr91+ zahYIKv6ltJJ)$g}HG^4~!K@QAVLovepQEOwS;rMDNwba@uq4ge3Kr*M1&gz`f~8*f z8Ck_yLoX;vvySJnB+VM)O|Up?D_ESh6~sN};OxLzm%*&vIP0bH2VmYQg-6S@pLtb0 z!%D|8RlxF6D2vJJ2}`s2^aCQr4JjT-i7U~YaCB|a>1jxAi%v{?;6Et4+u$o&rf-?P zb?I9Lx9N&(K3d%jU(q0LzJh;U&C%1*GdTNbpETsRMR%p)5Vb`&W34T^7Do@^DKCz` zDn2OXiuvK>OpWFtzjw9YtBv$&qkU>-wDmkq9W+{}__Uuu>p^pxNxy#L=ZzGIfFSKx zKJ8wIlw#}SK5dOXB@csQM#@0HcO#^{JA6g(Zz87U9}T{Wg^9<}?7 zimf%OHW*r^8Nr#9avLcl{N5dqQm<;09a4&|3svnldkP-jGe!zTKv(Uzs`jWuO0jjD zs_n3+oPiY8NEzezwm`~ZReQ@JrP%tps(ocoQ6Z(vNP!6Gs$Ed7T~yxPOR@Fxa_vfJ zmArI8O4vx5>i515Df7#HvHkWHDhm>OLtL54Od&((D zsWDRK`Mt*=z-6zpl`hIHVL?|5%}|v!{%OlolfeBA~1Gw+iiLhm>OL(F*ODJ*5RwqDD%S z-&=qbcctd5>^`Gn>!3>QVrZ3)bQDsWj1-7~uG+Pg+I0>o#nworcDp?V?xMLWxZe#D z_d73y`ry8kQZPB>XAQ1_uwf%$;~oPWbt-Ja^I%i67&c>@U=y9_2duCfespbw4ch@5 zcMELP*I^Sr2Ai5wuo+u`jo!P%pN->v&Ih0h`-|5l7;9^9hhO1NcaF0YC)5mF;}P?P zIQ6tBK5gFD(seL)xMdCvRnBKWVcG}4Wf91BYW6nhx5b84wu+BMe$8X_DhqkBw%A*jb`D z%aOgsWY_askXk~zvBm11mYWz85HHqyK#V$v7pUGau_aS?g#C|M_ zA3L&dnCvC|4P-Bo*tbOSEl2i4lO4c6M0SA09uUO?j_emE>*rq}>zCLUMDYbjw$fz3 z6=Q*-Bn(UMOMr5Cq*r}p8)sem3WFP0ZBm20- zjuFK%j_eYXUBQr3@6CB< zKAitu{`!38LwKy53XjA;##JZKfm!8{Re@QRdk+lVa9Yo*HL_+W-0_C{PdjCO4q5O_ zogQDzf`?tDEY)w7s|=PEU?}htOBC*RG0oEt_XFz%sY=)nJ_Xk$ro|_7MIT)T9_4b= zA!s5@71yTpk>N|@-o*C!E~6LRxO4DOkj4iCT+uMc505-4KaPJ}{3ud+enGvl=5Y>Q zWFz=1JWEIFGfl>?rNx-Y6>=;73hB^UXRpA~S`&8~5h4*6w)7o{M0`=VB+H3asDrW~vsrr~imUY1Z^^st6~?}VZH&^ixm4xiEoQ*ane zqZkY}*$313nm!n8vJa;5HGMGHWFJi9e;s67H1m5B`ew@Hg-i9Q2ud zfqy|@L2yB6L0HYeIvE^5IE?(SV7EPdTIvo*bc@t|i{2fNou&H*4}*9l_4xH3w%*Iu z``CJwtuJTReeCssxAySYxRVm4@1+}6+Le`(XL7gSn%*A%B;mG<%j~P~0Q;6Q?R`t5 z(dY1Ik2LP~@bQG(I*d|xJzMW?4YzbpFR`4#K{zZSJS=sIGQ3_2{L)^=RfLy7I~HAf zQCuc>I2E6DDt1B<4}g`%3-h?W*y2=dG>X;{jloELlvjnphq%}+!_=$Y#%ZZq25PC6 zMrtWqhH9x=#%ifr2CG-az)GWiP;nUSgX2_O0fn<2Pv4^G2bUQ|%d{TcXB4rg&{wKi z23n$F1cvC+e$1W)UK$bh%)$FOd~PzYR(PpSh4IFgjw=fSYcCF{kzp(rT-#9a1R4sl z&{|I*7GB|pp(F#mw_n{4mv^MToau*T7~2o0RWh_6F5pKzOmrFmC-8ZDL6Txmg89Qf z-or9JBdrjxQwln*m^$lGCK+HmGnhtoy6Ajk(2BsJf-PN#5#$s=Obs?$zwp`g04-orA?PLp(xcsV<*m^$l9y{3tBrcZfB(~bf;>Q|EzS2&@^`Lj*WN&O>{;>Qq4 zzNSYOTO}4=%8ZW+n8)nvWF~eeYsv0lm_u|`e zGEx5bOVkYXgiH1Nc+-YjlU{=}2Ws#cfnIw+uffN9P}_+$I4!I!zOrD=%0hx(v$AKQ zmU|BdwcRqPY8X^698_IgNnR22C$EeJU?49}XMB`jedk6vVc?1Koq6zohrbOz_4}Z? z6;EloL!;iI)!!Wc2x96WX1s`*#rU)yW26pp%(W0RS;S0byt>C2se>gZXMM%$1#|5U zbDjNmA{Z~=6&4G`f~!0%7K(-8CRx48%iwNU)xT!S&<=k`NQGClWjxC|!k%!f>T;;I z`a1&I9FXCEdss&h+hbL&)rY(+8H|OptvPs6!w;X$7fE=-nCb(&{951RI&*(`yM}!( zja5My?)UPVt|6`dWGJh)hEwYxt9n={>u(KNzj1dslK#-Q!=DUv_R;$US}ot&9ns~>81(xsQ0h2SMI#QUioacz4D7`_R8loq{{qc)v)F8 zgflTXvI4fDusc#dwmuT80=Xu<&(LkcqB8%{q09Ofmjia@@5qnLcjhw|Ulny}L_)|A^qZ$`TGw_46W z>EqAVIye50R`oHj;NRUpz@nLx0Wv@a$N(8217v^fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^ UInt16 { + if let filename = Bundle(for: type(of: self)).path(forResource: resource, ofType: "bin") { + if let functionalTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) { + let machine = CSTestMachine6502(is65C02: is65C02) + machine.setData(functionalTest, atAddress: 0) + machine.setValue(0x400, for: .programCounter) + + while true { + let oldPC = machine.value(for: .lastOperationAddress) + machine.runForNumber(ofCycles: 1000) + let newPC = machine.value(for: .lastOperationAddress) + + if newPC == oldPC { + return newPC + } + } + } + } + + return 0 + } + + /// Runs Klaus Dorman's 6502 tests. + func test6502() { func errorForTrapAddress(_ address: UInt16) -> String? { - let hexAddress = String(format:"%04x", address) switch address { case 0x3399: return nil // success! @@ -28,29 +50,35 @@ class KlausDormannTests: XCTestCase { case 0x26d2: return "ASL zpg,x produced incorrect flags" case 0x36c6: return "Unexpected RESET" - default: return "Unknown error at \(hexAddress)" + case 0: return "Didn't find tests" + + default: return "Unknown error at \(String(format:"%04x", address))" } } - if let filename = Bundle(for: type(of: self)).path(forResource: "6502_functional_test", ofType: "bin") { - if let functionalTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - let machine = CSTestMachine6502() + let destination = runTest(resource: "6502_functional_test", is65C02: false) + let error = errorForTrapAddress(destination) + XCTAssert(error == nil, "Failed with error \(error!)") + } - machine.setData(functionalTest, atAddress: 0) - machine.setValue(0x400, for: .programCounter) + /// Runs Klaus Dorman's 65C02 tests. + func test65C02() { + func errorForTrapAddress(_ address: UInt16) -> String? { + switch address { + case 0x0423: return "PHX: value of X not on stack page" + case 0x0428: return "PHX: stack pointer not decremented" + case 0x042d: return "PLY: didn't acquire value 0xaa from stack" + case 0x0432: return "PLY: didn't acquire value 0x55 from stack" + case 0x0437: return "PLY: stack pointer not incremented" + case 0x043c: return "PLY: stack pointer not incremented" - while true { - let oldPC = machine.value(for: .lastOperationAddress) - machine.runForNumber(ofCycles: 1000) - let newPC = machine.value(for: .lastOperationAddress) - - if newPC == oldPC { - let error = errorForTrapAddress(oldPC) - XCTAssert(error == nil, "Failed with error \(error!)") - return - } - } + case 0: return "Didn't find tests" + default: return "Unknown error at \(String(format:"%04x", address))" } } + + let destination = runTest(resource: "65C02_extended_opcodes_test", is65C02: true) + let error = errorForTrapAddress(destination) + XCTAssert(error == nil, "Failed with error \(error!)") } } diff --git a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift index 9f0660853..4ec9be87b 100644 --- a/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift +++ b/OSBindings/Mac/Clock SignalTests/WolfgangLorenzTests.swift @@ -200,7 +200,7 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler { if let filename = Bundle(for: type(of: self)).path(forResource: name, ofType: nil) { if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) { - machine = CSTestMachine6502() + machine = CSTestMachine6502(is65C02: false) machine.trapHandler = self // machine.logActivity = true output = "" diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index c6a916b22..6dd33f569 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -69,7 +69,7 @@ using namespace CPU::MOS6502; #define JAM {CycleFetchOperand, CycleScheduleJam} -ProcessorStorage::ProcessorStorage(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; @@ -214,7 +214,13 @@ ProcessorStorage::ProcessorStorage(Personality) { /* 0xfe INC abs, x */ AbsoluteXReadModifyWrite(OperationINC), /* 0xff INS abs, x */ AbsoluteXReadModifyWrite(OperationINS), }; + // Install the basic 6502 table. memcpy(operations_, operations_6502, sizeof(operations_)); + + // Patch the table according to the chip's personality. + switch(personality) { + default: break; + } } #undef Program From 5c881bd19d8a28f8d0cbfbc62be0350d59dd5892 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Aug 2018 22:00:23 -0400 Subject: [PATCH 05/18] Implements PLX, PLY, PHX and PHY. --- .../6502/Implementation/6502Implementation.hpp | 6 ++++++ Processors/6502/Implementation/6502Storage.cpp | 13 +++++++++++-- Processors/6502/Implementation/6502Storage.hpp | 5 +++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 7f999bde8..6761da892 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -115,6 +115,8 @@ if(number_of_cycles <= Cycles(0)) break; case CyclePushPCL: push(pc_.bytes.low); break; case CyclePushOperand: push(operand_); break; case CyclePushA: push(a_); break; + case CyclePushX: push(x_); break; + case CyclePushY: push(y_); break; case CycleNoWritePush: { uint16_t targetAddress = s_ | 0x100; s_--; read_mem(operand_, targetAddress); @@ -140,11 +142,15 @@ if(number_of_cycles <= Cycles(0)) break; case CyclePullPCL: s_++; read_mem(pc_.bytes.low, s_ | 0x100); break; case CyclePullPCH: s_++; read_mem(pc_.bytes.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 CycleIncrementPCAndReadStack: pc_.full++; throwaway_read(s_ | 0x100); break; case CycleReadPCLFromAddress: read_mem(pc_.bytes.low, address_.full); break; diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 6dd33f569..7dd903629 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -218,8 +218,17 @@ ProcessorStorage::ProcessorStorage(Personality personality) { memcpy(operations_, operations_6502, sizeof(operations_)); // Patch the table according to the chip's personality. - switch(personality) { - default: break; + if(personality != P6502) { + // This is a 65C02 or 65SC02; add P[L/H][X/Y] + const ProcessorStorage::MicroOp phx[10] = Program(CyclePushX); + const ProcessorStorage::MicroOp phy[10] = Program(CyclePushY); + const ProcessorStorage::MicroOp plx[10] = Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX); + const ProcessorStorage::MicroOp ply[10] = Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY); + + memcpy(&operations_[0x5a], phy, sizeof(phy)); + memcpy(&operations_[0xda], phx, sizeof(phx)); + memcpy(&operations_[0x7a], ply, sizeof(ply)); + memcpy(&operations_[0xfa], plx, sizeof(plx)); } } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index f9c47e866..a9265ef6f 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -25,13 +25,14 @@ class ProcessorStorage { enum MicroOp { CycleFetchOperation, CycleFetchOperand, OperationDecodeOperation, CycleIncPCPushPCH, CyclePushPCH, CyclePushPCL, CyclePushA, CyclePushOperand, - OperationSetI, + CyclePushX, CyclePushY, OperationSetI, OperationBRKPickVector, OperationNMIPickVector, OperationRSTPickVector, CycleReadVectorLow, CycleReadVectorHigh, CycleReadFromS, CycleReadFromPC, CyclePullOperand, CyclePullPCL, CyclePullPCH, CyclePullA, + CyclePullX, CyclePullY, CycleNoWritePush, CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL, CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute, @@ -58,7 +59,7 @@ class ProcessorStorage { OperationSBX, OperationLXA, OperationANE, OperationANC, OperationLAS, CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, OperationSetOperandFromFlags, - OperationSetFlagsFromA, + OperationSetFlagsFromA, OperationSetFlagsFromX, OperationSetFlagsFromY, CycleScheduleJam }; From 32338bea4dc3f64b5402f6347104fa2d16fa0387 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 6 Aug 2018 22:37:30 -0400 Subject: [PATCH 06/18] Implements BRA. --- .../Clock SignalTests/KlausDormannTests.swift | 4 +++ .../Implementation/6502Implementation.hpp | 1 + .../6502/Implementation/6502Storage.cpp | 28 ++++++++++++------- .../6502/Implementation/6502Storage.hpp | 9 +++--- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index f884413d2..71a82f171 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -72,6 +72,10 @@ class KlausDormannTests: XCTestCase { case 0x0437: return "PLY: stack pointer not incremented" case 0x043c: return "PLY: stack pointer not incremented" + case 0x066a: return "BRA: branch not taken" + case 0x0730: return "BBS: branch not taken" + case 0x0733: return "BBR: branch taken" + case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" } diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 6761da892..043534991 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -470,6 +470,7 @@ if(number_of_cycles <= Cycles(0)) break; case OperationBCS: BRA(carry_flag_); continue; case OperationBNE: BRA(zero_result_); continue; case OperationBEQ: BRA(!zero_result_); continue; + case OperationBRA: BRA(true); continue; case CycleAddSignedOperandToPC: nextAddress.full = static_cast(pc_.full + (int8_t)operand_); diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 7dd903629..31efd30e4 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -76,7 +76,9 @@ ProcessorStorage::ProcessorStorage(Personality personality) { decimal_flag_ &= Flag::Decimal; overflow_flag_ &= Flag::Overflow; - const ProcessorStorage::MicroOp operations_6502[256][10] = { + using InstructionList = ProcessorStorage::MicroOp[10]; + + const InstructionList operations_6502[256] = { /* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetI, CycleReadVectorLow, CycleReadVectorHigh), /* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA), /* 0x02 JAM */ JAM, /* 0x03 ASO x, ind */ IndexedIndirectReadModifyWrite(OperationASO), @@ -218,18 +220,24 @@ ProcessorStorage::ProcessorStorage(Personality personality) { memcpy(operations_, operations_6502, sizeof(operations_)); // Patch the table according to the chip's personality. +#define Install(location, code) memcpy(&operations_[location], code, sizeof(InstructionList)) if(personality != P6502) { - // This is a 65C02 or 65SC02; add P[L/H][X/Y] - const ProcessorStorage::MicroOp phx[10] = Program(CyclePushX); - const ProcessorStorage::MicroOp phy[10] = Program(CyclePushY); - const ProcessorStorage::MicroOp plx[10] = Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX); - const ProcessorStorage::MicroOp ply[10] = Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY); + // Add P[L/H][X/Y]. + const InstructionList phx = Program(CyclePushX); + const InstructionList phy = Program(CyclePushY); + const InstructionList plx = Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX); + const InstructionList ply = Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY); - memcpy(&operations_[0x5a], phy, sizeof(phy)); - memcpy(&operations_[0xda], phx, sizeof(phx)); - memcpy(&operations_[0x7a], ply, sizeof(ply)); - memcpy(&operations_[0xfa], plx, sizeof(plx)); + Install(0x5a, phy); + Install(0xda, phx); + Install(0x7a, ply); + Install(0xfa, plx); + + // Add BRA and the various BBS and BBRs. + const InstructionList bra = Program(OperationBRA); + Install(0x80, bra); } +#undef Install } #undef Program diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index a9265ef6f..bb9a06d83 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -54,10 +54,11 @@ class ProcessorStorage { OperationDEC, OperationINX, OperationDEX, OperationINY, OperationDEY, OperationBPL, OperationBMI, OperationBVC, OperationBVS, OperationBCC, OperationBCS, OperationBNE, - OperationBEQ, OperationTXA, OperationTYA, OperationTXS, - OperationTAY, OperationTAX, OperationTSX, OperationARR, - OperationSBX, OperationLXA, OperationANE, OperationANC, - OperationLAS, CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, + OperationBEQ, OperationBRA, OperationTXA, OperationTYA, + OperationTXS, OperationTAY, OperationTAX, OperationTSX, + OperationARR, OperationSBX, OperationLXA, OperationANE, + OperationANC, OperationLAS, + CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, OperationSetOperandFromFlags, OperationSetFlagsFromA, OperationSetFlagsFromX, OperationSetFlagsFromY, CycleScheduleJam From e46bde35f556aa1099f459e0235eff343d9a1ab3 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Aug 2018 21:52:17 -0400 Subject: [PATCH 07/18] Implements BBS and BBR. --- .../Implementation/6502Implementation.hpp | 37 ++++++++++++++++++- .../6502/Implementation/6502Storage.cpp | 34 ++++++++++------- .../6502/Implementation/6502Storage.hpp | 21 ++++++++--- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 043534991..4d3cca800 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -13,7 +13,7 @@ */ template void Processor::run_for(const Cycles cycles) { - static const MicroOp doBranch[] = { + static const MicroOp do_branch[] = { CycleReadFromPC, CycleAddSignedOperandToPC, OperationMoveToNextProgram @@ -460,7 +460,7 @@ if(number_of_cycles <= Cycles(0)) break; // MARK: - Branching -#define BRA(condition) pc_.full++; if(condition) scheduled_program_counter_ = doBranch +#define BRA(condition) pc_.full++; if(condition) scheduled_program_counter_ = do_branch case OperationBPL: BRA(!(negative_result_&0x80)); continue; case OperationBMI: BRA(negative_result_&0x80); continue; @@ -483,6 +483,39 @@ if(number_of_cycles <= Cycles(0)) break; } continue; + case CycleFetchFromHalfUpdatedPC: { + uint16_t halfUpdatedPc = static_cast(((pc_.bytes.low + (int8_t)operand_) & 0xff) | (pc_.bytes.high << 8)); + throwaway_read(halfUpdatedPc); + } break; + + case OperationAddSignedOperandToPC16: + pc_.full = static_cast(pc_.full + (int8_t)operand_); + continue; + + case OperationBBRBBS: { + // To reach here, the 6502 has (i) read the operation; (ii) read the first operand; + // and (iii) read from the corresponding zero page. + const uint8_t mask = static_cast(1 << ((operation_ >> 4)&7)); + if((operand_ & mask) == ((operation_ & 0x80) ? mask : 0)) { + static const MicroOp do_branch[] = { + CycleFetchOperand, // Fetch offset. + OperationIncrementPC, + CycleFetchFromHalfUpdatedPC, + OperationAddSignedOperandToPC16, + OperationMoveToNextProgram + }; + scheduled_program_counter_ = do_branch; + } else { + static const MicroOp do_not_branch[] = { + CycleFetchOperand, + OperationIncrementPC, + CycleFetchFromHalfUpdatedPC, + OperationMoveToNextProgram + }; + scheduled_program_counter_ = do_not_branch; + } + } break; + #undef BRA // MARK: - Transfers diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 31efd30e4..264287f4e 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -76,8 +76,6 @@ ProcessorStorage::ProcessorStorage(Personality personality) { decimal_flag_ &= Flag::Decimal; overflow_flag_ &= Flag::Overflow; - using InstructionList = ProcessorStorage::MicroOp[10]; - const InstructionList operations_6502[256] = { /* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetI, CycleReadVectorLow, CycleReadVectorHigh), /* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA), @@ -220,22 +218,30 @@ ProcessorStorage::ProcessorStorage(Personality personality) { memcpy(operations_, operations_6502, sizeof(operations_)); // Patch the table according to the chip's personality. -#define Install(location, code) memcpy(&operations_[location], code, sizeof(InstructionList)) +#define Install(location, instructions) {\ + const InstructionList code = instructions; \ + memcpy(&operations_[location], code, sizeof(InstructionList)); \ + } if(personality != P6502) { // Add P[L/H][X/Y]. - const InstructionList phx = Program(CyclePushX); - const InstructionList phy = Program(CyclePushY); - const InstructionList plx = Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX); - const InstructionList ply = Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY); + Install(0x5a, Program(CyclePushY)); + Install(0xda, Program(CyclePushX)); + Install(0x7a, Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY)); + Install(0xfa, Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX)); - Install(0x5a, phy); - Install(0xda, phx); - Install(0x7a, ply); - Install(0xfa, plx); + // Add BRA. + Install(0x80, Program(OperationBRA)); - // Add BRA and the various BBS and BBRs. - const InstructionList bra = Program(OperationBRA); - Install(0x80, bra); + // Add BBS and BBR. These take five cycles. My guessed breakdown is: + // 1. read opcode + // 2. read operand + // 3. read zero page + // 4. read second operand + // 5. read from PC without top byte fixed yet + // ... with the caveat that (3) and (4) could be the other way around. + for(int location = 0x0f; location <= 0xff; location += 0x10) { + Install(location, Program(OperationLoadAddressZeroPage, CycleFetchOperandFromAddress, OperationBBRBBS)); + } } #undef Install } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index bb9a06d83..bc58eb74a 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -52,19 +52,28 @@ class ProcessorStorage { OperationCLC, OperationCLI, OperationCLV, OperationCLD, OperationSEC, OperationSEI, OperationSED, OperationINC, OperationDEC, OperationINX, OperationDEX, OperationINY, - OperationDEY, OperationBPL, OperationBMI, OperationBVC, - OperationBVS, OperationBCC, OperationBCS, OperationBNE, - OperationBEQ, OperationBRA, OperationTXA, OperationTYA, - OperationTXS, OperationTAY, OperationTAX, OperationTSX, + OperationDEY, + + OperationBPL, OperationBMI, OperationBVC, OperationBVS, + OperationBCC, OperationBCS, OperationBNE, OperationBEQ, + OperationBRA, OperationBBRBBS, + + OperationTXA, OperationTYA, OperationTXS, OperationTAY, + OperationTAX, OperationTSX, + OperationARR, OperationSBX, OperationLXA, OperationANE, OperationANC, OperationLAS, - CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, + + CycleFetchFromHalfUpdatedPC, CycleAddSignedOperandToPC, OperationAddSignedOperandToPC16, + + OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet, OperationSetOperandFromFlags, OperationSetFlagsFromA, OperationSetFlagsFromX, OperationSetFlagsFromY, CycleScheduleJam }; - MicroOp operations_[256][10]; + using InstructionList = MicroOp[10]; + InstructionList operations_[256]; const MicroOp *scheduled_program_counter_ = nullptr; From e3f6da6994af9f6ed82c9eff97d83ee964cf99ae Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 8 Aug 2018 20:00:14 -0400 Subject: [PATCH 08/18] Implements the 65C02 NOPs. --- .../Clock SignalTests/KlausDormannTests.swift | 2 ++ Processors/6502/6502.hpp | 3 ++- .../6502/Implementation/6502Implementation.hpp | 11 ++++++++++- Processors/6502/Implementation/6502Storage.cpp | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 71a82f171..7da2aa683 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -76,6 +76,8 @@ class KlausDormannTests: XCTestCase { case 0x0730: return "BBS: branch not taken" case 0x0733: return "BBR: branch taken" + case 0x2884: return "JMP (abs) exhibited 6502 page-crossing bug" + case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" } diff --git a/Processors/6502/6502.hpp b/Processors/6502/6502.hpp index 37a2e6eca..00fb75429 100644 --- a/Processors/6502/6502.hpp +++ b/Processors/6502/6502.hpp @@ -204,7 +204,7 @@ template class Processor: public ProcessorBas /*! Constructs an instance of the 6502 that will use @c bus_handler for all bus communications. */ - Processor(Personality personality, T &bus_handler) : ProcessorBase(personality), bus_handler_(bus_handler) {} + Processor(Personality personality, T &bus_handler) : ProcessorBase(personality), personality_(personality), bus_handler_(bus_handler) {} /*! Runs the 6502 for a supplied number of cycles. @@ -221,6 +221,7 @@ template class Processor: public ProcessorBas void set_ready_line(bool active); private: + Personality personality_; T &bus_handler_; }; diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 4d3cca800..3a3ef35a5 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -93,7 +93,16 @@ if(number_of_cycles <= Cycles(0)) break; } break; case CycleFetchOperand: - read_mem(operand_, pc_.full); + if( + personality_ == P6502 || + (operation_&7) != 3 || + operation_ == 0xcb || + operation_ == 0xdb + ) { + read_mem(operand_, pc_.full); + } else { + printf("Skipping %02x\n", operation_); + } break; case OperationDecodeOperation: diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 264287f4e..517a09420 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -242,6 +242,24 @@ ProcessorStorage::ProcessorStorage(Personality personality) { for(int location = 0x0f; location <= 0xff; location += 0x10) { Install(location, Program(OperationLoadAddressZeroPage, CycleFetchOperandFromAddress, OperationBBRBBS)); } + + // Add NOPs. + + // The 1-byte, 1-cycle (!) NOPs. + for(int c = 0x03; c <= 0xf3; c += 0x10) { + Install(c, ImpliedNop()); + } + for(int c = 0x0b; c <= 0xbb; c += 0x10) { + Install(c, ImpliedNop()); + } + for(int c = 0xeb; c <= 0xfb; c += 0x10) { + Install(c, ImpliedNop()); + } + + // The 2-byte, 2-cycle NOPs that the 6502 doesn't have. + for(int c = 0x02; c <= 0x62; c += 0x10) { + Install(c, ImmediateNop()); + } } #undef Install } From bb680b40d89296c331bce500f0789c7f24b58bcc Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 8 Aug 2018 22:26:57 -0400 Subject: [PATCH 09/18] Implements the 65C02's JMPs. --- .../Clock SignalTests/KlausDormannTests.swift | 5 +++++ .../Implementation/6502Implementation.hpp | 19 +++++++++++++------ .../6502/Implementation/6502Storage.cpp | 11 ++++++++++- .../6502/Implementation/6502Storage.hpp | 6 +++++- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 7da2aa683..17928cdbe 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -77,6 +77,11 @@ class KlausDormannTests: XCTestCase { case 0x0733: return "BBR: branch taken" case 0x2884: return "JMP (abs) exhibited 6502 page-crossing bug" + case 0x16ca: return "JMP (abs, x) failed" + + case 0x2785: return "BRK didn't clear the decimal mode flag" + + case 0x177b: return "INC A didn't function" case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 3a3ef35a5..b39122e8b 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -93,6 +93,10 @@ if(number_of_cycles <= Cycles(0)) break; } break; case CycleFetchOperand: + // This is supposed to produce the 65C02's 1-cycle NOPs; they're + // treated as a special case because they break the rule that + // governs everything else on the 6502: that two bytes will always + // be fetched. if( personality_ == P6502 || (operation_&7) != 3 || @@ -100,8 +104,6 @@ if(number_of_cycles <= Cycles(0)) break; operation_ == 0xdb ) { read_mem(operand_, pc_.full); - } else { - printf("Skipping %02x\n", operation_); } break; @@ -146,7 +148,10 @@ if(number_of_cycles <= Cycles(0)) break; case OperationRSTPickVector: nextAddress.full = 0xfffc; continue; case CycleReadVectorLow: read_mem(pc_.bytes.low, nextAddress.full); break; case CycleReadVectorHigh: read_mem(pc_.bytes.high, nextAddress.full+1); break; - case OperationSetI: inverse_interrupt_flag_ = 0; continue; + case OperationSetI: + inverse_interrupt_flag_ = 0; + if(personality_ != P6502) decimal_flag_ = false; + continue; case CyclePullPCL: s_++; read_mem(pc_.bytes.low, s_ | 0x100); break; case CyclePullPCH: s_++; read_mem(pc_.bytes.high, s_ | 0x100); break; @@ -161,9 +166,11 @@ if(number_of_cycles <= Cycles(0)) break; case OperationSetFlagsFromX: zero_result_ = negative_result_ = x_; continue; case OperationSetFlagsFromY: zero_result_ = negative_result_ = y_; continue; - case CycleIncrementPCAndReadStack: pc_.full++; throwaway_read(s_ | 0x100); break; - case CycleReadPCLFromAddress: read_mem(pc_.bytes.low, address_.full); break; - case CycleReadPCHFromAddress: address_.bytes.low++; read_mem(pc_.bytes.high, address_.full); break; + case CycleIncrementPCAndReadStack: pc_.full++; throwaway_read(s_ | 0x100); break; + case CycleReadPCLFromAddress: read_mem(pc_.bytes.low, address_.full); break; + case CycleReadPCHFromAddressLowInc: address_.bytes.low++; read_mem(pc_.bytes.high, address_.full); break; + case CycleReadPCHFromAddressFixed: if(!address_.bytes.low) address_.bytes.high++; read_mem(pc_.bytes.high, address_.full); break; + case CycleReadPCHFromAddressInc: address_.full++; read_mem(pc_.bytes.high, address_.full); break; case CycleReadAndIncrementPC: { uint16_t oldPC = pc_.full; diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 517a09420..92e200182 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -137,7 +137,7 @@ ProcessorStorage::ProcessorStorage(Personality personality) { /* 0x66 ROR zpg */ ZeroReadModifyWrite(OperationROR), /* 0x67 RRA zpg */ ZeroReadModifyWrite(OperationRRA, OperationADC), /* 0x68 PLA */ Program(CycleReadFromS, CyclePullA, OperationSetFlagsFromA), /* 0x69 ADC # */ Immediate(OperationADC), /* 0x6a ROR A */ Implied(OperationROR), /* 0x6b ARR # */ Immediate(OperationARR), - /* 0x6c JMP (abs) */ Program(CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress), + /* 0x6c JMP (abs) */ Program(CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddressLowInc), /* 0x6d ADC abs */ AbsoluteRead(OperationADC), /* 0x6e ROR abs */ AbsoluteReadModifyWrite(OperationROR), /* 0x6f RRA abs */ AbsoluteReadModifyWrite(OperationRRA, OperationADC), /* 0x70 BVS */ Program(OperationBVS), /* 0x71 ADC ind, y */ IndirectIndexedRead(OperationADC), @@ -260,6 +260,15 @@ ProcessorStorage::ProcessorStorage(Personality personality) { for(int c = 0x02; c <= 0x62; c += 0x10) { Install(c, ImmediateNop()); } + + // Correct JMP (abs) and install JMP (abs, x). + Install(0x6c, Program(CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddressLowInc, CycleReadPCHFromAddressFixed)); + Install(0x7c, Program( + CycleReadAddressHLoadAddressL, // (3) read second byte of (addr) + CycleAddXToAddressLowRead, // (4) calculate addr+x, read from (addr+x) with high byte not yet calculated + OperationCorrectAddressHigh, CycleReadPCLFromAddress, // (5) read from real (addr+x) + CycleReadPCHFromAddressInc // (6) read from addr+x+1 + )); } #undef Install } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index bc58eb74a..d77a18103 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -35,7 +35,11 @@ class ProcessorStorage { CyclePullX, CyclePullY, CycleNoWritePush, CycleReadAndIncrementPC, CycleIncrementPCAndReadStack, CycleIncrementPCReadPCHLoadPCL, CycleReadPCHLoadPCL, - CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddress, CycleLoadAddressAbsolute, + CycleReadAddressHLoadAddressL, + + CycleReadPCLFromAddress, CycleReadPCHFromAddressLowInc, CycleReadPCHFromAddressFixed, CycleReadPCHFromAddressInc, + + CycleLoadAddressAbsolute, OperationLoadAddressZeroPage, CycleLoadAddessZeroX, CycleLoadAddessZeroY, CycleAddXToAddressLow, CycleAddYToAddressLow, CycleAddXToAddressLowRead, OperationCorrectAddressHigh, CycleAddYToAddressLowRead, OperationMoveToNextProgram, OperationIncrementPC, From 6f838fe1906972775677ddc90ca62882c9679d27 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 8 Aug 2018 22:30:19 -0400 Subject: [PATCH 10/18] Implements INA and DEA. --- Processors/6502/Implementation/6502Implementation.hpp | 2 ++ Processors/6502/Implementation/6502Storage.cpp | 4 ++++ Processors/6502/Implementation/6502Storage.hpp | 7 ++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index b39122e8b..7dbe6d069 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -367,6 +367,8 @@ if(number_of_cycles <= Cycles(0)) break; 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; diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 92e200182..d117a82fb 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -269,6 +269,10 @@ ProcessorStorage::ProcessorStorage(Personality personality) { OperationCorrectAddressHigh, CycleReadPCLFromAddress, // (5) read from real (addr+x) CycleReadPCHFromAddressInc // (6) read from addr+x+1 )); + + // Add INA and DEA. + Install(0x1a, Program(OperationINA)); + Install(0x3a, Program(OperationDEA)); } #undef Install } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index d77a18103..ec48d8d36 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -54,9 +54,10 @@ class ProcessorStorage { OperationASO, OperationROL, OperationRLA, OperationLSR, OperationLSE, OperationASR, OperationROR, OperationRRA, OperationCLC, OperationCLI, OperationCLV, OperationCLD, - OperationSEC, OperationSEI, OperationSED, OperationINC, - OperationDEC, OperationINX, OperationDEX, OperationINY, - OperationDEY, + OperationSEC, OperationSEI, OperationSED, + + OperationINC, OperationDEC, OperationINX, OperationDEX, + OperationINY, OperationDEY, OperationINA, OperationDEA, OperationBPL, OperationBMI, OperationBVC, OperationBVS, OperationBCC, OperationBCS, OperationBNE, OperationBEQ, From 95164b79c90b9f2b5b36253bcc796c23bab4780c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 9 Aug 2018 21:51:14 -0400 Subject: [PATCH 11/18] Attempted implementation of (zp) addressing mode. --- .../Mac/Clock SignalTests/KlausDormannTests.swift | 4 ++++ Processors/6502/Implementation/6502Storage.cpp | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 17928cdbe..6a614019c 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -83,6 +83,10 @@ class KlausDormannTests: XCTestCase { case 0x177b: return "INC A didn't function" + case 0x1834: return "LDA (zp) acted as JAM" + case 0x183a: return "STA (zp) acted as JAM" + case 0x1849: return "LDA/STA (zp) left flags in incorrect state" + case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" } diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index d117a82fb..385ea326d 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -22,6 +22,7 @@ using namespace CPU::MOS6502; #define Zero OperationLoadAddressZeroPage #define ZeroX CycleLoadAddessZeroX #define ZeroY CycleLoadAddessZeroY +#define ZeroIndirect OperationLoadAddressZeroPage, CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh #define IndexedIndirect CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh #define IndirectIndexedr CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh, CycleAddYToAddressLow, OperationCorrectAddressHigh #define IndirectIndexed CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh, CycleAddYToAddressLowRead, OperationCorrectAddressHigh @@ -36,6 +37,7 @@ using namespace CPU::MOS6502; #define ZeroRead(...) Program(Zero, Read(__VA_ARGS__)) #define ZeroXRead(op) Program(ZeroX, Read(op)) #define ZeroYRead(op) Program(ZeroY, Read(op)) +#define ZeroIndirectRead(op) Program(ZeroIndirect, Read(op)) #define IndexedIndirectRead(op) Program(IndexedIndirect, Read(op)) #define IndirectIndexedRead(op) Program(IndirectIndexedr, Read(op)) @@ -45,6 +47,7 @@ using namespace CPU::MOS6502; #define ZeroWrite(op) Program(Zero, Write(op)) #define ZeroXWrite(op) Program(ZeroX, Write(op)) #define ZeroYWrite(op) Program(ZeroY, Write(op)) +#define ZeroIndirectWrite(op) Program(ZeroIndirect, Write(op)) #define IndexedIndirectWrite(op) Program(IndexedIndirect, Write(op)) #define IndirectIndexedWrite(op) Program(IndirectIndexed, Write(op)) @@ -273,6 +276,16 @@ ProcessorStorage::ProcessorStorage(Personality personality) { // Add INA and DEA. Install(0x1a, Program(OperationINA)); Install(0x3a, Program(OperationDEA)); + + // Add (zp) operations. + Install(0x12, ZeroIndirectRead(OperationORA)); + Install(0x32, ZeroIndirectRead(OperationAND)); + Install(0x52, ZeroIndirectRead(OperationEOR)); + Install(0x72, ZeroIndirectRead(OperationADC)); + Install(0x92, ZeroIndirectRead(OperationSTA)); + Install(0xb2, ZeroIndirectRead(OperationLDA)); + Install(0xd2, ZeroIndirectWrite(OperationCMP)); + Install(0xd2, ZeroIndirectRead(OperationSBC)); } #undef Install } From 8b50ab2593c1e24a897b5962a2af417ab8deef6f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 21:12:55 -0400 Subject: [PATCH 12/18] Corrects (zero) behaviour. --- Processors/6502/Implementation/6502Implementation.hpp | 3 +++ Processors/6502/Implementation/6502Storage.cpp | 8 ++++---- Processors/6502/Implementation/6502Storage.hpp | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 7dbe6d069..ca0a371c6 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -429,6 +429,9 @@ if(number_of_cycles <= Cycles(0)) break; operand_ += x_; read_mem(address_.bytes.low, operand_); break; + case CycleFetchAddressLowFromOperand: + read_mem(address_.bytes.low, operand_); + break; case CycleIncrementOperandFetchAddressHigh: operand_++; read_mem(address_.bytes.high, operand_); diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 385ea326d..786394d45 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -22,14 +22,14 @@ using namespace CPU::MOS6502; #define Zero OperationLoadAddressZeroPage #define ZeroX CycleLoadAddessZeroX #define ZeroY CycleLoadAddessZeroY -#define ZeroIndirect OperationLoadAddressZeroPage, CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh +#define ZeroIndirect OperationLoadAddressZeroPage, CycleFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh #define IndexedIndirect CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh #define IndirectIndexedr CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh, CycleAddYToAddressLow, OperationCorrectAddressHigh #define IndirectIndexed CycleIncrementPCFetchAddressLowFromOperand, CycleIncrementOperandFetchAddressHigh, CycleAddYToAddressLowRead, OperationCorrectAddressHigh #define Read(...) CycleFetchOperandFromAddress, __VA_ARGS__ #define Write(...) __VA_ARGS__, CycleWriteOperandToAddress -#define ReadModifyWrite(...) CycleFetchOperandFromAddress, CycleWriteOperandToAddress, __VA_ARGS__, CycleWriteOperandToAddress +#define ReadModifyWrite(...) CycleFetchOperandFromAddress, (personality == P6502) ? CycleWriteOperandToAddress : CycleFetchOperandFromAddress, __VA_ARGS__, CycleWriteOperandToAddress #define AbsoluteRead(op) Program(Absolute, Read(op)) #define AbsoluteXRead(op) Program(AbsoluteXr, Read(op)) @@ -282,9 +282,9 @@ ProcessorStorage::ProcessorStorage(Personality personality) { Install(0x32, ZeroIndirectRead(OperationAND)); Install(0x52, ZeroIndirectRead(OperationEOR)); Install(0x72, ZeroIndirectRead(OperationADC)); - Install(0x92, ZeroIndirectRead(OperationSTA)); + Install(0x92, ZeroIndirectWrite(OperationSTA)); Install(0xb2, ZeroIndirectRead(OperationLDA)); - Install(0xd2, ZeroIndirectWrite(OperationCMP)); + Install(0xd2, ZeroIndirectRead(OperationCMP)); Install(0xd2, ZeroIndirectRead(OperationSBC)); } #undef Install diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index ec48d8d36..50d24727b 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -45,6 +45,7 @@ class ProcessorStorage { OperationMoveToNextProgram, OperationIncrementPC, CycleFetchOperandFromAddress, CycleWriteOperandToAddress, OperationCopyOperandFromA, OperationCopyOperandToA, CycleIncrementPCFetchAddressLowFromOperand, CycleAddXToOperandFetchAddressLow, CycleIncrementOperandFetchAddressHigh, OperationDecrementOperand, + CycleFetchAddressLowFromOperand, OperationIncrementOperand, OperationORA, OperationAND, OperationEOR, OperationINS, OperationADC, OperationSBC, OperationLDA, OperationLDX, OperationLDY, OperationLAX, OperationSTA, From aed4c0539ed505d34ad861cee06e73781ff54db9 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 21:17:02 -0400 Subject: [PATCH 13/18] Implements STZ. --- OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift | 4 ++++ Processors/6502/Implementation/6502Implementation.hpp | 1 + Processors/6502/Implementation/6502Storage.cpp | 6 ++++++ Processors/6502/Implementation/6502Storage.hpp | 3 ++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 6a614019c..17dfda582 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -87,6 +87,10 @@ class KlausDormannTests: XCTestCase { case 0x183a: return "STA (zp) acted as JAM" case 0x1849: return "LDA/STA (zp) left flags in incorrect state" + case 0x1983: return "STZ didn't store zero" + + case 0x1b03: return "BIT didn't set flags correctly" + case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" } diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index ca0a371c6..d9888d29b 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -201,6 +201,7 @@ if(number_of_cycles <= Cycles(0)) break; case OperationSTA: operand_ = a_; continue; case OperationSTX: operand_ = x_; continue; case OperationSTY: operand_ = y_; continue; + case OperationSTZ: operand_ = 0; continue; case OperationSAX: operand_ = a_ & x_; continue; case OperationSHA: operand_ = a_ & x_ & (address_.bytes.high+1); continue; case OperationSHX: operand_ = x_ & (address_.bytes.high+1); continue; diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 786394d45..49292b030 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -286,6 +286,12 @@ ProcessorStorage::ProcessorStorage(Personality personality) { Install(0xb2, ZeroIndirectRead(OperationLDA)); Install(0xd2, ZeroIndirectRead(OperationCMP)); Install(0xd2, ZeroIndirectRead(OperationSBC)); + + // Add STZ. + Install(0x9c, AbsoluteWrite(OperationSTZ)); + Install(0x9e, AbsoluteXWrite(OperationSTZ)); + Install(0x64, ZeroWrite(OperationSTZ)); + Install(0x74, ZeroXWrite(OperationSTZ)); } #undef Install } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index 50d24727b..cde267786 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -49,7 +49,8 @@ class ProcessorStorage { OperationIncrementOperand, OperationORA, OperationAND, OperationEOR, OperationINS, OperationADC, OperationSBC, OperationLDA, OperationLDX, OperationLDY, OperationLAX, OperationSTA, - OperationSTX, OperationSTY, OperationSAX, OperationSHA, + OperationSTX, OperationSTY, OperationSTZ, + OperationSAX, OperationSHA, OperationSHX, OperationSHY, OperationSHS, OperationCMP, OperationCPX, OperationCPY, OperationBIT, OperationASL, OperationASO, OperationROL, OperationRLA, OperationLSR, From 90094529a5fba36e207ce30963d70904a5280f21 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 22:04:45 -0400 Subject: [PATCH 14/18] Implements TSB and TRB, and adds the extra BIT instructions. --- .../Clock SignalTests/KlausDormannTests.swift | 4 ++++ .../6502/Implementation/6502Implementation.hpp | 16 +++++++++++++++- Processors/6502/Implementation/6502Storage.cpp | 11 +++++++++++ Processors/6502/Implementation/6502Storage.hpp | 4 +++- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 17dfda582..d2d4f5107 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -90,6 +90,10 @@ class KlausDormannTests: XCTestCase { case 0x1983: return "STZ didn't store zero" case 0x1b03: return "BIT didn't set flags correctly" + case 0x1c6c: return "BIT immediate didn't set flags correctly" + + case 0x1d88: return "TRB set Z flag incorrectly" + case 0x1e7c: return "RMB set flags incorrectly" case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index d9888d29b..b8a52f2e6 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -108,6 +108,9 @@ if(number_of_cycles <= Cycles(0)) break; break; case OperationDecodeOperation: + if(operation_ == 0x89) { + printf(""); + } scheduled_program_counter_ = operations_[operation_]; continue; @@ -231,13 +234,24 @@ if(number_of_cycles <= Cycles(0)) break; carry_flag_ = ((~temp16) >> 8)&1; } continue; -// MARK: - BIT +// MARK: - BIT, TSB, TRB case OperationBIT: zero_result_ = operand_ & a_; negative_result_ = operand_; overflow_flag_ = operand_&Flag::Overflow; continue; + case OperationBITNoNV: + zero_result_ = operand_ & a_; + continue; + case OperationTRB: + zero_result_ = operand_ & a_; + operand_ &= ~a_; + continue; + case OperationTSB: + zero_result_ = operand_ & a_; + operand_ |= a_; + continue; // MARK: - ADC/SBC (and INS) diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 49292b030..7ef8ae728 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -292,6 +292,17 @@ ProcessorStorage::ProcessorStorage(Personality personality) { Install(0x9e, AbsoluteXWrite(OperationSTZ)); Install(0x64, ZeroWrite(OperationSTZ)); Install(0x74, ZeroXWrite(OperationSTZ)); + + // Add the extra BITs. + Install(0x34, ZeroXRead(OperationBIT)); + Install(0x3c, AbsoluteXRead(OperationBIT)); + Install(0x89, Immediate(OperationBITNoNV)); + + // Add TRB and TSB. + Install(0x04, ZeroReadModifyWrite(OperationTSB)); + Install(0x0c, AbsoluteReadModifyWrite(OperationTSB)); + Install(0x14, ZeroReadModifyWrite(OperationTRB)); + Install(0x1c, AbsoluteReadModifyWrite(OperationTRB)); } #undef Install } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index cde267786..8e41934ea 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -52,11 +52,13 @@ class ProcessorStorage { OperationSTX, OperationSTY, OperationSTZ, OperationSAX, OperationSHA, OperationSHX, OperationSHY, OperationSHS, OperationCMP, - OperationCPX, OperationCPY, OperationBIT, OperationASL, + OperationCPX, OperationCPY, OperationBIT, OperationBITNoNV, + OperationASL, OperationASO, OperationROL, OperationRLA, OperationLSR, OperationLSE, OperationASR, OperationROR, OperationRRA, OperationCLC, OperationCLI, OperationCLV, OperationCLD, OperationSEC, OperationSEI, OperationSED, + OperationTRB, OperationTSB, OperationINC, OperationDEC, OperationINX, OperationDEX, OperationINY, OperationDEY, OperationINA, OperationDEA, From 5d6e479338dc272c144882b413d66ab4a73c68e6 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 22:13:51 -0400 Subject: [PATCH 15/18] Implements RMB and SMB, and fixes SBC (zero). --- .../Mac/Clock SignalTests/KlausDormannTests.swift | 2 ++ Processors/6502/Implementation/6502Implementation.hpp | 9 +++++++++ Processors/6502/Implementation/6502Storage.cpp | 10 +++++++++- Processors/6502/Implementation/6502Storage.hpp | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index d2d4f5107..b030bd6a5 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -95,6 +95,8 @@ class KlausDormannTests: XCTestCase { case 0x1d88: return "TRB set Z flag incorrectly" case 0x1e7c: return "RMB set flags incorrectly" + case 0x2245: return "CMP (zero) didn't work" + case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" } diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index b8a52f2e6..771b4b5d2 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -253,6 +253,15 @@ if(number_of_cycles <= Cycles(0)) break; operand_ |= a_; continue; +// MARK: - RMB and SMB + + case OperationRMB: + operand_ &= ~(1 << (operation_ >> 4)); + continue; + case OperationSMB: + operand_ |= 1 << ((operation_ >> 4)&7); + continue; + // MARK: - ADC/SBC (and INS) case OperationINS: diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 7ef8ae728..d8fae7c4f 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -285,7 +285,7 @@ ProcessorStorage::ProcessorStorage(Personality personality) { Install(0x92, ZeroIndirectWrite(OperationSTA)); Install(0xb2, ZeroIndirectRead(OperationLDA)); Install(0xd2, ZeroIndirectRead(OperationCMP)); - Install(0xd2, ZeroIndirectRead(OperationSBC)); + Install(0xf2, ZeroIndirectRead(OperationSBC)); // Add STZ. Install(0x9c, AbsoluteWrite(OperationSTZ)); @@ -303,6 +303,14 @@ ProcessorStorage::ProcessorStorage(Personality personality) { Install(0x0c, AbsoluteReadModifyWrite(OperationTSB)); Install(0x14, ZeroReadModifyWrite(OperationTRB)); Install(0x1c, AbsoluteReadModifyWrite(OperationTRB)); + + // Add RMB and SMB. + for(int c = 0x07; c <= 0x77; c += 0x10) { + Install(c, ZeroReadModifyWrite(OperationRMB)); + } + for(int c = 0x87; c <= 0xf7; c += 0x10) { + Install(c, ZeroReadModifyWrite(OperationSMB)); + } } #undef Install } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index 8e41934ea..85d4d1f3d 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -53,7 +53,7 @@ class ProcessorStorage { OperationSAX, OperationSHA, OperationSHX, OperationSHY, OperationSHS, OperationCMP, OperationCPX, OperationCPY, OperationBIT, OperationBITNoNV, - OperationASL, + OperationASL, OperationRMB, OperationSMB, OperationASO, OperationROL, OperationRLA, OperationLSR, OperationLSE, OperationASR, OperationROR, OperationRRA, OperationCLC, OperationCLI, OperationCLV, OperationCLD, From b63e0cff72f26129d395d440bdc652ffc8b4f4f5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 22:27:01 -0400 Subject: [PATCH 16/18] Improves has-completed test. --- OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index b030bd6a5..5e37d84d2 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -25,7 +25,12 @@ class KlausDormannTests: XCTestCase { let newPC = machine.value(for: .lastOperationAddress) if newPC == oldPC { - return newPC + machine.runForNumber(ofCycles: 7) + + let retestPC = machine.value(for: .lastOperationAddress) + if retestPC == oldPC { + return newPC + } } } } @@ -96,6 +101,7 @@ class KlausDormannTests: XCTestCase { case 0x1e7c: return "RMB set flags incorrectly" case 0x2245: return "CMP (zero) didn't work" + case 0x2506: return "Decimal ADC set flags incorrectly" case 0: return "Didn't find tests" default: return "Unknown error at \(String(format:"%04x", address))" From 261fb3d4f89f0724c769f844b21a866222eb8a70 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 22:42:35 -0400 Subject: [PATCH 17/18] Implements proper test for ADC/SBC 65C02 NZ, though not yet the proper timing. This gets Klaus Dorman's test to pass. --- OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift | 2 ++ Processors/6502/Implementation/6502Implementation.hpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift index 5e37d84d2..d04e74e1e 100644 --- a/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift +++ b/OSBindings/Mac/Clock SignalTests/KlausDormannTests.swift @@ -70,6 +70,8 @@ class KlausDormannTests: XCTestCase { func test65C02() { func errorForTrapAddress(_ address: UInt16) -> String? { switch address { + case 0x24f1: return nil // success! + case 0x0423: return "PHX: value of X not on stack page" case 0x0428: return "PHX: stack pointer not decremented" case 0x042d: return "PLY: didn't acquire value 0xaa from stack" diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 771b4b5d2..0010da63c 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -285,6 +285,10 @@ if(number_of_cycles <= Cycles(0)) break; carry_flag_ = (temp16 > 0xff) ? 0 : Flag::Carry; a_ = static_cast(temp16); + + if(personality_ != P6502) { + negative_result_ = zero_result_ = a_; + } continue; } else { operand_ = ~operand_; @@ -305,6 +309,10 @@ if(number_of_cycles <= Cycles(0)) break; carry_flag_ = (result >> 8) ? 1 : 0; a_ = static_cast(result); zero_result_ = static_cast(decimalResult); + + if(personality_ != P6502) { + negative_result_ = zero_result_ = a_; + } } else { const uint16_t result = static_cast(a_) + static_cast(operand_) + static_cast(carry_flag_); overflow_flag_ = (( (result^a_)&(result^operand_) )&0x80) >> 1; From 878c63dcd2751a2832025176802106d7fc33a3ef Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 10 Aug 2018 22:52:55 -0400 Subject: [PATCH 18/18] Ensures ADC and SBC decimal take an extra cycle on the 65C02. --- Processors/6502/Implementation/6502Implementation.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 0010da63c..045389754 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -288,6 +288,8 @@ if(number_of_cycles <= Cycles(0)) break; if(personality_ != P6502) { negative_result_ = zero_result_ = a_; + read_mem(operand_, address_.full); + break; } continue; } else { @@ -312,6 +314,8 @@ if(number_of_cycles <= Cycles(0)) break; if(personality_ != P6502) { negative_result_ = zero_result_ = a_; + read_mem(operand_, address_.full); + break; } } else { const uint16_t result = static_cast(a_) + static_cast(operand_) + static_cast(carry_flag_);