Refactor the 6502 implementation to be a lot more like the MC6809. Hopefully show bugs in the latter a little more easily.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2018-10-31 23:29:13 +00:00
parent b1af0710ba
commit 4dc0becb74
11 changed files with 638 additions and 694 deletions

View File

@ -3,10 +3,14 @@
#include <cstdint>
#include <string>
#include "mos6502.h"
#include "Symbols.h"
#include <EightBitCompilerDefinitions.h>
namespace EightBit {
class Bus;
class MOS6502;
class Symbols;
class Disassembly {
public:
Disassembly(Bus& bus, MOS6502& processor, const Symbols& symbols);

View File

@ -1,22 +1,21 @@
#pragma once
#include <array>
#include <map>
#include <cstdint>
#include <functional>
#include <map>
#include <EventArgs.h>
#include <Signal.h>
#include "Disassembly.h"
#include "Symbols.h"
#include "ProfileLineEventArgs.h"
#include "ProfileScopeEventArgs.h"
#include "mos6502.h"
namespace EightBit {
class Disassembly;
class MOS6502;
class Symbols;
class Profiler {
public:
std::array<uint64_t, 0x100> instructionCounts;

View File

@ -1,16 +1,17 @@
#pragma once
#include <cstdint>
#include <string>
#include <array>
#include <functional>
#include <cassert>
#include <utility>
#include <Bus.h>
#include <EightBitCompilerDefinitions.h>
#include <LittleEndianProcessor.h>
#include <Register.h>
#include <Signal.h>
namespace EightBit {
class Bus;
class MOS6502 : public LittleEndianProcessor {
public:
enum StatusBits {
@ -33,36 +34,73 @@ namespace EightBit {
virtual int step() final;
virtual void powerOn() final;
uint8_t& X() { return x; }
uint8_t& Y() { return y; }
uint8_t& A() { return a; }
uint8_t& S() { return s; }
uint8_t& P() { return p; }
auto& X() { return x; }
auto& Y() { return y; }
auto& A() { return a; }
auto& S() { return s; }
PinLevel& NMI() { return m_nmiLine; } // In
PinLevel& SO() { return m_soLine; } // In
auto& P() { return p; }
const auto& P() const { return p; }
auto& NMI() { return m_nmiLine; } // In
auto& SO() { return m_soLine; } // In
protected:
virtual void handleRESET() final;
virtual void handleIRQ() final;
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow = 0);
uint8_t SBC(uint8_t operand, uint8_t data);
uint8_t SUB_b(uint8_t operand, uint8_t data, int borrow);
uint8_t SUB_d(uint8_t operand, uint8_t data, int borrow);
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0);
uint8_t sbc(uint8_t operand, uint8_t data);
uint8_t sub_b(uint8_t operand, uint8_t data, int borrow);
uint8_t sub_d(uint8_t operand, uint8_t data, int borrow);
virtual uint8_t ADD(uint8_t operand, uint8_t data, int carry = 0);
uint8_t ADC(uint8_t operand, uint8_t data);
uint8_t ADD_b(uint8_t operand, uint8_t data, int carry);
uint8_t ADD_d(uint8_t operand, uint8_t data, int carry);
virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0);
uint8_t adc(uint8_t operand, uint8_t data);
uint8_t add_b(uint8_t operand, uint8_t data, int carry);
uint8_t add_d(uint8_t operand, uint8_t data, int carry);
private:
const uint8_t IRQvector = 0xfe; // IRQ vector
const uint8_t RSTvector = 0xfc; // RST vector
const uint8_t NMIvector = 0xfa; // NMI vector
void handleNMI();
void handleSO();
void handleHALT();
void interrupt(uint8_t vector);
virtual void push(uint8_t value) final;
virtual uint8_t pop() final;
// Addressing modes
register16_t Address_Absolute();
uint8_t Address_ZeroPage();
register16_t Address_ZeroPageIndirect();
register16_t Address_Indirect();
uint8_t Address_ZeroPageX();
uint8_t Address_ZeroPageY();
std::pair<register16_t, bool> Address_AbsoluteX();
std::pair<register16_t, bool> Address_AbsoluteY();
register16_t Address_IndexedIndirectX();
std::pair<register16_t, bool> Address_IndirectIndexedY();
register16_t Address_relative_byte();
// Addressing modes, read
uint8_t AM_Immediate();
uint8_t AM_Absolute();
uint8_t AM_ZeroPage();
uint8_t AM_AbsoluteX();
uint8_t AM_AbsoluteY();
uint8_t AM_ZeroPageX();
uint8_t AM_ZeroPageY();
uint8_t AM_IndexedIndirectX();
uint8_t AM_IndirectIndexedY();
// Flag adjustment
void adjustZero(const uint8_t datum) { clearFlag(P(), ZF, datum); }
void adjustNegative(const uint8_t datum) { setFlag(P(), NF, datum & NF); }
@ -71,261 +109,59 @@ namespace EightBit {
adjustNegative(datum);
}
virtual void push(uint8_t value) final;
virtual uint8_t pop() final;
// Flag checking
// Address resolution
auto interruptMasked() const { return P() & IF; }
auto decimal() const { return P() & DF; }
auto Address_Absolute() {
return fetchWord();
auto negative() const { return P() & NF; }
auto zero() const { return P() & ZF; }
auto overflow() const { return P() & VF; }
auto carry() const { return P() & CF; }
// Branching
auto branch(const register16_t destination, const int condition) {
const auto page = PC().high;
if (condition) {
jump(destination);
if (UNLIKELY(PC().high != page))
addCycle();
}
return !!condition;
}
auto Address_ZeroPage() {
return fetchByte();
}
auto Address_ZeroPageIndirect() {
return getWordPaged(0, Address_ZeroPage());
}
auto Address_Indirect() {
const auto address = Address_Absolute();
return getWordPaged(address.high, address.low);
}
uint8_t Address_ZeroPageX() {
return Address_ZeroPage() + X();
}
uint8_t Address_ZeroPageY() {
return Address_ZeroPage() + Y();
}
auto Address_AbsoluteX() {
auto address = Address_Absolute();
const auto page = address.high;
address += X();
return std::make_pair(address, address.high != page);
}
auto Address_AbsoluteY() {
auto address = Address_Absolute();
const auto page = address.high;
address += Y();
return std::make_pair(address, address.high != page);
}
auto Address_IndexedIndirectX() {
return getWordPaged(0, Address_ZeroPageX());
}
auto Address_IndirectIndexedY() {
auto address = Address_ZeroPageIndirect();
const auto page = address.high;
address += Y();
return std::make_pair(address, address.high != page);
}
// Addressing modes, read
auto AM_Immediate() {
return fetchByte();
}
auto AM_Absolute() {
return BUS().read(Address_Absolute());
}
auto AM_ZeroPage() {
return BUS().read(Address_ZeroPage());
}
auto AM_AbsoluteX() {
const auto [address, paged] = Address_AbsoluteX();
if (UNLIKELY(paged))
void branch(const int condition) {
if (branch(Address_relative_byte(), condition))
addCycle();
return BUS().read(address);
}
auto AM_AbsoluteY() {
const auto [address, paged] = Address_AbsoluteY();
if (UNLIKELY(paged))
addCycle();
return BUS().read(address);
// Miscellaneous
auto through(const uint8_t data) {
adjustNZ(data);
return data;
}
auto AM_ZeroPageX() {
return BUS().read(Address_ZeroPageX());
}
// Instruction implementations
auto AM_ZeroPageY() {
return BUS().read(Address_ZeroPageY());
}
auto AM_IndexedIndirectX() {
return BUS().read(Address_IndexedIndirectX());
}
auto AM_IndirectIndexedY() {
const auto [address, paged] = Address_IndirectIndexedY();
if (UNLIKELY(paged))
addCycle();
return BUS().read(address);
}
// Addressing modes, write
void AM_Absolute(const uint8_t value) {
BUS().write(Address_Absolute(), value);
}
void AM_ZeroPage(const uint8_t value) {
BUS().write(Address_ZeroPage(), value);
}
void AM_AbsoluteX(const uint8_t value) {
const auto [address, paged] = Address_AbsoluteX();
BUS().write(address, value);
}
void AM_AbsoluteY(const uint8_t value) {
const auto [address, paged] = Address_AbsoluteY();
BUS().write(address, value);
}
void AM_ZeroPageX(const uint8_t value) {
BUS().write(Address_ZeroPageX(), value);
}
void AM_ZeroPageY(const uint8_t value) {
BUS().write(Address_ZeroPageY(), value);
}
void AM_IndexedIndirectX(const uint8_t value) {
BUS().write(Address_IndexedIndirectX(), value);
}
void AM_IndirectIndexedY(const uint8_t value) {
const auto [address, paged] = Address_IndirectIndexedY();
BUS().write(address, value);
}
// Operations
void DCP(uint8_t value) {
BUS().write(--value);
CMP(A(), value);
}
void ISB(uint8_t value) {
BUS().write(++value);
A() = SBC(A(), value);
}
void SLO(const uint8_t value) {
const auto result = ASL(value);
BUS().write(result);
ORA(result);
}
void SRE(const uint8_t value) {
const auto result = LSR(value);
BUS().write(result);
EORA(result);
}
void RLA(const uint8_t value) {
const auto result = ROL(value);
BUS().write(result);
ANDA(result);
}
void RRA(const uint8_t value) {
const auto result = ROR(value);
BUS().write(result);
A() = ADC(A(), result);
}
void LAX(const uint8_t value) {
adjustNZ(X() = A() = value);
}
void AAC(const uint8_t value) {
ANDA(value);
setFlag(P(), CF, A() & Bit7);
}
void ASR(const uint8_t value) {
A() = LSR(A() & value);
}
void ARR(const uint8_t value) {
}
void ATX(const uint8_t value) {
ANDA(value);
X() = A();
}
void AXS(const uint8_t value) {
}
//
auto DEC(uint8_t value) {
const auto result = --value;
adjustNZ(result);
return result;
}
auto INC(uint8_t value) {
const auto result = ++value;
adjustNZ(result);
return result;
}
void ORA(const uint8_t value) {
adjustNZ(A() |= value);
}
void ANDA(const uint8_t value) {
adjustNZ(A() &= value);
}
void EORA(const uint8_t value) {
adjustNZ(A() ^= value);
}
uint8_t ROR(uint8_t value);
uint8_t LSR(uint8_t value);
void BIT(uint8_t data);
uint8_t ROL(uint8_t value);
uint8_t ASL(uint8_t value);
void CMP(uint8_t first, uint8_t second);
void Branch(int8_t displacement);
void Branch(bool flag);
void PHP();
void PLP();
void JSR_abs();
void RTI();
void RTS();
void JMP_abs();
void JMP_ind();
void BRK();
// All interrupt vectors are on the 0xFF page
const uint8_t IRQvector = 0xfe;
const uint8_t RSTvector = 0xfc;
const uint8_t NMIvector = 0xfa;
uint8_t andr(uint8_t operand, uint8_t data);
uint8_t asl(uint8_t value);
void bit(uint8_t operand, uint8_t data);
void brk();
void cmp(uint8_t first, uint8_t second);
uint8_t dec(uint8_t value);
uint8_t eorr(uint8_t operand, uint8_t data);
uint8_t inc(uint8_t value);
void jsr(register16_t destination);
uint8_t lsr(uint8_t value);
uint8_t orr(uint8_t operand, uint8_t data);
void php();
void plp();
uint8_t rol(uint8_t operand);
uint8_t ror(uint8_t operand);
void rti();
void rts();
uint8_t x = 0; // index register X
uint8_t y = 0; // index register Y

View File

@ -1,6 +1,9 @@
#include "stdafx.h"
#include "Disassembly.h"
#include "mos6502.h"
#include "Symbols.h"
#include <sstream>
#include <iomanip>
#include <functional>

View File

@ -1,6 +1,9 @@
#include "stdafx.h"
#include "Profiler.h"
#include "Disassembly.h"
#include "Symbols.h"
EightBit::Profiler::Profiler(MOS6502& targetProcessor, Disassembly& disassemblerTarget, Symbols& symbolsTarget)
: processor(targetProcessor),
disassembler(disassemblerTarget),

View File

@ -6,7 +6,7 @@ EightBit::MOS6502::MOS6502(Bus& bus)
void EightBit::MOS6502::powerOn() {
Processor::powerOn();
LittleEndianProcessor::powerOn();
X() = Bit7;
Y() = 0;
@ -18,13 +18,41 @@ void EightBit::MOS6502::powerOn() {
raise(SO());
}
int EightBit::MOS6502::step() {
resetCycles();
ExecutingInstruction.fire(*this);
if (LIKELY(powered())) {
if (UNLIKELY(lowered(SO())))
handleSO();
if (UNLIKELY(lowered(HALT())))
handleHALT();
else if (UNLIKELY(lowered(RESET())))
handleRESET();
else if (UNLIKELY(lowered(NMI())))
handleNMI();
else if (UNLIKELY(lowered(IRQ()) && !interruptMasked()))
handleIRQ();
else
execute(fetchByte());
}
ExecutedInstruction.fire(*this);
return cycles();
}
// Interrupt (etc.) handlers
void EightBit::MOS6502::handleSO() {
raise(SO());
P() |= VF;
}
void EightBit::MOS6502::handleHALT() {
execute(0xea); // NOP
addCycles(2);
}
void EightBit::MOS6502::handleRESET() {
Processor::handleRESET();
LittleEndianProcessor::handleRESET();
jump(getWordPaged(0xff, RSTvector));
addCycles(4); // ?? TBC
}
@ -37,322 +65,296 @@ void EightBit::MOS6502::handleNMI() {
}
void EightBit::MOS6502::handleIRQ() {
Processor::handleIRQ();
LittleEndianProcessor::handleIRQ();
interrupt(IRQvector);
addCycles(4); // ?? TBC
}
void EightBit::MOS6502::handleHALT() {
execute(0xea); // NOP
addCycles(2);
}
int EightBit::MOS6502::step() {
resetCycles();
if (LIKELY(powered())) {
ExecutingInstruction.fire(*this);
if (UNLIKELY(lowered(SO()))) {
handleSO();
}
if (UNLIKELY(lowered(RESET()))) {
handleRESET();
} else if (UNLIKELY(lowered(NMI()))) {
handleNMI();
} else if (UNLIKELY(lowered(IRQ()))) {
handleIRQ();
} else if (UNLIKELY(lowered(HALT()))) {
handleHALT();
} else {
execute(fetchByte());
}
ExecutedInstruction.fire(*this);
}
return cycles();
}
void EightBit::MOS6502::interrupt(uint8_t vector) {
raise(HALT());
pushWord(PC());
push(P());
setFlag(P(), IF);
setFlag(P(), IF); // Disable IRQ
jump(getWordPaged(0xff, vector));
}
int EightBit::MOS6502::execute(uint8_t cell) {
//
switch (cell) {
int EightBit::MOS6502::execute(const uint8_t opcode) {
case 0x00: addCycles(7); BRK(); break;
case 0x01: addCycles(6); ORA(AM_IndexedIndirectX()); break;
case 0x02: addCycles(0); break;
case 0x03: addCycles(8); SLO(AM_IndexedIndirectX()); break;
case 0x04: addCycles(3); AM_ZeroPage(); break;
case 0x05: addCycles(3); ORA(AM_ZeroPage()); break;
case 0x06: addCycles(5); BUS().write(ASL(AM_ZeroPage())); break;
case 0x07: addCycles(5); SLO(AM_ZeroPage()); break;
case 0x08: addCycles(3); PHP(); break;
case 0x09: addCycles(2); ORA(AM_Immediate()); break;
case 0x0a: addCycles(2); A() = ASL(A()); break;
case 0x0b: addCycles(2); AAC(AM_Immediate()); break;
case 0x0c: addCycles(4); AM_Absolute(); break;
case 0x0d: addCycles(4); ORA(AM_Absolute()); break;
case 0x0e: addCycles(6); BUS().write(ASL(AM_Absolute())); break;
case 0x0f: addCycles(6); SLO(AM_Absolute()); break;
switch (opcode) {
case 0x10: addCycles(2); Branch(!(P() & NF)); break;
case 0x11: addCycles(5); ORA(AM_IndirectIndexedY()); break;
case 0x12: addCycles(0); break;
case 0x13: addCycles(7); SLO(AM_IndirectIndexedY()); break;
case 0x14: addCycles(4); AM_ZeroPageX(); break;
case 0x15: addCycles(4); ORA(AM_ZeroPageX()); break;
case 0x16: addCycles(6); BUS().write(ASL(AM_ZeroPageX())); break;
case 0x17: addCycles(6); SLO(AM_ZeroPageX()); break;
case 0x18: addCycles(2); clearFlag(P(), CF); break;
case 0x19: addCycles(4); ORA(AM_AbsoluteY()); break;
case 0x1a: addCycles(2); break;
case 0x1b: addCycles(6); SLO(AM_AbsoluteY()); break;
case 0x1c: addCycles(4); AM_AbsoluteX(); break;
case 0x1d: addCycles(4); ORA(AM_AbsoluteX()); break;
case 0x1e: addCycles(7); BUS().write(ASL(AM_AbsoluteX())); break;
case 0x1f: addCycles(6); SLO(AM_AbsoluteX()); break;
case 0x00: addCycles(7); brk(); break; // BRK
case 0x01: addCycles(6); A() = orr(A(), AM_IndexedIndirectX()); break; // ORA (indexed indirect X)
case 0x02: break;
case 0x03: break;
case 0x04: break;
case 0x05: addCycles(3); A() = orr(A(), AM_ZeroPage()); break; // ORA (zero page)
case 0x06: addCycles(5); BUS().write(asl(AM_ZeroPage())); break; // ASL (zero page)
case 0x07: break;
case 0x08: addCycles(3); php(); break; // PHP
case 0x09: addCycles(2); A() = orr(A(), AM_Immediate()); break; // ORA (immediate)
case 0x0a: addCycles(2); A() = asl(A()); break; // ASL A
case 0x0b: break;
case 0x0c: break;
case 0x0d: addCycles(4); A() = orr(A(), AM_Absolute()); break; // ORA (absolute)
case 0x0e: addCycles(6); BUS().write(asl(AM_Absolute())); break; // ASL (absolute)
case 0x0f: break;
case 0x20: addCycles(6); JSR_abs(); break;
case 0x21: addCycles(6); ANDA(AM_IndexedIndirectX()); break;
case 0x22: addCycles(0); break;
case 0x23: addCycles(8); RLA(AM_IndexedIndirectX()); break;
case 0x24: addCycles(3); BIT(AM_ZeroPage()); break;
case 0x25: addCycles(3); ANDA(AM_ZeroPage()); break;
case 0x26: addCycles(5); BUS().write(ROL(AM_ZeroPage())); break;
case 0x27: addCycles(5); RLA(AM_ZeroPage()); break;
case 0x28: addCycles(4); PLP(); break;
case 0x29: addCycles(2); ANDA(AM_Immediate()); break;
case 0x2a: addCycles(2); A() = ROL(A()); break;
case 0x2b: addCycles(2); AAC(AM_Immediate()); break;
case 0x2c: addCycles(4); BIT(AM_Absolute()); break;
case 0x2d: addCycles(4); ANDA(AM_Absolute()); break;
case 0x2e: addCycles(6); BUS().write(ROL(AM_Absolute())); break;
case 0x2f: addCycles(6); RLA(AM_Absolute()); break;
case 0x10: addCycles(2); branch(!negative()); break; // BPL (relative)
case 0x11: addCycles(5); A() = orr(A(), AM_IndirectIndexedY()); break; // ORA (indirect indexed Y)
case 0x12: break;
case 0x13: break;
case 0x14: break;
case 0x15: addCycles(4); A() = orr(A(), AM_ZeroPageX()); break; // ORA (zero page, X)
case 0x16: addCycles(6); BUS().write(asl(AM_ZeroPageX())); break; // ASL (zero page, X)
case 0x17: break;
case 0x18: addCycles(2); clearFlag(P(), CF); break; // CLC
case 0x19: addCycles(4); A() = orr(A(), AM_AbsoluteY()); break; // ORA (absolute, Y)
case 0x1a: break;
case 0x1b: break;
case 0x1c: break;
case 0x1d: addCycles(4); A() = orr(A(), AM_AbsoluteX()); break; // ORA (absolute, X)
case 0x1e: addCycles(7); BUS().write(asl(AM_AbsoluteX())); break; // ASL (absolute, X)
case 0x1f: break;
case 0x30: addCycles(2); Branch(!!(P() & NF)); break;
case 0x31: addCycles(5); ANDA(AM_IndirectIndexedY()); break;
case 0x32: addCycles(0); break;
case 0x33: addCycles(7); RLA(AM_IndirectIndexedY()); break;
case 0x34: addCycles(4); AM_ZeroPageX(); break;
case 0x35: addCycles(4); ANDA(AM_ZeroPageX()); break;
case 0x36: addCycles(6); BUS().write(ROL(AM_ZeroPageX())); break;
case 0x37: addCycles(6); RLA(AM_ZeroPageX()); break;
case 0x38: addCycles(2); setFlag(P(), CF); break;
case 0x39: addCycles(4); ANDA(AM_AbsoluteY()); break;
case 0x3a: addCycles(2); break;
case 0x3b: addCycles(6); RLA(AM_AbsoluteY()); break;
case 0x3c: addCycles(4); AM_AbsoluteX(); break;
case 0x3d: addCycles(4); ANDA(AM_AbsoluteX()); break;
case 0x3e: addCycles(7); BUS().write(ROL(AM_AbsoluteX())); break;
case 0x3f: addCycles(6); RLA(AM_AbsoluteX()); break;
case 0x20: addCycles(6); jsr(Address_Absolute()); break; // JSR (absolute)
case 0x21: addCycles(6); A() = andr(A(), AM_IndexedIndirectX()); break; // AND (indexed indirect X)
case 0x22: break;
case 0x23: break;
case 0x24: addCycles(3); bit(A(), AM_ZeroPage()); break; // BIT (zero page)
case 0x25: addCycles(3); A() = andr(A(), AM_ZeroPage()); break; // AND (zero page)
case 0x26: addCycles(5); BUS().write(rol(AM_ZeroPage())); break; // ROL (zero page)
case 0x27: break;
case 0x28: addCycles(4); plp(); break; // PLP
case 0x29: addCycles(2); A() = andr(A(), AM_Immediate()); break; // AND (immediate)
case 0x2a: addCycles(2); A() = rol(A()); break; // ROL A
case 0x2b: break;
case 0x2c: addCycles(4); bit(A(), AM_Absolute()); break; // BIT (absolute)
case 0x2d: addCycles(4); A() = andr(A(), AM_Absolute()); break; // AND (absolute)
case 0x2e: addCycles(6); BUS().write(rol(AM_Absolute())); break; // ROL (absolute)
case 0x2f: break;
case 0x40: addCycles(6); RTI(); break;
case 0x41: addCycles(6); EORA(AM_IndexedIndirectX()); break;
case 0x42: addCycles(0); break;
case 0x43: addCycles(8); SRE(AM_IndexedIndirectX()); break;
case 0x44: addCycles(3); AM_ZeroPage(); break;
case 0x45: addCycles(3); EORA(AM_ZeroPage()); break;
case 0x46: addCycles(5); BUS().write(LSR(AM_ZeroPage())); break;
case 0x47: addCycles(5); SRE(AM_ZeroPage()); break;
case 0x48: addCycles(3); push(A()); break;
case 0x49: addCycles(2); EORA(AM_Immediate()); break;
case 0x4a: addCycles(2); A() = LSR(A()); break;
case 0x4b: addCycles(2); ASR(AM_Immediate()); break;
case 0x4c: addCycles(3); JMP_abs(); break;
case 0x4d: addCycles(4); EORA(AM_Absolute()); break;
case 0x4e: addCycles(6); BUS().write(LSR(AM_Absolute())); break;
case 0x4f: addCycles(6); SRE(AM_Absolute()); break;
case 0x30: addCycles(2); branch(negative()); break; // BMI
case 0x31: addCycles(5); A() = andr(A(), AM_IndirectIndexedY()); break; // AND (indirect indexed Y)
case 0x32: break;
case 0x33: break;
case 0x34: break;
case 0x35: addCycles(4); A() = andr(A(), AM_ZeroPageX()); break; // AND (zero page, X)
case 0x36: addCycles(6); BUS().write(rol(AM_ZeroPageX())); break; // ROL (zero page, X)
case 0x37: break;
case 0x38: addCycles(2); setFlag(P(), CF); break; // SEC
case 0x39: addCycles(4); A() = andr(A(), AM_AbsoluteY()); break; // AND (absolute, Y)
case 0x3a: break;
case 0x3b: break;
case 0x3c: break;
case 0x3d: addCycles(4); A() = andr(A(), AM_AbsoluteX()); break; // AND (absolute, X)
case 0x3e: addCycles(7); BUS().write(rol(AM_AbsoluteX())); break; // ROL (absolute, X)
case 0x3f: break;
case 0x50: addCycles(2); Branch(!(P() & VF)); break;
case 0x51: addCycles(5); EORA(AM_IndirectIndexedY()); break;
case 0x52: addCycles(0); break;
case 0x53: addCycles(7); SRE(AM_IndirectIndexedY()); break;
case 0x54: addCycles(4); AM_ZeroPage(); break;
case 0x55: addCycles(4); EORA(AM_ZeroPageX()); break;
case 0x56: addCycles(6); BUS().write(LSR(AM_ZeroPageX())); break;
case 0x57: addCycles(6); SRE(AM_ZeroPageX()); break;
case 0x58: addCycles(2); clearFlag(P(), IF); break;
case 0x59: addCycles(4); EORA(AM_AbsoluteY()); break;
case 0x5a: addCycles(2); break;
case 0x5b: addCycles(6); SRE(AM_AbsoluteY()); break;
case 0x5c: addCycles(4); AM_AbsoluteX(); break;
case 0x5d: addCycles(4); EORA(AM_AbsoluteX()); break;
case 0x5e: addCycles(7); BUS().write(LSR(AM_AbsoluteX())); break;
case 0x5f: addCycles(6); SRE(AM_AbsoluteX()); break;
case 0x40: addCycles(6); rti(); break; // RTI
case 0x41: addCycles(6); A() = eorr(A(), AM_IndexedIndirectX()); break; // EOR (indexed indirect X)
case 0x42: break;
case 0x43: break;
case 0x44: break;
case 0x45: addCycles(3); A() = eorr(A(), AM_ZeroPage()); break; // EOR (zero page)
case 0x46: addCycles(5); BUS().write(lsr(AM_ZeroPage())); break; // LSR (zero page)
case 0x47: break;
case 0x48: addCycles(3); push(A()); break; // PHA
case 0x49: addCycles(2); A() = eorr(A(), AM_Immediate()); break; // EOR (immediate)
case 0x4a: addCycles(2); A() = lsr(A()); break; // LSR A
case 0x4b: break;
case 0x4c: addCycles(3); jump(Address_Absolute()); break; // JMP (absolute)
case 0x4d: addCycles(4); A() = eorr(A(), AM_Absolute()); break; // EOR (absolute)
case 0x4e: addCycles(6); BUS().write(lsr(AM_Absolute())); break; // LSR (absolute)
case 0x4f: break;
case 0x60: addCycles(6); RTS(); break;
case 0x61: addCycles(6); A() = ADC(A(), AM_IndexedIndirectX()); break;
case 0x62: addCycles(0); break;
case 0x63: addCycles(8); RRA(AM_IndexedIndirectX()); break;
case 0x64: addCycles(3); AM_ZeroPage(); break;
case 0x65: addCycles(3); A() = ADC(A(), AM_ZeroPage()); break;
case 0x66: addCycles(5); BUS().write(ROR(AM_ZeroPage())); break;
case 0x67: addCycles(5); RRA(AM_ZeroPage()); break;
case 0x68: addCycles(4); adjustNZ(A() = pop()); break;
case 0x69: addCycles(2); A() = ADC(A(), AM_Immediate()); break;
case 0x6a: addCycles(2); A() = ROR(A()); break;
case 0x6b: addCycles(2); ARR(AM_Immediate()); break;
case 0x6c: addCycles(5); JMP_ind(); break;
case 0x6d: addCycles(4); A() = ADC(A(), AM_Absolute()); break;
case 0x6e: addCycles(6); BUS().write(ROR(AM_Absolute())); break;
case 0x6f: addCycles(6); RRA(AM_Absolute()); break;
case 0x50: addCycles(2); branch(!overflow()); break; // BVC (relative)
case 0x51: addCycles(5); A() = eorr(A(), AM_IndirectIndexedY()); break; // EOR (indirect indexed Y)
case 0x52: break;
case 0x53: break;
case 0x54: break;
case 0x55: addCycles(4); A() = eorr(A(), AM_ZeroPageX()); break; // EOR (zero page, X)
case 0x56: addCycles(6); BUS().write(lsr(AM_ZeroPageX())); break; // LSR (zero page, X)
case 0x57: break;
case 0x58: addCycles(2); clearFlag(P(), IF); break; // CLI
case 0x59: addCycles(4); A() = eorr(A(), AM_AbsoluteY()); break; // EOR (absolute, Y)
case 0x5a: break;
case 0x5b: break;
case 0x5c: break;
case 0x5d: addCycles(4); A() = eorr(A(), AM_AbsoluteX()); break; // EOR (absolute, X)
case 0x5e: addCycles(7); BUS().write(lsr(AM_AbsoluteX())); break; // LSR (absolute, X)
case 0x5f: break;
case 0x70: addCycles(2); Branch(!!(P() & VF)); break;
case 0x71: addCycles(5); A() = ADC(A(), AM_IndirectIndexedY()); break;
case 0x72: addCycles(0); break;
case 0x73: addCycles(7); RRA(AM_IndirectIndexedY()); break;
case 0x74: addCycles(4); AM_ZeroPageX(); break;
case 0x75: addCycles(4); A() = ADC(A(), AM_ZeroPageX()); break;
case 0x76: addCycles(6); BUS().write(ROR(AM_ZeroPageX())); break;
case 0x77: addCycles(6); RRA(AM_ZeroPageX()); break;
case 0x78: addCycles(2); setFlag(P(), IF); break;
case 0x79: addCycles(4); A() = ADC(A(), AM_AbsoluteY()); break;
case 0x7a: addCycles(2); break;
case 0x7b: addCycles(6); RRA(AM_AbsoluteY()); break;
case 0x7c: addCycles(4); AM_AbsoluteX(); break;
case 0x7d: addCycles(4); A() = ADC(A(), AM_AbsoluteX()); break;
case 0x7e: addCycles(7); BUS().write(ROR(AM_AbsoluteX())); break;
case 0x7f: addCycles(6); RRA(AM_AbsoluteX()); break;
case 0x60: addCycles(6); rts(); break; // RTS
case 0x61: addCycles(6); A() = adc(A(), AM_IndexedIndirectX()); break; // ADC (indexed indirect X)
case 0x62: break;
case 0x63: break;
case 0x64: break;
case 0x65: addCycles(3); A() = adc(A(), AM_ZeroPage()); break; // ADC (zero page)
case 0x66: addCycles(5); BUS().write(ror(AM_ZeroPage())); break; // ROR (zero page)
case 0x67: break;
case 0x68: addCycles(4); A() = through(pop()); break; // PLA
case 0x69: addCycles(2); A() = adc(A(), AM_Immediate()); break; // ADC (immediate)
case 0x6a: addCycles(2); A() = ror(A()); break; // ROR A
case 0x6b: break;
case 0x6c: addCycles(5); jump(Address_Indirect()); break; // JMP (indirect)
case 0x6d: addCycles(4); A() = adc(A(), AM_Absolute()); break; // ADC (absolute)
case 0x6e: addCycles(6); BUS().write(ror(AM_Absolute())); break; // ROR (absolute)
case 0x6f: break;
case 0x80: addCycles(2); AM_Immediate(); break;
case 0x81: addCycles(6); AM_IndexedIndirectX(A()); break;
case 0x82: addCycles(2); AM_Immediate(); break;
case 0x83: addCycles(6); AM_IndexedIndirectX(A() & X()); break;
case 0x84: addCycles(3); AM_ZeroPage(Y()); break;
case 0x85: addCycles(3); AM_ZeroPage(A()); break;
case 0x86: addCycles(3); AM_ZeroPage(X()); break;
case 0x87: addCycles(3); AM_ZeroPage(A() & X()); break;
case 0x88: addCycles(2); adjustNZ(--Y()); break;
case 0x89: addCycles(2); AM_Immediate(); break;
case 0x8a: addCycles(2); adjustNZ(A() = X()); break;
case 0x8b: addCycles(0); break;
case 0x8c: addCycles(4); AM_Absolute(Y()); break;
case 0x8d: addCycles(4); AM_Absolute(A()); break;
case 0x8e: addCycles(4); AM_Absolute(X()); break;
case 0x8f: addCycles(4); AM_Absolute(A() & X()); break;
case 0x70: addCycles(2); branch(overflow()); break; // BVS (relative)
case 0x71: addCycles(5); A() = adc(A(), AM_IndirectIndexedY()); break; // ADC (indirect indexed Y)
case 0x72: break;
case 0x73: break;
case 0x74: break;
case 0x75: addCycles(4); A() = adc(A(), AM_ZeroPageX()); break; // ADC (zero page, X)
case 0x76: addCycles(6); BUS().write(ror(AM_ZeroPageX())); break; // ROR (zero page, X)
case 0x77: break;
case 0x78: addCycles(2); setFlag(P(), IF); break; // SEI
case 0x79: addCycles(4); A() = adc(A(), AM_AbsoluteY()); break; // ADC (absolute, Y)
case 0x7a: break;
case 0x7b: break;
case 0x7c: break;
case 0x7d: addCycles(4); A() = adc(A(), AM_AbsoluteX()); break; // ADC (absolute, X)
case 0x7e: addCycles(7); BUS().write(ror(AM_AbsoluteX())); break; // ROR (absolute, X)
case 0x7f: break;
case 0x90: addCycles(2); Branch(!(P() & CF)); break;
case 0x91: addCycles(6); AM_IndirectIndexedY(A()); break;
case 0x92: addCycles(0); break;
case 0x93: addCycles(0); break;
case 0x94: addCycles(4); AM_ZeroPageX(Y()); break;
case 0x95: addCycles(4); AM_ZeroPageX(A()); break;
case 0x96: addCycles(4); AM_ZeroPageY(X()); break;
case 0x97: addCycles(4); AM_ZeroPageY(A() & X()); break;
case 0x98: addCycles(2); adjustNZ(A() = Y()); break;
case 0x99: addCycles(5); AM_AbsoluteY(A()); break;
case 0x9a: addCycles(2); S() = X(); break;
case 0x9b: addCycles(0); break;
case 0x9c: addCycles(0); break;
case 0x9d: addCycles(5); AM_AbsoluteX(A()); break;
case 0x9e: addCycles(0); break;
case 0x9f: addCycles(0); break;
case 0x80: break;
case 0x81: addCycles(6); BUS().write(Address_IndexedIndirectX(), A()); break; // STA (indexed indirect X)
case 0x82: break;
case 0x83: break;
case 0x84: addCycles(3); BUS().write(Address_ZeroPage(), Y()); break; // STY (zero page)
case 0x85: addCycles(3); BUS().write(Address_ZeroPage(), A()); break; // STA (zero page)
case 0x86: addCycles(3); BUS().write(Address_ZeroPage(), X()); break; // STX (zero page)
case 0x87: break;
case 0x88: addCycles(2); Y() = dec(Y()); break; // DEY
case 0x89: break;
case 0x8a: addCycles(2); A() = through(X()); break; // TXA
case 0x8b: break;
case 0x8c: addCycles(4); BUS().write(Address_Absolute(), Y()); break; // STY (absolute)
case 0x8d: addCycles(4); BUS().write(Address_Absolute(), A()); break; // STA (absolute)
case 0x8e: addCycles(4); BUS().write(Address_Absolute(), X()); break; // STX (absolute)
case 0x8f: break;
case 0xa0: addCycles(2); adjustNZ(Y() = AM_Immediate()); break;
case 0xa1: addCycles(6); adjustNZ(A() = AM_IndexedIndirectX()); break;
case 0xa2: addCycles(2); adjustNZ(X() = AM_Immediate()); break;
case 0xa3: addCycles(6); LAX(AM_IndexedIndirectX()); break;
case 0xa4: addCycles(3); adjustNZ(Y() = AM_ZeroPage()); break;
case 0xa5: addCycles(3); adjustNZ(A() = AM_ZeroPage()); break;
case 0xa6: addCycles(3); adjustNZ(X() = AM_ZeroPage()); break;
case 0xa7: addCycles(3); LAX(AM_ZeroPage()); break;
case 0xa8: addCycles(2); adjustNZ(Y() = A()); break;
case 0xa9: addCycles(2); adjustNZ(A() = AM_Immediate()); break;
case 0xaa: addCycles(2); adjustNZ(X() = A()); break;
case 0xab: addCycles(2); ATX(AM_Immediate()); break;
case 0xac: addCycles(4); adjustNZ(Y() = AM_Absolute()); break;
case 0xad: addCycles(4); adjustNZ(A() = AM_Absolute()); break;
case 0xae: addCycles(4); adjustNZ(X() = AM_Absolute()); break;
case 0xaf: addCycles(4); LAX(AM_Absolute()); break;
case 0x90: addCycles(2); branch(!carry()); break; // BCC
case 0x91: addCycles(6); BUS().write(Address_IndirectIndexedY().first, A()); break; // STA (indirect indexed Y)
case 0x92: break;
case 0x93: break;
case 0x94: addCycles(4); BUS().write(Address_ZeroPageX(), Y()); break; // STY (zero page, X)
case 0x95: addCycles(4); BUS().write(Address_ZeroPageX(), A()); break; // STA (zero page, X)
case 0x96: addCycles(4); BUS().write(Address_ZeroPageY(), X()); break; // STX (zero page, X)
case 0x97: break;
case 0x98: addCycles(2); A() = through(Y()); break; // TYA
case 0x99: addCycles(5); BUS().write(Address_AbsoluteY().first, A()); break; // STA (absolute, Y)
case 0x9a: addCycles(2); S() = X(); break; // TXS
case 0x9b: break;
case 0x9c: break;
case 0x9d: addCycles(5); BUS().write(Address_AbsoluteX().first, A()); break; // STA (absolute, X)
case 0x9e: break;
case 0x9f: break;
case 0xb0: addCycles(2); Branch(!!(P() & CF)); break;
case 0xb1: addCycles(5); adjustNZ(A() = AM_IndirectIndexedY()); break;
case 0xb2: addCycles(0); break;
case 0xb3: addCycles(5); LAX(AM_IndirectIndexedY()); break;
case 0xb4: addCycles(4); adjustNZ(Y() = AM_ZeroPageX()); break;
case 0xb5: addCycles(4); adjustNZ(A() = AM_ZeroPageX()); break;
case 0xb6: addCycles(4); adjustNZ(X() = AM_ZeroPageY()); break;
case 0xb7: addCycles(4); LAX(AM_ZeroPageY()); break;
case 0xb8: addCycles(2); clearFlag(P(), VF); break;
case 0xb9: addCycles(4); adjustNZ(A() = AM_AbsoluteY()); break;
case 0xba: addCycles(2); adjustNZ(X() = S()); break;
case 0xbb: addCycles(0); break;
case 0xbc: addCycles(4); adjustNZ(Y() = AM_AbsoluteX()); break;
case 0xbd: addCycles(4); adjustNZ(A() = AM_AbsoluteX()); break;
case 0xbe: addCycles(4); adjustNZ(X() = AM_AbsoluteY()); break;
case 0xbf: addCycles(4); LAX(AM_AbsoluteY()); break;
case 0xa0: addCycles(2); Y() = through(AM_Immediate()); break; // LDY (immediate)
case 0xa1: addCycles(6); A() = through(AM_IndexedIndirectX()); break; // LDA (indexed indirect X)
case 0xa2: addCycles(2); X() = through(AM_Immediate()); break; // LDX (immediate)
case 0xa3: break;
case 0xa4: addCycles(3); Y() = through(AM_ZeroPage()); break; // LDY (zero page)
case 0xa5: addCycles(3); A() = through(AM_ZeroPage()); break; // LDA (zero page)
case 0xa6: addCycles(3); X() = through(AM_ZeroPage()); break; // LDX (zero page)
case 0xa7: break;
case 0xa8: addCycles(2); Y() = through(A()); break; // TAY
case 0xa9: addCycles(2); A() = through(AM_Immediate()); break; // LDA (immediate)
case 0xaa: addCycles(2); X() = through(A()); break; // TAX
case 0xab: break;
case 0xac: addCycles(4); Y() = through(AM_Absolute()); break; // LDY (absolute)
case 0xad: addCycles(4); A() = through(AM_Absolute()); break; // LDA (absolute)
case 0xae: addCycles(4); X() = through(AM_Absolute()); break; // LDX (absolute)
case 0xaf: break;
case 0xc0: addCycles(2); CMP(Y(), AM_Immediate()); break;
case 0xc1: addCycles(6); CMP(A(), AM_IndexedIndirectX()); break;
case 0xc2: addCycles(2); AM_Immediate(); break;
case 0xc3: addCycles(8); DCP(AM_IndexedIndirectX()); break;
case 0xc4: addCycles(3); CMP(Y(), AM_ZeroPage()); break;
case 0xc5: addCycles(3); CMP(A(), AM_ZeroPage()); break;
case 0xc6: addCycles(5); BUS().write(DEC(AM_ZeroPage())); break;
case 0xc7: addCycles(5); DCP(AM_ZeroPage()); break;
case 0xc8: addCycles(2); adjustNZ(++Y()); break;
case 0xc9: addCycles(2); CMP(A(), AM_Immediate()); break;
case 0xca: addCycles(2); adjustNZ(--X()); break;
case 0xcb: addCycles(2); AXS(AM_Immediate()); break;
case 0xcc: addCycles(4); CMP(Y(), AM_Absolute()); break;
case 0xcd: addCycles(4); CMP(A(), AM_Absolute()); break;
case 0xce: addCycles(6); BUS().write(DEC(AM_Absolute())); break;
case 0xcf: addCycles(6); DCP(AM_Absolute()); break;
case 0xb0: addCycles(2); branch(carry()); break; // BCS
case 0xb1: addCycles(5); A() = through(AM_IndirectIndexedY()); break; // LDA (indirect indexed Y)
case 0xb2: break;
case 0xb3: break;
case 0xb4: addCycles(4); Y() = through(AM_ZeroPageX()); break; // LDY (zero page, X)
case 0xb5: addCycles(4); A() = through(AM_ZeroPageX()); break; // LDA (zero page, X)
case 0xb6: addCycles(4); X() = through(AM_ZeroPageY()); break; // LDX (zero page, Y)
case 0xb7: break;
case 0xb8: addCycles(2); clearFlag(P(), VF); break; // CLV
case 0xb9: addCycles(4); A() = through(AM_AbsoluteY()); break; // LDA (absolute, Y)
case 0xba: addCycles(2); X() = through(S()); break; // TSX
case 0xbb: break;
case 0xbc: addCycles(4); Y() = through(AM_AbsoluteX()); break; // LDY (absolute, X)
case 0xbd: addCycles(4); A() = through(AM_AbsoluteX()); break; // LDA (absolute, X)
case 0xbe: addCycles(4); X() = through(AM_AbsoluteY()); break; // LDX (absolute, Y)
case 0xbf: break;
case 0xd0: addCycles(2); Branch(!(P() & ZF)); break;
case 0xd1: addCycles(5); CMP(A(), AM_IndirectIndexedY()); break;
case 0xd2: addCycles(0); break;
case 0xd3: addCycles(7); DCP(AM_IndirectIndexedY()); break;
case 0xd4: addCycles(4); AM_ZeroPageX(); break;
case 0xd5: addCycles(4); CMP(A(), AM_ZeroPageX()); break;
case 0xd6: addCycles(6); BUS().write(DEC(AM_ZeroPageX())); break;
case 0xd7: addCycles(6); DCP(AM_ZeroPageX()); break;
case 0xd8: addCycles(2); clearFlag(P(), DF); break;
case 0xd9: addCycles(4); CMP(A(), AM_AbsoluteY()); break;
case 0xda: addCycles(2); break;
case 0xdb: addCycles(6); DCP(AM_AbsoluteY()); break;
case 0xdc: addCycles(4); AM_AbsoluteX(); break;
case 0xdd: addCycles(4); CMP(A(), AM_AbsoluteX()); break;
case 0xde: addCycles(7); BUS().write(DEC(AM_AbsoluteX())); break;
case 0xdf: addCycles(6); DCP(AM_AbsoluteX()); break;
case 0xc0: addCycles(2); cmp(Y(), AM_Immediate()); break; // CPY (immediate)
case 0xc1: addCycles(6); cmp(A(), AM_IndexedIndirectX()); break; // CMP (indexed indirect X)
case 0xc2: break;
case 0xc3: break;
case 0xc4: addCycles(3); cmp(Y(), AM_ZeroPage()); break; // CPY (zero page)
case 0xc5: addCycles(3); cmp(A(), AM_ZeroPage()); break; // CMP (zero page)
case 0xc6: addCycles(5); BUS().write(dec(AM_ZeroPage())); break; // DEC (zero page)
case 0xc7: break;
case 0xc8: addCycles(2); Y() = inc(Y()); break; // INY
case 0xc9: addCycles(2); cmp(A(), AM_Immediate()); break; // CMP (immediate)
case 0xca: addCycles(2); X() = dec(X()); break; // DEX
case 0xcb: break;
case 0xcc: addCycles(4); cmp(Y(), AM_Absolute()); break; // CPY (absolute)
case 0xcd: addCycles(4); cmp(A(), AM_Absolute()); break; // CMP (absolute)
case 0xce: addCycles(6); BUS().write(dec(AM_Absolute())); break; // DEC (absolute)
case 0xcf: break;
case 0xe0: addCycles(2); CMP(X(), AM_Immediate()); break;
case 0xe1: addCycles(6); A() = SBC(A(), AM_IndexedIndirectX()); break;
case 0xe2: addCycles(2); AM_Immediate(); break;
case 0xe3: addCycles(8); ISB(AM_IndexedIndirectX()); break;
case 0xe4: addCycles(3); CMP(X(), AM_ZeroPage()); break;
case 0xe5: addCycles(3); A() = SBC(A(), AM_ZeroPage()); break;
case 0xe6: addCycles(5); BUS().write(INC(AM_ZeroPage())); break;
case 0xe7: addCycles(5); ISB(AM_ZeroPage()); break;
case 0xe8: addCycles(2); adjustNZ(++X()); break;
case 0xe9: addCycles(2); A() = SBC(A(), AM_Immediate()); break;
case 0xea: addCycles(2); break;
case 0xeb: addCycles(2); A() = SBC(A(), AM_Immediate()); break;
case 0xec: addCycles(4); CMP(X(), AM_Absolute()); break;
case 0xed: addCycles(4); A() = SBC(A(), AM_Absolute()); break;
case 0xee: addCycles(6); BUS().write(INC(AM_Absolute())); break;
case 0xef: addCycles(6); ISB(AM_Absolute()); break;
case 0xd0: addCycles(2); branch(!zero()); break; // BNE
case 0xd1: addCycles(5); cmp(A(), AM_IndirectIndexedY()); break; // CMP (indirect indexed Y)
case 0xd2: break;
case 0xd3: break;
case 0xd4: break;
case 0xd5: addCycles(4); cmp(A(), AM_ZeroPageX()); break; // CMP (zero page, X)
case 0xd6: addCycles(6); BUS().write(dec(AM_ZeroPageX())); break; // DEC (zero page, X)
case 0xd7: break;
case 0xd8: addCycles(2); clearFlag(P(), DF); break; // CLD
case 0xd9: addCycles(4); cmp(A(), AM_AbsoluteY()); break; // CMP (absolute, Y)
case 0xda: break;
case 0xdb: break;
case 0xdc: break;
case 0xdd: addCycles(4); cmp(A(), AM_AbsoluteX()); break; // CMP (absolute, X)
case 0xde: addCycles(7); BUS().write(dec(AM_AbsoluteX())); break; // DEC (absolute, X)
case 0xdf: break;
case 0xf0: addCycles(2); Branch(!!(P() & ZF)); break;
case 0xf1: addCycles(5); A() = SBC(A(), AM_IndirectIndexedY()); break;
case 0xf2: addCycles(0); break;
case 0xf3: addCycles(7); ISB(AM_IndirectIndexedY()); break;
case 0xf4: addCycles(4); AM_ZeroPageX(); break;
case 0xf5: addCycles(4); A() = SBC(A(), AM_ZeroPageX()); break;
case 0xf6: addCycles(6); BUS().write(INC(AM_ZeroPageX())); break;
case 0xf7: addCycles(6); ISB(AM_ZeroPageX()); break;
case 0xf8: addCycles(2); setFlag(P(), DF); break;
case 0xf9: addCycles(4); A() = SBC(A(), AM_AbsoluteY()); break;
case 0xfa: addCycles(2); break;
case 0xfb: addCycles(6); ISB(AM_AbsoluteY()); break;
case 0xfc: addCycles(4); AM_AbsoluteX(); break;
case 0xfd: addCycles(4); A() = SBC(A(), AM_AbsoluteX()); break;
case 0xfe: addCycles(7); BUS().write(INC(AM_AbsoluteX())); break;
case 0xff: addCycles(6); ISB(AM_AbsoluteX()); break;
case 0xe0: addCycles(2); cmp(X(), AM_Immediate()); break; // CPX (immediate)
case 0xe1: addCycles(6); A() = sbc(A(), AM_IndexedIndirectX()); break; // SBC (indexed indirect X)
case 0xe2: break;
case 0xe3: break;
case 0xe4: addCycles(3); cmp(X(), AM_ZeroPage()); break; // CPX (zero page)
case 0xe5: addCycles(3); A() = sbc(A(), AM_ZeroPage()); break; // SBC (zero page)
case 0xe6: addCycles(5); BUS().write(inc(AM_ZeroPage())); break; // INC (zero page)
case 0xe7: break;
case 0xe8: addCycles(2); X() = inc(X()); break; // INX
case 0xe9: addCycles(2); A() = sbc(A(), AM_Immediate()); break; // SBC (immediate)
case 0xea: break;
case 0xeb: break;
case 0xec: addCycles(4); cmp(X(), AM_Absolute()); break; // CPX (absolute)
case 0xed: addCycles(4); A() = sbc(A(), AM_Absolute()); break; // SBC (absolute)
case 0xee: addCycles(6); BUS().write(inc(AM_Absolute())); break; // INC (absolute)
case 0xef: break;
case 0xf0: addCycles(2); branch(zero()); break; // BEQ
case 0xf1: addCycles(5); A() = sbc(A(), AM_IndirectIndexedY()); break; // SBC (indirect indexed Y)
case 0xf2: break;
case 0xf3: break;
case 0xf4: break;
case 0xf5: addCycles(4); A() = sbc(A(), AM_ZeroPageX()); break; // SBC (zero page, X)
case 0xf6: addCycles(6); BUS().write(inc(AM_ZeroPageX())); break; // INC (zero page, X)
case 0xf7: break;
case 0xf8: addCycles(2); setFlag(P(), DF); break; // SED
case 0xf9: addCycles(4); A() = sbc(A(), AM_AbsoluteY()); break; // SBC (absolute, Y)
case 0xfa: break;
case 0xfb: break;
case 0xfc: break;
case 0xfd: addCycles(4); A() = sbc(A(), AM_AbsoluteX()); break; // SBC (absolute, X)
case 0xfe: addCycles(7); BUS().write(inc(AM_AbsoluteX())); break; // INC (absolute, X)
case 0xff: break;
}
ASSUME(cycles() > 0);
@ -371,44 +373,114 @@ uint8_t EightBit::MOS6502::pop() {
////
uint8_t EightBit::MOS6502::ROR(uint8_t value) {
const auto carry = P() & CF;
setFlag(P(), CF, value & CF);
value = (value >> 1) | (carry << 7);
adjustNZ(value);
return value;
EightBit::register16_t EightBit::MOS6502::Address_Absolute() {
return fetchWord();
}
uint8_t EightBit::MOS6502::LSR(uint8_t value) {
setFlag(P(), CF, value & CF);
adjustNZ(value >>= 1);
return value;
uint8_t EightBit::MOS6502::Address_ZeroPage() {
return fetchByte();
}
void EightBit::MOS6502::BIT(uint8_t data) {
adjustZero(A() & data);
adjustNegative(data);
setFlag(P(), VF, data & VF);
EightBit::register16_t EightBit::MOS6502::Address_ZeroPageIndirect() {
return getWordPaged(0, Address_ZeroPage());
}
uint8_t EightBit::MOS6502::ROL(uint8_t value) {
const uint8_t result = (value << 1) | (P() & CF);
setFlag(P(), CF, value & Bit7);
adjustNZ(result);
return result;
EightBit::register16_t EightBit::MOS6502::Address_Indirect() {
const auto address = Address_Absolute();
return getWordPaged(address.high, address.low);
}
uint8_t EightBit::MOS6502::ASL(uint8_t value) {
setFlag(P(), CF, (value & Bit7) >> 7);
adjustNZ(value <<= 1);
return value;
uint8_t EightBit::MOS6502::Address_ZeroPageX() {
return Address_ZeroPage() + X();
}
uint8_t EightBit::MOS6502::SBC(const uint8_t operand, const uint8_t data) {
uint8_t EightBit::MOS6502::Address_ZeroPageY() {
return Address_ZeroPage() + Y();
}
const auto returned = SUB(operand, data, ~P() & CF);
std::pair<EightBit::register16_t, bool> EightBit::MOS6502::Address_AbsoluteX() {
auto address = Address_Absolute();
const auto page = address.high;
address += X();
return { address, address.high != page };
}
const register16_t& difference = m_intermediate;
std::pair<EightBit::register16_t, bool> EightBit::MOS6502::Address_AbsoluteY() {
auto address = Address_Absolute();
const auto page = address.high;
address += Y();
return { address, address.high != page };
}
EightBit::register16_t EightBit::MOS6502::Address_IndexedIndirectX() {
return getWordPaged(0, Address_ZeroPageX());
}
std::pair<EightBit::register16_t, bool> EightBit::MOS6502::Address_IndirectIndexedY() {
auto address = Address_ZeroPageIndirect();
const auto page = address.high;
address += Y();
return { address, address.high != page };
}
EightBit::register16_t EightBit::MOS6502::Address_relative_byte() {
return PC() + (int8_t)fetchByte();
}
// Addressing modes, read
uint8_t EightBit::MOS6502::AM_Immediate() {
return fetchByte();
}
uint8_t EightBit::MOS6502::AM_Absolute() {
return BUS().read(Address_Absolute());
}
uint8_t EightBit::MOS6502::AM_ZeroPage() {
return BUS().read(Address_ZeroPage());
}
uint8_t EightBit::MOS6502::AM_AbsoluteX() {
const auto [address, paged] = Address_AbsoluteX();
if (UNLIKELY(paged))
addCycle();
return BUS().read(address);
}
uint8_t EightBit::MOS6502::AM_AbsoluteY() {
const auto [address, paged] = Address_AbsoluteY();
if (UNLIKELY(paged))
addCycle();
return BUS().read(address);
}
uint8_t EightBit::MOS6502::AM_ZeroPageX() {
return BUS().read(Address_ZeroPageX());
}
uint8_t EightBit::MOS6502::AM_ZeroPageY() {
return BUS().read(Address_ZeroPageY());
}
uint8_t EightBit::MOS6502::AM_IndexedIndirectX() {
return BUS().read(Address_IndexedIndirectX());
}
uint8_t EightBit::MOS6502::AM_IndirectIndexedY() {
const auto [address, paged] = Address_IndirectIndexedY();
if (UNLIKELY(paged))
addCycle();
return BUS().read(address);
}
////
uint8_t EightBit::MOS6502::sbc(const uint8_t operand, const uint8_t data) {
const auto returned = sub(operand, data, ~P() & CF);
const auto difference = m_intermediate;
adjustNZ(difference.low);
setFlag(P(), VF, (operand ^ data) & (operand ^ difference.low) & NF);
clearFlag(P(), CF, difference.high);
@ -416,16 +488,16 @@ uint8_t EightBit::MOS6502::SBC(const uint8_t operand, const uint8_t data) {
return returned;
}
uint8_t EightBit::MOS6502::SUB(const uint8_t operand, const uint8_t data, const int borrow) {
return P() & DF ? SUB_d(operand, data, borrow) : SUB_b(operand, data, borrow);
uint8_t EightBit::MOS6502::sub(const uint8_t operand, const uint8_t data, const int borrow) {
return decimal() ? sub_d(operand, data, borrow) : sub_b(operand, data, borrow);
}
uint8_t EightBit::MOS6502::SUB_b(const uint8_t operand, const uint8_t data, const int borrow) {
uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const uint8_t data, const int borrow) {
m_intermediate.word = operand - data - borrow;
return m_intermediate.low;
}
uint8_t EightBit::MOS6502::SUB_d(const uint8_t operand, const uint8_t data, const int borrow) {
uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, const int borrow) {
m_intermediate.word = operand - data - borrow;
uint8_t low = lowNibble(operand) - lowNibble(data) - borrow;
@ -441,23 +513,17 @@ uint8_t EightBit::MOS6502::SUB_d(const uint8_t operand, const uint8_t data, cons
return promoteNibble(high) | lowNibble(low);
}
void EightBit::MOS6502::CMP(const uint8_t first, const uint8_t second) {
const register16_t result = first - second;
adjustNZ(result.low);
clearFlag(P(), CF, result.high);
}
uint8_t EightBit::MOS6502::ADC(const uint8_t operand, const uint8_t data) {
const auto returned = ADD(operand, data, P() & CF);
uint8_t EightBit::MOS6502::adc(const uint8_t operand, const uint8_t data) {
const auto returned = add(operand, data, carry());
adjustNZ(m_intermediate.low);
return returned;
}
uint8_t EightBit::MOS6502::ADD(uint8_t operand, uint8_t data, int carry) {
return P() & DF ? ADD_d(operand, data, carry) : ADD_b(operand, data, carry);
uint8_t EightBit::MOS6502::add(uint8_t operand, uint8_t data, int carry) {
return decimal() ? add_d(operand, data, carry) : add_b(operand, data, carry);
}
uint8_t EightBit::MOS6502::ADD_b(uint8_t operand, uint8_t data, int carry) {
uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carry) {
m_intermediate.word = operand + data + carry;
setFlag(P(), VF, ~(operand ^ data) & (operand ^ m_intermediate.low) & NF);
@ -466,7 +532,7 @@ uint8_t EightBit::MOS6502::ADD_b(uint8_t operand, uint8_t data, int carry) {
return m_intermediate.low;
}
uint8_t EightBit::MOS6502::ADD_d(uint8_t operand, uint8_t data, int carry) {
uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) {
m_intermediate.word = operand + data + carry;
@ -485,61 +551,90 @@ uint8_t EightBit::MOS6502::ADD_d(uint8_t operand, uint8_t data, int carry) {
return promoteNibble(high) | lowNibble(low);
}
////
void EightBit::MOS6502::Branch(const int8_t displacement) {
const auto page = PC().high;
PC() += displacement;
if (UNLIKELY(PC().high != page))
addCycle();
addCycle();
uint8_t EightBit::MOS6502::andr(const uint8_t operand, const uint8_t data) {
return through(operand & data);
}
void EightBit::MOS6502::Branch(const bool flag) {
const int8_t displacement = AM_Immediate();
if (UNLIKELY(flag))
Branch(displacement);
uint8_t EightBit::MOS6502::asl(const uint8_t value) {
setFlag(P(), CF, (value & Bit7) >> 7);
return through(value << 1);
}
//
void EightBit::MOS6502::PHP() {
push(P() | BF);
void EightBit::MOS6502::bit(const uint8_t operand, const uint8_t data) {
setFlag(P(), VF, data & VF);
adjustZero(operand & data);
adjustNegative(data);
}
void EightBit::MOS6502::PLP() {
P() = (pop() | RF) & ~BF;
}
//
void EightBit::MOS6502::JSR_abs() {
const auto address = Address_Absolute();
--PC();
call(address);
}
void EightBit::MOS6502::RTI() {
PLP();
ret();
}
void EightBit::MOS6502::RTS() {
ret();
++PC();
}
void EightBit::MOS6502::JMP_abs() {
jump(Address_Absolute());
}
void EightBit::MOS6502::JMP_ind() {
jump(Address_Indirect());
}
void EightBit::MOS6502::BRK() {
void EightBit::MOS6502::brk() {
pushWord(++PC());
PHP();
php();
setFlag(P(), IF);
jump(getWordPaged(0xff, IRQvector));
}
void EightBit::MOS6502::cmp(const uint8_t first, const uint8_t second) {
const register16_t result = first - second;
adjustNZ(result.low);
clearFlag(P(), CF, result.high);
}
uint8_t EightBit::MOS6502::dec(const uint8_t value) {
return through(value - 1);
}
uint8_t EightBit::MOS6502::eorr(const uint8_t operand, const uint8_t data) {
return through(operand ^ data);
}
uint8_t EightBit::MOS6502::inc(const uint8_t value) {
return through(value + 1);
}
void EightBit::MOS6502::jsr(const register16_t destination) {
--PC();
call(destination);
}
uint8_t EightBit::MOS6502::lsr(const uint8_t value) {
setFlag(P(), CF, value & Bit0);
return through(value >> 1);
}
uint8_t EightBit::MOS6502::orr(const uint8_t operand, const uint8_t data) {
return through(operand | data);
}
void EightBit::MOS6502::php() {
push(P() | BF);
}
void EightBit::MOS6502::plp() {
P() = (pop() | RF) & ~BF;
}
uint8_t EightBit::MOS6502::rol(uint8_t operand) {
const auto carryIn = carry();
setFlag(P(), CF, operand & Bit7);
operand <<= 1;
operand |= carryIn;
return through(operand);
}
uint8_t EightBit::MOS6502::ror(uint8_t operand) {
const auto carryIn = carry();
setFlag(P(), CF, operand & Bit0);
operand >>= 1;
operand |= (carryIn << 7);
return through(operand);
}
void EightBit::MOS6502::rti() {
plp();
ret();
}
void EightBit::MOS6502::rts() {
ret();
++PC();
}

View File

@ -2,25 +2,24 @@
#pragma once
#endif
#include <cstdint>
#include <functional>
#include <cassert>
#include <string>
#include <array>
#include <map>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cstdint>
#include <fstream>
#include <functional>
#include <iomanip>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <Bus.h>
#include <LittleEndianProcessor.h>
#include <Signal.h>
#include <EightBitCompilerDefinitions.h>
#include <EventArgs.h>
#include <LittleEndianProcessor.h>
#include <Register.h>
#include <Signal.h>

View File

@ -327,6 +327,7 @@ namespace EightBit {
uint8_t andr(uint8_t operand, uint8_t data);
uint8_t asl(uint8_t operand);
uint8_t asr(uint8_t operand);
void bit(uint8_t operand, uint8_t data);
uint8_t clr();
void cmp(uint8_t operand, uint8_t data);
void cmp(register16_t operand, register16_t data);
@ -334,7 +335,7 @@ namespace EightBit {
void cwai(uint8_t data);
uint8_t da(uint8_t operand);
uint8_t dec(uint8_t operand);
uint8_t eor(uint8_t operand, uint8_t data);
uint8_t eorr(uint8_t operand, uint8_t data);
void exg(uint8_t data);
uint8_t inc(uint8_t operand);
void jsr(register16_t address);

View File

@ -8,7 +8,7 @@ EightBit::mc6809::mc6809(Bus& bus)
: BigEndianProcessor(bus) {}
void EightBit::mc6809::powerOn() {
Processor::powerOn();
BigEndianProcessor::powerOn();
lower(BA());
lower(BS());
}
@ -43,7 +43,7 @@ void EightBit::mc6809::handleHALT() {
}
void EightBit::mc6809::handleRESET() {
Processor::handleRESET();
BigEndianProcessor::handleRESET();
raise(NMI());
lower(BA());
raise(BS());
@ -66,7 +66,7 @@ void EightBit::mc6809::handleNMI() {
}
void EightBit::mc6809::handleIRQ() {
Processor::handleIRQ();
BigEndianProcessor::handleIRQ();
lower(BA());
raise(BS());
saveEntireRegisterState();
@ -173,15 +173,15 @@ void EightBit::mc6809::executeUnprefixed(const uint8_t opcode) {
case 0x77: addCycles(7); BUS().write(asr(AM_extended_byte())); break; // ASR (extended)
// BIT
case 0x85: addCycles(2); andr(A(), AM_immediate_byte()); break; // BIT (BITA immediate)
case 0x95: addCycles(4); andr(A(), AM_direct_byte()); break; // BIT (BITA direct)
case 0xa5: addCycles(4); andr(A(), AM_indexed_byte()); break; // BIT (BITA indexed)
case 0xb5: addCycles(5); andr(A(), AM_extended_byte()); break; // BIT (BITA extended)
case 0x85: addCycles(2); bit(A(), AM_immediate_byte()); break; // BIT (BITA immediate)
case 0x95: addCycles(4); bit(A(), AM_direct_byte()); break; // BIT (BITA direct)
case 0xa5: addCycles(4); bit(A(), AM_indexed_byte()); break; // BIT (BITA indexed)
case 0xb5: addCycles(5); bit(A(), AM_extended_byte()); break; // BIT (BITA extended)
case 0xc5: addCycles(2); andr(B(), AM_immediate_byte()); break; // BIT (BITB immediate)
case 0xd5: addCycles(4); andr(B(), AM_direct_byte()); break; // BIT (BITB direct)
case 0xe5: addCycles(4); andr(B(), AM_indexed_byte()); break; // BIT (BITB indexed)
case 0xf5: addCycles(5); andr(B(), AM_extended_byte()); break; // BIT (BITB extended)
case 0xc5: addCycles(2); bit(B(), AM_immediate_byte()); break; // BIT (BITB immediate)
case 0xd5: addCycles(4); bit(B(), AM_direct_byte()); break; // BIT (BITB direct)
case 0xe5: addCycles(4); bit(B(), AM_indexed_byte()); break; // BIT (BITB indexed)
case 0xf5: addCycles(5); bit(B(), AM_extended_byte()); break; // BIT (BITB extended)
// CLR
case 0x0f: addCycles(6); BUS().write(Address_direct(), clr()); break; // CLR (direct)
@ -233,16 +233,16 @@ void EightBit::mc6809::executeUnprefixed(const uint8_t opcode) {
// EOR
// EORA
case 0x88: addCycles(2); A() = eor(A(), AM_immediate_byte()); break; // EOR (EORA immediate)
case 0x98: addCycles(4); A() = eor(A(), AM_direct_byte()); break; // EOR (EORA direct)
case 0xa8: addCycles(4); A() = eor(A(), AM_indexed_byte()); break; // EOR (EORA indexed)
case 0xb8: addCycles(5); A() = eor(A(), AM_extended_byte()); break; // EOR (EORA extended)
case 0x88: addCycles(2); A() = eorr(A(), AM_immediate_byte()); break; // EOR (EORA immediate)
case 0x98: addCycles(4); A() = eorr(A(), AM_direct_byte()); break; // EOR (EORA direct)
case 0xa8: addCycles(4); A() = eorr(A(), AM_indexed_byte()); break; // EOR (EORA indexed)
case 0xb8: addCycles(5); A() = eorr(A(), AM_extended_byte()); break; // EOR (EORA extended)
// EORB
case 0xc8: addCycles(2); B() = eor(B(), AM_immediate_byte()); break; // EOR (EORB immediate)
case 0xd8: addCycles(4); B() = eor(B(), AM_direct_byte()); break; // EOR (EORB direct)
case 0xe8: addCycles(4); B() = eor(B(), AM_indexed_byte()); break; // EOR (EORB indexed)
case 0xf8: addCycles(5); B() = eor(B(), AM_extended_byte()); break; // EOR (EORB extended)
case 0xc8: addCycles(2); B() = eorr(B(), AM_immediate_byte()); break; // EOR (EORB immediate)
case 0xd8: addCycles(4); B() = eorr(B(), AM_direct_byte()); break; // EOR (EORB direct)
case 0xe8: addCycles(4); B() = eorr(B(), AM_indexed_byte()); break; // EOR (EORB indexed)
case 0xf8: addCycles(5); B() = eorr(B(), AM_extended_byte()); break; // EOR (EORB extended)
// EXG
case 0x1e: addCycles(8); exg(AM_immediate_byte()); break; // EXG (R1,R2 immediate)
@ -793,6 +793,10 @@ uint8_t EightBit::mc6809::asr(uint8_t operand) {
return operand;
}
void EightBit::mc6809::bit(const uint8_t operand, const uint8_t data) {
andr(operand, data);
}
uint8_t EightBit::mc6809::clr() {
clearFlag(CC(), CF);
return through((uint8_t)0U);
@ -840,7 +844,7 @@ uint8_t EightBit::mc6809::dec(const uint8_t operand) {
return result;
}
uint8_t EightBit::mc6809::eor(const uint8_t operand, const uint8_t data) {
uint8_t EightBit::mc6809::eorr(const uint8_t operand, const uint8_t data) {
return through((uint8_t)(operand ^ data));
}

View File

@ -11,7 +11,7 @@ namespace EightBit {
virtual ~Ricoh2A03() = default;
protected:
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow) final;
virtual uint8_t ADD(uint8_t operand, uint8_t data, int carry) final;
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow) final;
virtual uint8_t add(uint8_t operand, uint8_t data, int carry) final;
};
}

View File

@ -5,10 +5,10 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& bus)
: MOS6502(bus) {
}
uint8_t EightBit::Ricoh2A03::SUB(uint8_t operand, uint8_t data, int borrow) {
return MOS6502::SUB_b(operand ,data, borrow);
uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, uint8_t data, int borrow) {
return MOS6502::sub_b(operand ,data, borrow);
}
uint8_t EightBit::Ricoh2A03::ADD(uint8_t operand, uint8_t data, int carry) {
return MOS6502::ADD_b(operand, data, carry);
uint8_t EightBit::Ricoh2A03::add(uint8_t operand, uint8_t data, int carry) {
return MOS6502::add_b(operand, data, carry);
}