diff --git a/Processors/6502Mk2/Decoder.hpp b/Processors/6502Mk2/Decoder.hpp index 6dee2ffea..a5955ec49 100644 --- a/Processors/6502Mk2/Decoder.hpp +++ b/Processors/6502Mk2/Decoder.hpp @@ -68,7 +68,6 @@ enum class AccessProgram { ZeroXRead, ZeroXModify, ZeroXWrite, - ZeroXNOP, ZeroYRead, ZeroYModify, @@ -112,14 +111,14 @@ struct Decoder> { case 0xc0: return {Immediate, Operation::CPY}; case 0xe0: return {Immediate, Operation::CPX}; - case 0x01: return {IndirectIndexedRead, Operation::ORA}; - case 0x21: return {IndirectIndexedRead, Operation::AND}; - case 0x41: return {IndirectIndexedRead, Operation::EOR}; - case 0x61: return {IndirectIndexedRead, Operation::ADC}; - case 0x81: return {IndirectIndexedWrite, Operation::STA}; - case 0xa1: return {IndirectIndexedRead, Operation::LDA}; - case 0xc1: return {IndirectIndexedRead, Operation::CMP}; - case 0xe1: return {IndirectIndexedRead, Operation::SBC}; + case 0x01: return {IndexedIndirectRead, Operation::ORA}; + case 0x21: return {IndexedIndirectRead, Operation::AND}; + case 0x41: return {IndexedIndirectRead, Operation::EOR}; + case 0x61: return {IndexedIndirectRead, Operation::ADC}; + case 0x81: return {IndexedIndirectWrite, Operation::STA}; + case 0xa1: return {IndexedIndirectRead, Operation::LDA}; + case 0xc1: return {IndexedIndirectRead, Operation::CMP}; + case 0xe1: return {IndexedIndirectRead, Operation::SBC}; case 0x02: return {JAM, Operation::JAM}; case 0x22: return {JAM, Operation::JAM}; @@ -130,14 +129,14 @@ struct Decoder> { case 0xc2: return {Implied, Operation::NOP}; case 0xe2: return {Implied, Operation::NOP}; - case 0x03: return {IndirectIndexedModify, Operation::ASO}; - case 0x23: return {IndirectIndexedModify, Operation::RLA}; - case 0x43: return {IndirectIndexedModify, Operation::LSE}; - case 0x63: return {IndirectIndexedModify, Operation::RRA}; - case 0x83: return {IndirectIndexedWrite, Operation::SAX}; - case 0xa3: return {IndirectIndexedRead, Operation::LAX}; - case 0xc3: return {IndirectIndexedWrite, Operation::DCP}; - case 0xe3: return {IndirectIndexedWrite, Operation::INS}; + case 0x03: return {IndexedIndirectModify, Operation::ASO}; + case 0x23: return {IndexedIndirectModify, Operation::RLA}; + case 0x43: return {IndexedIndirectModify, Operation::LSE}; + case 0x63: return {IndexedIndirectModify, Operation::RRA}; + case 0x83: return {IndexedIndirectWrite, Operation::SAX}; + case 0xa3: return {IndexedIndirectRead, Operation::LAX}; + case 0xc3: return {IndexedIndirectWrite, Operation::DCP}; + case 0xe3: return {IndexedIndirectWrite, Operation::INS}; case 0x04: return {ZeroRead, Operation::NOP}; case 0x24: return {ZeroRead, Operation::BIT}; @@ -283,14 +282,14 @@ struct Decoder> { case 0xd3: return {IndirectIndexedModify, Operation::DCP}; case 0xf3: return {IndirectIndexedModify, Operation::INS}; - case 0x14: return {ZeroXNOP, Operation::NOP}; - case 0x34: return {ZeroXNOP, Operation::NOP}; - case 0x54: return {ZeroXNOP, Operation::NOP}; - case 0x74: return {ZeroXNOP, Operation::NOP}; + case 0x14: return {ZeroXRead, Operation::NOP}; + case 0x34: return {ZeroXRead, Operation::NOP}; + case 0x54: return {ZeroXRead, Operation::NOP}; + case 0x74: return {ZeroXRead, Operation::NOP}; case 0x94: return {ZeroXWrite, Operation::STY}; case 0xb4: return {ZeroXRead, Operation::LDY}; - case 0xd4: return {ZeroXNOP, Operation::NOP}; - case 0xf4: return {ZeroXNOP, Operation::NOP}; + case 0xd4: return {ZeroXRead, Operation::NOP}; + case 0xf4: return {ZeroXRead, Operation::NOP}; case 0x15: return {ZeroXRead, Operation::ORA}; case 0x35: return {ZeroXRead, Operation::AND}; diff --git a/Processors/6502Mk2/Implementation/6502.hpp b/Processors/6502Mk2/Implementation/6502.hpp index a1536855b..7e994ae71 100644 --- a/Processors/6502Mk2/Implementation/6502.hpp +++ b/Processors/6502Mk2/Implementation/6502.hpp @@ -78,6 +78,7 @@ void Processor::run_for(const Cycles cycles) { __builtin_unreachable(); // MARK: - Fetch/decode. + fetch_decode: case ResumePoint::FetchDecode: @@ -114,6 +115,28 @@ void Processor::run_for(const Cycles cycles) { CPU::MOS6502Mk2::perform(Storage::decoded_.operation, registers, registers.a, Storage::opcode_); goto fetch_decode; + // MARK: - Relative. + + case access_program(Relative): + ++registers.pc.full; + + if(!test(Storage::decoded_.operation, registers)) { + goto fetch_decode; + } + + Storage::address_ = registers.pc; + access(BusOperation::Read, Literal(registers.pc.full), throwaway); + + registers.pc.full += int8_t(Storage::operand_); + if(registers.pc.halves.high == Storage::address_.halves.high) { + goto fetch_decode; + } + + Storage::address_.halves.low = registers.pc.halves.low; + access(BusOperation::Read, Literal(Storage::address_.full), throwaway); + + goto fetch_decode; + // MARK: - Zero. case access_program(ZeroRead): @@ -209,7 +232,7 @@ void Processor::run_for(const Cycles cycles) { // MARK: - Indexed indirect. - case access_program(IndirectIndexedRead): + case access_program(IndexedIndirectRead): ++registers.pc.full; access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway); Storage::operand_ += registers.x; @@ -221,7 +244,7 @@ void Processor::run_for(const Cycles cycles) { perform_operation(); goto fetch_decode; - case access_program(IndirectIndexedWrite): + case access_program(IndexedIndirectWrite): ++registers.pc.full; access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway); Storage::operand_ += registers.x; @@ -233,15 +256,83 @@ void Processor::run_for(const Cycles cycles) { access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_); goto fetch_decode; + case access_program(IndexedIndirectModify): + ++registers.pc.full; + access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway); + Storage::operand_ += registers.x; + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low); + ++Storage::operand_; + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high); + access(BusOperation::Read, Literal(Storage::address_.full), Storage::operand_); + access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_); + check_interrupt(); + perform_operation(); + access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_); + goto fetch_decode; + + // MARK: - Indirect indexed. + case access_program(IndirectIndexedRead): + ++registers.pc.full; + + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low); + ++Storage::operand_; + + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high); + + Storage::operand_ = Storage::address_.halves.high; + Storage::address_.full += registers.y; + if(Storage::address_.halves.high == Storage::operand_) { + goto skip_indirect_indexed_read_bonus_cycle; + } + + std::swap(Storage::address_.halves.high, Storage::operand_); + access(BusOperation::Read, Literal(Storage::address_.full), throwaway); + std::swap(Storage::address_.halves.high, Storage::operand_); + + skip_indirect_indexed_read_bonus_cycle: + check_interrupt(); + access(BusOperation::Read, Literal(Storage::address_.full), Storage::operand_); + perform_operation(); + goto fetch_decode; + + + case access_program(IndirectIndexedWrite): + ++registers.pc.full; + + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low); + ++Storage::operand_; + + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high); + + Storage::operand_ = Storage::address_.halves.high; + Storage::address_.full += registers.y; + std::swap(Storage::address_.halves.high, Storage::operand_); + access(BusOperation::Read, Literal(Storage::address_.full), throwaway); + std::swap(Storage::address_.halves.high, Storage::operand_); + + check_interrupt(); + perform_operation(); + access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_); + goto fetch_decode; + case access_program(IndirectIndexedModify): ++registers.pc.full; - access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway); - Storage::operand_ += registers.x; + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low); ++Storage::operand_; + access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high); + + Storage::operand_ = Storage::address_.halves.high; + Storage::address_.full += registers.y; + std::swap(Storage::address_.halves.high, Storage::operand_); + access(BusOperation::Read, Literal(Storage::address_.full), throwaway); + std::swap(Storage::address_.halves.high, Storage::operand_); + + skip_indirect_indexed_modify_bonus_cycle: access(BusOperation::Read, Literal(Storage::address_.full), Storage::operand_); access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_); + check_interrupt(); perform_operation(); access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_); diff --git a/Processors/6502Mk2/Perform.hpp b/Processors/6502Mk2/Perform.hpp index 433773740..fb8d7c32e 100644 --- a/Processors/6502Mk2/Perform.hpp +++ b/Processors/6502Mk2/Perform.hpp @@ -14,6 +14,24 @@ namespace CPU::MOS6502Mk2 { +template +bool test(const Operation operation, RegistersT ®isters) { + switch(operation) { + default: + __builtin_unreachable(); + + case Operation::BPL: return !(registers.flags.negative_result & 0x80); + case Operation::BMI: return registers.flags.negative_result & 0x80; + case Operation::BVC: return !registers.flags.overflow; + case Operation::BVS: return registers.flags.overflow; + case Operation::BCC: return !registers.flags.carry; + case Operation::BCS: return registers.flags.carry; + case Operation::BNE: return registers.flags.zero_result; + case Operation::BEQ: return !registers.flags.zero_result; + case Operation::BRA: return true; + } +} + template void perform(const Operation operation, RegistersT ®isters, uint8_t &operand, const uint8_t opcode) { (void)opcode;