2017-06-04 20:38:34 +00:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "mos6502.h"
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
EightBit::MOS6502::MOS6502(Memory& memory)
|
|
|
|
|
: Processor(memory) {
|
2017-07-15 22:19:46 +00:00
|
|
|
|
m_timings = {
|
|
|
|
|
//// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
|
|
|
/* 0 */ 7, 6, 0, 0, 0, 4, 5, 0, 3, 2, 2, 0, 0, 4, 6, 0,
|
|
|
|
|
/* 1 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
|
|
|
|
/* 2 */ 6, 6, 0, 0, 3, 3, 5, 0, 4, 2, 2, 0, 4, 4, 6, 0,
|
|
|
|
|
/* 3 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
|
|
|
|
/* 4 */ 6, 6, 0, 0, 0, 3, 5, 0, 3, 2, 2, 0, 3, 4, 6, 0,
|
|
|
|
|
/* 5 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
|
|
|
|
/* 6 */ 6, 6, 0, 0, 0, 3, 5, 0, 4, 2, 2, 0, 5, 4, 6, 0,
|
|
|
|
|
/* 7 */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
|
|
|
|
/* 8 */ 0, 6, 0, 0, 3, 3, 3, 0, 2, 0, 2, 0, 4, 4, 4, 0,
|
|
|
|
|
/* 9 */ 2, 6, 0, 0, 4, 4, 4, 0, 2, 5, 2, 0, 0, 5, 0, 0,
|
|
|
|
|
/* A */ 2, 6, 2, 0, 3, 3, 3, 0, 2, 2, 2, 0, 4, 4, 4, 0,
|
|
|
|
|
/* B */ 2, 5, 0, 0, 4, 4, 4, 0, 2, 4, 2, 0, 4, 4, 4, 0,
|
|
|
|
|
/* C */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
|
|
|
|
|
/* D */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
|
|
|
|
/* E */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
|
|
|
|
|
/* F */ 2, 5, 0, 0, 0, 4, 6, 0, 2, 4, 0, 0, 0, 4, 7, 0,
|
|
|
|
|
};
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
EightBit::MOS6502::~MOS6502() {
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
void EightBit::MOS6502::initialise() {
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
Processor::initialise();
|
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
for (int i = 0; i < 0x100; ++i) {
|
|
|
|
|
m_decodedOpcodes[i] = i;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
PC().word = 0;
|
2017-07-17 12:46:06 +00:00
|
|
|
|
X() = Bit7;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Y() = 0;
|
|
|
|
|
A() = 0;
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
P() = 0;
|
2017-07-10 14:51:33 +00:00
|
|
|
|
setFlag(P(), RF);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
S() = Mask8;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().word = 0;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
int EightBit::MOS6502::step() {
|
2017-07-06 11:02:41 +00:00
|
|
|
|
ExecutingInstruction.fire(*this);
|
|
|
|
|
auto returned = Execute(FetchByte());
|
|
|
|
|
ExecutedInstruction.fire(*this);
|
|
|
|
|
return returned;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::Reset() {
|
2017-07-06 20:32:52 +00:00
|
|
|
|
GetWord(RSTvector, PC());
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::TriggerIRQ() {
|
2017-06-04 20:38:34 +00:00
|
|
|
|
Interrupt(IRQvector);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::TriggerNMI() {
|
2017-06-04 20:38:34 +00:00
|
|
|
|
Interrupt(NMIvector);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-06 20:32:52 +00:00
|
|
|
|
void EightBit::MOS6502::GetWord(register16_t& output) {
|
|
|
|
|
output.low = GetByte();
|
|
|
|
|
m_memory.ADDRESS().word++;
|
|
|
|
|
output.high = GetByte();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EightBit::MOS6502::GetWord(uint16_t offset, register16_t& output) {
|
|
|
|
|
m_memory.ADDRESS().word = offset;
|
|
|
|
|
GetWord(output);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::Interrupt(uint16_t vector) {
|
2017-07-05 16:46:02 +00:00
|
|
|
|
PushWord(PC());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
PushByte(P());
|
2017-07-10 14:51:33 +00:00
|
|
|
|
setFlag(P(), IF);
|
2017-07-06 20:32:52 +00:00
|
|
|
|
GetWord(vector, PC());
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
int EightBit::MOS6502::Execute(uint8_t cell) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
|
2017-07-15 22:19:46 +00:00
|
|
|
|
cycles = m_timings[cell];
|
2017-07-13 11:02:44 +00:00
|
|
|
|
|
|
|
|
|
// http://www.llx.com/~nparker/a2/opcodes.html
|
|
|
|
|
|
|
|
|
|
// Most instructions that explicitly reference memory
|
|
|
|
|
// locations have bit patterns of the form aaabbbcc.
|
|
|
|
|
// The aaa and cc bits determine the opcode, and the bbb
|
|
|
|
|
// bits determine the addressing mode.
|
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
const auto& decoded = m_decodedOpcodes[cell];
|
2017-07-13 11:02:44 +00:00
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.cc) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b00:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.aaa) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000: // BRK
|
2017-07-14 16:22:28 +00:00
|
|
|
|
BRK();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b010: // PHP
|
2017-07-14 16:22:28 +00:00
|
|
|
|
PHP();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BPL
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch(!(P() & NF));
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // CLC
|
2017-07-14 16:22:28 +00:00
|
|
|
|
clearFlag(P(), CF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw std::domain_error("Illegal instruction");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b001:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000: // JSR
|
|
|
|
|
JSR_abs();
|
|
|
|
|
break;
|
|
|
|
|
case 0b010: // PLP
|
2017-07-14 16:22:28 +00:00
|
|
|
|
PLP();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BMI
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch((P() & NF) != 0);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // SEC
|
2017-07-14 16:22:28 +00:00
|
|
|
|
setFlag(P(), CF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // BIT
|
2017-07-17 12:46:06 +00:00
|
|
|
|
BIT(AM_00(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
assert(m_busRW);
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b010:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000: // RTI
|
2017-07-14 16:22:28 +00:00
|
|
|
|
RTI();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b010: // PHA
|
2017-07-14 16:22:28 +00:00
|
|
|
|
PushByte(A());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b011: // JMP
|
|
|
|
|
JMP_abs();
|
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BVC
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch(!(P() & VF));
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
2017-07-14 16:22:28 +00:00
|
|
|
|
case 0b110: // CLI
|
|
|
|
|
clearFlag(P(), IF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b011:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000: // RTS
|
2017-07-14 16:22:28 +00:00
|
|
|
|
RTS();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b010: // PLA
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(A() = PopByte());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b011: // JMP (abs)
|
|
|
|
|
JMP_ind();
|
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BVS
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch((P() & VF) != 0);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // SEI
|
2017-07-14 16:22:28 +00:00
|
|
|
|
setFlag(P(), IF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b100:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // DEY
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(--Y());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BCC
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch(!(P() & CF));
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // TYA
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(A() = Y());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // STY
|
2017-07-17 12:46:06 +00:00
|
|
|
|
AM_00(decoded.bbb, false);
|
2017-07-16 09:40:38 +00:00
|
|
|
|
assert(m_busRW);
|
|
|
|
|
m_memory.write(Y());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b101:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // TAY
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(Y() = A());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BCS
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch((P() & CF) != 0);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // CLV
|
2017-07-14 16:22:28 +00:00
|
|
|
|
clearFlag(P(), VF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // LDY
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(Y() = AM_00(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b110:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // INY
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(++Y());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BNE
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch(!(P() & ZF));
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // CLD
|
2017-07-14 16:22:28 +00:00
|
|
|
|
clearFlag(P(), DF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // CPY
|
2017-07-17 12:46:06 +00:00
|
|
|
|
CMP(Y(), AM_00(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b111:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // INX
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(++X());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // BEQ
|
2017-07-14 16:22:28 +00:00
|
|
|
|
Branch((P() & ZF) != 0);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // SED
|
2017-07-14 16:22:28 +00:00
|
|
|
|
setFlag(P(), DF);
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // CPX
|
2017-07-17 12:46:06 +00:00
|
|
|
|
CMP(X(), AM_00(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b01:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.aaa) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000: // ORA
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(A() |= AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b001: // AND
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(A() &= AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b010: // EOR
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(A() ^= AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b011: // ADC
|
2017-07-17 12:46:06 +00:00
|
|
|
|
ADC(AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100: // STA
|
2017-07-17 12:46:06 +00:00
|
|
|
|
AM_01(decoded.bbb, false);
|
2017-07-16 09:40:38 +00:00
|
|
|
|
assert(m_busRW);
|
|
|
|
|
m_memory.write(A());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b101: // LDA
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(A() = AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // CMP
|
2017-07-17 12:46:06 +00:00
|
|
|
|
CMP(A(), AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b111: // SBC
|
2017-07-17 12:46:06 +00:00
|
|
|
|
SBC(AM_01(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b10:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.aaa) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b000: // ASL
|
2017-07-17 12:46:06 +00:00
|
|
|
|
ASL(AM_10(decoded.bbb, false));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b001: // ROL
|
2017-07-17 12:46:06 +00:00
|
|
|
|
ROL(AM_10(decoded.bbb, false));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b010: // LSR
|
2017-07-17 12:46:06 +00:00
|
|
|
|
LSR(AM_10(decoded.bbb, false));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b011: // ROR
|
2017-07-17 12:46:06 +00:00
|
|
|
|
ROR(AM_10(decoded.bbb, false));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b100:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // TXA
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(A() = X());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 0b110: // TXS
|
2017-07-14 16:22:28 +00:00
|
|
|
|
S() = X();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // STX
|
2017-07-17 12:46:06 +00:00
|
|
|
|
AM_10_x(decoded.bbb, false);
|
2017-07-16 09:40:38 +00:00
|
|
|
|
assert(m_busRW);
|
|
|
|
|
m_memory.write(X());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b101:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b110: // TSX
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(X() = S());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // LDX
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(X() = AM_10_x(decoded.bbb));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b110:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // DEX
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(--X());
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
default: // DEC
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(--AM_10(decoded.bbb, false));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b111:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
switch (decoded.bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010: // NOP
|
|
|
|
|
break;
|
|
|
|
|
default: // INC
|
2017-07-17 12:46:06 +00:00
|
|
|
|
adjustNZ(++AM_10(decoded.bbb, false));
|
2017-07-16 09:40:38 +00:00
|
|
|
|
if (m_busRW)
|
|
|
|
|
m_memory.read();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0b11:
|
|
|
|
|
throw std::domain_error("Illegal instruction group");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
return cycles;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::PushByte(uint8_t value) {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
SetByte(PageOne + S()--, value);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
uint8_t EightBit::MOS6502::PopByte() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
return GetByte(PageOne + ++S());
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
void EightBit::MOS6502::PushWord(register16_t value) {
|
|
|
|
|
PushByte(value.high);
|
|
|
|
|
PushByte(value.low);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-06 20:32:52 +00:00
|
|
|
|
void EightBit::MOS6502::PopWord(register16_t& output) {
|
|
|
|
|
output.low = PopByte();
|
|
|
|
|
output.high = PopByte();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
uint8_t EightBit::MOS6502::FetchByte() {
|
2017-07-06 20:32:52 +00:00
|
|
|
|
m_memory.ADDRESS().word = PC().word++;
|
|
|
|
|
return GetByte();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-06 20:32:52 +00:00
|
|
|
|
void EightBit::MOS6502::FetchWord(register16_t& output) {
|
|
|
|
|
m_memory.ADDRESS().word = PC().word++;
|
|
|
|
|
GetWord(output);
|
|
|
|
|
PC().word++;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void EightBit::MOS6502::ROR(uint8_t& output) {
|
|
|
|
|
auto carry = P() & CF;
|
|
|
|
|
setFlag(P(), CF, output & CF);
|
|
|
|
|
output = (output >> 1) | (carry << 7);
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(output);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void EightBit::MOS6502::LSR(uint8_t& output) {
|
|
|
|
|
setFlag(P(), CF, output & CF);
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(output >>= 1);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::BIT(uint8_t data) {
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustZero(A() & data);
|
|
|
|
|
adjustNegative(data);
|
2017-07-10 14:51:33 +00:00
|
|
|
|
setFlag(P(), VF, data & VF);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void EightBit::MOS6502::ROL(uint8_t& output) {
|
|
|
|
|
uint8_t result = (output << 1) | (P() & CF);
|
|
|
|
|
setFlag(P(), CF, output & Bit7);
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(output = result);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void EightBit::MOS6502::ASL(uint8_t& output) {
|
2017-07-17 12:46:06 +00:00
|
|
|
|
setFlag(P(), CF, (output & Bit7) >> 7);
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(output <<= 1);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::SBC(uint8_t data) {
|
2017-07-10 14:51:33 +00:00
|
|
|
|
if (P() & DF)
|
2017-06-04 20:38:34 +00:00
|
|
|
|
SBC_d(data);
|
|
|
|
|
else
|
|
|
|
|
SBC_b(data);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::SBC_b(uint8_t data) {
|
2017-07-05 16:46:02 +00:00
|
|
|
|
register16_t difference;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
difference.word = A() - data - (~P() & CF);
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(difference.low);
|
2017-07-17 12:46:06 +00:00
|
|
|
|
setFlag(P(), VF, (A() ^ data) & (A() ^ difference.low) & NF);
|
2017-07-10 14:51:33 +00:00
|
|
|
|
clearFlag(P(), CF, difference.high);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
A() = difference.low;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::SBC_d(uint8_t data) {
|
2017-07-10 14:51:33 +00:00
|
|
|
|
auto carry = ~P() & CF;
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
|
|
|
|
register16_t difference;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
difference.word = A() - data - carry;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(difference.low);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-17 12:46:06 +00:00
|
|
|
|
setFlag(P(), VF, (A() ^ data) & (A() ^ difference.low) & NF);
|
2017-07-10 14:51:33 +00:00
|
|
|
|
clearFlag(P(), CF, difference.high);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
auto low = (uint8_t)(lowNibble(A()) - lowNibble(data) - carry);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
|
|
auto lowNegative = (int8_t)low < 0;
|
|
|
|
|
if (lowNegative)
|
|
|
|
|
low -= 6;
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
uint8_t high = highNibble(A()) - highNibble(data) - (lowNegative ? 1 : 0);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
|
|
if ((int8_t)high < 0)
|
|
|
|
|
high -= 6;
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
A() = promoteNibble(high) | lowNibble(low);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::CMP(uint8_t first, uint8_t second) {
|
2017-07-05 16:46:02 +00:00
|
|
|
|
register16_t result;
|
|
|
|
|
result.word = first - second;
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(result.low);
|
2017-07-10 14:51:33 +00:00
|
|
|
|
clearFlag(P(), CF, result.high);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::ADC(uint8_t data) {
|
2017-07-10 14:51:33 +00:00
|
|
|
|
if (P() & DF)
|
2017-06-04 20:38:34 +00:00
|
|
|
|
ADC_d(data);
|
|
|
|
|
else
|
|
|
|
|
ADC_b(data);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::ADC_b(uint8_t data) {
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
|
register16_t sum;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
sum.word = A() + data + (P() & CF);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(sum.low);
|
2017-07-17 12:46:06 +00:00
|
|
|
|
setFlag(P(), VF, ~(A() ^ data) & (A() ^ sum.low) & NF);
|
2017-07-10 14:51:33 +00:00
|
|
|
|
setFlag(P(), CF, sum.high & CF);
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
A() = sum.low;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::ADC_d(uint8_t data) {
|
2017-07-10 14:51:33 +00:00
|
|
|
|
auto carry = P() & CF;
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
|
|
|
|
register16_t sum;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
sum.word = A() + data + carry;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-16 09:05:49 +00:00
|
|
|
|
adjustNZ(sum.low);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
auto low = (uint8_t)(lowNibble(A()) + lowNibble(data) + carry);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
if (low > 9)
|
|
|
|
|
low += 6;
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
auto high = (uint8_t)(highNibble(A()) + highNibble(data) + (low > 0xf ? 1 : 0));
|
2017-07-17 12:46:06 +00:00
|
|
|
|
setFlag(P(), VF, ~(A() ^ data) & (A() ^ promoteNibble(high)) & NF);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
|
|
|
|
if (high > 9)
|
|
|
|
|
high += 6;
|
|
|
|
|
|
2017-07-10 14:51:33 +00:00
|
|
|
|
setFlag(P(), CF, high > 0xf);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
A() = (uint8_t)(promoteNibble(high) | lowNibble(low));
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::Branch(int8_t displacement) {
|
2017-07-15 22:19:46 +00:00
|
|
|
|
auto page = PC().high;
|
2017-07-05 16:46:02 +00:00
|
|
|
|
PC().word += displacement;
|
2017-07-15 22:19:46 +00:00
|
|
|
|
if (PC().high != page)
|
|
|
|
|
cycles++;
|
|
|
|
|
cycles++;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void EightBit::MOS6502::Branch(bool flag) {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
int8_t displacement = AM_Immediate();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
if (flag)
|
|
|
|
|
Branch(displacement);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::PHP() {
|
|
|
|
|
setFlag(P(), BF);
|
|
|
|
|
PushByte(P());
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::PLP() {
|
|
|
|
|
P() = PopByte();
|
|
|
|
|
setFlag(P(), RF);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::JSR_abs() {
|
|
|
|
|
Address_Absolute();
|
|
|
|
|
PC().word--;
|
|
|
|
|
PushWord(PC());
|
2017-07-17 12:46:06 +00:00
|
|
|
|
PC() = MEMPTR();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::RTI() {
|
|
|
|
|
PLP();
|
|
|
|
|
PopWord(PC());
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::RTS() {
|
|
|
|
|
PopWord(PC());
|
|
|
|
|
PC().word++;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::JMP_abs() {
|
|
|
|
|
Address_Absolute();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
PC() = MEMPTR();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::JMP_ind() {
|
|
|
|
|
Address_Indirect();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
PC() = MEMPTR();
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void EightBit::MOS6502::BRK() {
|
2017-07-05 16:46:02 +00:00
|
|
|
|
PC().word++;
|
|
|
|
|
PushWord(PC());
|
2017-07-14 16:22:28 +00:00
|
|
|
|
PHP();
|
2017-07-10 14:51:33 +00:00
|
|
|
|
setFlag(P(), IF);
|
2017-07-14 16:22:28 +00:00
|
|
|
|
GetWord(IRQvector, PC());
|
2017-06-04 20:38:34 +00:00
|
|
|
|
}
|