mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-02-01 16:31:42 +00:00
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:
parent
b1af0710ba
commit
4dc0becb74
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "Disassembly.h"
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <functional>
|
||||
|
@ -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),
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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>
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user