mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2026-01-22 12:19:32 +00:00
526 lines
20 KiB
C++
526 lines
20 KiB
C++
#include "stdafx.h"
|
|
#include "mos6502.h"
|
|
|
|
EightBit::MOS6502::MOS6502(Bus& bus)
|
|
: LittleEndianProcessor(bus) {}
|
|
|
|
void EightBit::MOS6502::powerOn() {
|
|
|
|
Processor::powerOn();
|
|
|
|
X() = Bit7;
|
|
Y() = 0;
|
|
A() = 0;
|
|
P() = RF;
|
|
S() = Mask8;
|
|
|
|
raise(SO());
|
|
}
|
|
|
|
int EightBit::MOS6502::step() {
|
|
resetCycles();
|
|
auto returned = 0;
|
|
if (LIKELY(powered())) {
|
|
ExecutingInstruction.fire(*this);
|
|
if (UNLIKELY(lowered(SO()))) {
|
|
P() |= VF;
|
|
raise(SO());
|
|
}
|
|
if (UNLIKELY(lowered(NMI()))) {
|
|
raise(NMI());
|
|
interrupt(NMIvector);
|
|
returned = 4; // ?? TBC
|
|
} else if (UNLIKELY(lowered(INT()))) {
|
|
raise(INT());
|
|
interrupt(IRQvector);
|
|
returned = 4; // ?? TBC
|
|
} else if (UNLIKELY(lowered(HALT()))) {
|
|
execute(0xea); // NOP
|
|
returned = 2; //
|
|
} else {
|
|
returned = execute(fetchByte());
|
|
}
|
|
ExecutedInstruction.fire(*this);
|
|
}
|
|
return returned;
|
|
}
|
|
|
|
void EightBit::MOS6502::reset() {
|
|
Processor::reset();
|
|
jump(getWordPaged(0xff, RSTvector));
|
|
}
|
|
|
|
void EightBit::MOS6502::interrupt(uint8_t vector) {
|
|
raise(HALT());
|
|
pushWord(PC());
|
|
push(P());
|
|
setFlag(P(), IF);
|
|
jump(getWordPaged(0xff, vector));
|
|
}
|
|
|
|
int EightBit::MOS6502::execute(uint8_t cell) {
|
|
|
|
switch (cell) {
|
|
|
|
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;
|
|
|
|
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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;
|
|
}
|
|
|
|
ASSUME(cycles() > 0);
|
|
return cycles();
|
|
}
|
|
|
|
////
|
|
|
|
void EightBit::MOS6502::push(uint8_t value) {
|
|
setBytePaged(1, S()--, value);
|
|
}
|
|
|
|
uint8_t EightBit::MOS6502::pop() {
|
|
return getBytePaged(1, ++S());
|
|
}
|
|
|
|
////
|
|
|
|
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;
|
|
}
|
|
|
|
uint8_t EightBit::MOS6502::LSR(uint8_t value) {
|
|
setFlag(P(), CF, value & CF);
|
|
adjustNZ(value >>= 1);
|
|
return value;
|
|
}
|
|
|
|
void EightBit::MOS6502::BIT(uint8_t data) {
|
|
adjustZero(A() & data);
|
|
adjustNegative(data);
|
|
setFlag(P(), VF, data & VF);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
uint8_t EightBit::MOS6502::ASL(uint8_t value) {
|
|
setFlag(P(), CF, (value & Bit7) >> 7);
|
|
adjustNZ(value <<= 1);
|
|
return value;
|
|
}
|
|
|
|
uint8_t EightBit::MOS6502::SBC(const uint8_t operand, const uint8_t data) {
|
|
|
|
const auto returned = SUB(operand, data, ~P() & CF);
|
|
|
|
const register16_t& difference = m_intermediate;
|
|
adjustNZ(difference.low);
|
|
setFlag(P(), VF, (operand ^ data) & (operand ^ difference.low) & NF);
|
|
clearFlag(P(), CF, difference.high);
|
|
|
|
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_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) {
|
|
m_intermediate.word = operand - data - borrow;
|
|
|
|
uint8_t low = lowNibble(operand) - lowNibble(data) - borrow;
|
|
const auto lowNegative = low & NF;
|
|
if (lowNegative)
|
|
low -= 6;
|
|
|
|
uint8_t high = highNibble(operand) - highNibble(data) - (lowNegative >> 7);
|
|
const auto highNegative = high & NF;
|
|
if (highNegative)
|
|
high -= 6;
|
|
|
|
return promoteNibble(high) | lowNibble(low);
|
|
}
|
|
|
|
void EightBit::MOS6502::CMP(uint8_t first, 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);
|
|
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_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);
|
|
setFlag(P(), CF, m_intermediate.high & CF);
|
|
|
|
return m_intermediate.low;
|
|
}
|
|
|
|
uint8_t EightBit::MOS6502::ADD_d(uint8_t operand, uint8_t data, int carry) {
|
|
|
|
m_intermediate.word = operand + data + carry;
|
|
|
|
uint8_t low = lowNibble(operand) + lowNibble(data) + carry;
|
|
if (low > 9)
|
|
low += 6;
|
|
|
|
uint8_t high = highNibble(operand) + highNibble(data) + (low > 0xf ? 1 : 0);
|
|
setFlag(P(), VF, ~(operand ^ data) & (operand ^ promoteNibble(high)) & NF);
|
|
|
|
if (high > 9)
|
|
high += 6;
|
|
|
|
setFlag(P(), CF, high > 0xf);
|
|
|
|
return promoteNibble(high) | lowNibble(low);
|
|
}
|
|
|
|
////
|
|
|
|
void EightBit::MOS6502::Branch(int8_t displacement) {
|
|
const auto page = PC().high;
|
|
PC() += displacement;
|
|
if (UNLIKELY(PC().high != page))
|
|
addCycle();
|
|
addCycle();
|
|
}
|
|
|
|
void EightBit::MOS6502::Branch(bool flag) {
|
|
const int8_t displacement = AM_Immediate();
|
|
if (UNLIKELY(flag))
|
|
Branch(displacement);
|
|
}
|
|
|
|
//
|
|
|
|
void EightBit::MOS6502::PHP() {
|
|
push(P() | BF);
|
|
}
|
|
|
|
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() {
|
|
pushWord(++PC());
|
|
PHP();
|
|
setFlag(P(), IF);
|
|
jump(getWordPaged(0xff, IRQvector));
|
|
}
|