diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 4c6a827..a171aca 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -242,6 +242,98 @@ namespace EightBit { #pragma endregion References +#pragma region 6502 addressing mode switching + + uint8_t& AM_00(int bbb) { + switch (bbb) { + case 0b000: + return AM_Immediate(); + case 0b001: + return AM_ZeroPage(); + case 0b011: + return AM_Absolute(); + case 0b101: + return AM_ZeroPageX(); + case 0b111: + return AM_AbsoluteX(); + case 0b010: + case 0b100: + case 0b110: + throw std::domain_error("Illegal addressing mode"); + default: + __assume(0); + } + } + + uint8_t& AM_01(int bbb) { + switch (bbb) { + case 0b000: + return AM_IndexedIndirectX(); + case 0b001: + return AM_ZeroPage(); + case 0b010: + return AM_Immediate(); + case 0b011: + return AM_Absolute(); + case 0b100: + return AM_IndirectIndexedY(); + case 0b101: + return AM_ZeroPageX(); + case 0b110: + return AM_AbsoluteY(); + case 0b111: + return AM_AbsoluteX(); + default: + __assume(0); + } + } + + uint8_t& AM_10(int bbb) { + switch (bbb) { + case 0b000: + return AM_Immediate(); + case 0b001: + return AM_ZeroPage(); + case 0b010: + return AM_A(); + case 0b011: + return AM_Absolute(); + case 0b101: + return AM_ZeroPageX(); + case 0b111: + return AM_AbsoluteX(); + case 0b100: + case 0b110: + throw std::domain_error("Illegal addressing mode"); + default: + __assume(0); + } + } + + uint8_t& AM_10_x(int bbb, bool x = false) { + switch (bbb) { + case 0b000: + return AM_Immediate(); + case 0b001: + return AM_ZeroPage(); + case 0b010: + return AM_A(); + case 0b011: + return AM_Absolute(); + case 0b101: + return AM_ZeroPageY(); + case 0b111: + return AM_AbsoluteY(); + case 0b100: + case 0b110: + throw std::domain_error("Illegal addressing mode"); + default: + __assume(0); + } + } + +#pragma endregion 6502 addressing mode switching + #pragma endregion 6502 addressing modes void DEC(uint8_t& output); diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index d5dee49..ac34fc3 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -64,11 +64,265 @@ void EightBit::MOS6502::Interrupt(uint16_t vector) { } int EightBit::MOS6502::Execute(uint8_t cell) { + cycles = 0; - const auto& instruction = instructions[cell]; - const auto& method = instruction.vector; - method(); - cycles += instruction.count; + + // 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. + + auto aaa = (cell & 0b11100000) >> 5; + auto bbb = (cell & 0b00011100) >> 2; + auto cc = (cell & 0b00000011); + + switch (cc) { + case 0b00: + switch (aaa) { + case 0b000: + switch (bbb) { + case 0b000: // BRK + BRK_imp(); + break; + case 0b010: // PHP + PHP_imp(); + break; + case 0b100: // BPL + BPL_rel(); + break; + case 0b110: // CLC + CLC_imp(); + break; + default: + throw std::domain_error("Illegal instruction"); + } + break; + case 0b001: + switch (bbb) { + case 0b000: // JSR + JSR_abs(); + break; + case 0b010: // PLP + PLP_imp(); + break; + case 0b100: // BMI + BMI_rel(); + break; + case 0b110: // SEC + SEC_imp(); + break; + default: // BIT + BIT(AM_00(bbb)); + break; + } + break; + case 0b010: + switch (bbb) { + case 0b000: // RTI + RTI_imp(); + break; + case 0b010: // PHA + PHA_imp(); + break; + case 0b011: // JMP + JMP_abs(); + break; + case 0b100: // BVC + BVC_rel(); + break; + case 0b110: // BVC + CLI_imp(); + break; + default: + throw std::domain_error("Illegal addressing mode"); + } + break; + case 0b011: + switch (bbb) { + case 0b000: // RTS + RTS_imp(); + break; + case 0b010: // PLA + PLA_imp(); + break; + case 0b011: // JMP (abs) + JMP_ind(); + break; + case 0b100: // BVS + BVS_rel(); + break; + case 0b110: // SEI + SEI_imp(); + break; + default: + throw std::domain_error("Illegal addressing mode"); + } + break; + case 0b100: + switch (bbb) { + case 0b010: // DEY + DEY_imp(); + break; + case 0b100: // BCC + BCC_rel(); + break; + case 0b110: // TYA + TYA_imp(); + break; + default: // STY + AM_00(bbb) = Y(); + break; + } + break; + case 0b101: + switch (bbb) { + case 0b010: // TAY + TAY_imp(); + break; + case 0b100: // BCS + BCS_rel(); + break; + case 0b110: // CLV + CLV_imp(); + break; + default: // LDY + LDY(AM_00(bbb)); + break; + } + break; + case 0b110: + switch (bbb) { + case 0b010: // INY + INY_imp(); + break; + case 0b100: // BNE + BNE_rel(); + break; + case 0b110: // CLD + CLD_imp(); + break; + default: // CPY + CPY(AM_00(bbb)); + break; + } + break; + case 0b111: + switch (bbb) { + case 0b010: // INX + INX_imp(); + break; + case 0b100: // BEQ + BEQ_rel(); + break; + case 0b110: // SED + SED_imp(); + break; + default: // CPX + CPX(AM_00(bbb)); + break; + } + break; + } + break; + case 0b01: + switch (aaa) { + case 0b000: // ORA + ORA(AM_01(bbb)); + break; + case 0b001: // AND + AND(AM_01(bbb)); + break; + case 0b010: // EOR + EOR(AM_01(bbb)); + break; + case 0b011: // ADC + ADC(AM_01(bbb)); + break; + case 0b100: // STA + AM_01(bbb) = A(); + break; + case 0b101: // LDA + LDA(AM_01(bbb)); + break; + case 0b110: // CMP + CMP(AM_01(bbb)); + break; + case 0b111: // SBC + SBC(AM_01(bbb)); + break; + default: + __assume(0); + } + break; + case 0b10: + switch (aaa) { + case 0b000: // ASL + ASL(AM_10(bbb)); + break; + case 0b001: // ROL + ROL(AM_10(bbb)); + break; + case 0b010: // LSR + LSR(AM_10(bbb)); + break; + case 0b011: // ROR + ROR(AM_10(bbb)); + break; + case 0b100: + switch (bbb) { + case 0b010: // TXA + TXA_imp(); + break; + case 0b110: // TXS + TXS_imp(); + break; + default: // STX + AM_10_x(bbb) = X(); + break; + } + break; + case 0b101: + switch (bbb) { + case 0b110: // TSX + TSX_imp(); + break; + default: // LDX + LDX(AM_10_x(bbb)); + break; + } + break; + case 0b110: + switch (bbb) { + case 0b010: // DEX + DEX_imp(); + break; + default: // DEC + DEC(AM_10(bbb)); + break; + } + break; + case 0b111: + switch (bbb) { + case 0b010: // NOP + NOP_imp(); + break; + default: // INC + INC(AM_10(bbb)); + break; + } + break; + default: + __assume(0); + } + break; + case 0b11: + throw std::domain_error("Illegal instruction group"); + default: + __assume(0); + } + return cycles; } diff --git a/M6502/src/stdafx.h b/M6502/src/stdafx.h index d3535f5..9b131a4 100644 --- a/M6502/src/stdafx.h +++ b/M6502/src/stdafx.h @@ -2,6 +2,7 @@ #include #include +#include #include #include