mirror of
https://github.com/TomHarte/CLK.git
synced 2025-10-29 21:16:31 +00:00
Fix IndexedIndirect/IndirectIndexed confusion, proceed to test 0x14.
This commit is contained in:
@@ -68,7 +68,6 @@ enum class AccessProgram {
|
|||||||
ZeroXRead,
|
ZeroXRead,
|
||||||
ZeroXModify,
|
ZeroXModify,
|
||||||
ZeroXWrite,
|
ZeroXWrite,
|
||||||
ZeroXNOP,
|
|
||||||
|
|
||||||
ZeroYRead,
|
ZeroYRead,
|
||||||
ZeroYModify,
|
ZeroYModify,
|
||||||
@@ -112,14 +111,14 @@ struct Decoder<model, std::enable_if_t<is_6502(model)>> {
|
|||||||
case 0xc0: return {Immediate, Operation::CPY};
|
case 0xc0: return {Immediate, Operation::CPY};
|
||||||
case 0xe0: return {Immediate, Operation::CPX};
|
case 0xe0: return {Immediate, Operation::CPX};
|
||||||
|
|
||||||
case 0x01: return {IndirectIndexedRead, Operation::ORA};
|
case 0x01: return {IndexedIndirectRead, Operation::ORA};
|
||||||
case 0x21: return {IndirectIndexedRead, Operation::AND};
|
case 0x21: return {IndexedIndirectRead, Operation::AND};
|
||||||
case 0x41: return {IndirectIndexedRead, Operation::EOR};
|
case 0x41: return {IndexedIndirectRead, Operation::EOR};
|
||||||
case 0x61: return {IndirectIndexedRead, Operation::ADC};
|
case 0x61: return {IndexedIndirectRead, Operation::ADC};
|
||||||
case 0x81: return {IndirectIndexedWrite, Operation::STA};
|
case 0x81: return {IndexedIndirectWrite, Operation::STA};
|
||||||
case 0xa1: return {IndirectIndexedRead, Operation::LDA};
|
case 0xa1: return {IndexedIndirectRead, Operation::LDA};
|
||||||
case 0xc1: return {IndirectIndexedRead, Operation::CMP};
|
case 0xc1: return {IndexedIndirectRead, Operation::CMP};
|
||||||
case 0xe1: return {IndirectIndexedRead, Operation::SBC};
|
case 0xe1: return {IndexedIndirectRead, Operation::SBC};
|
||||||
|
|
||||||
case 0x02: return {JAM, Operation::JAM};
|
case 0x02: return {JAM, Operation::JAM};
|
||||||
case 0x22: return {JAM, Operation::JAM};
|
case 0x22: return {JAM, Operation::JAM};
|
||||||
@@ -130,14 +129,14 @@ struct Decoder<model, std::enable_if_t<is_6502(model)>> {
|
|||||||
case 0xc2: return {Implied, Operation::NOP};
|
case 0xc2: return {Implied, Operation::NOP};
|
||||||
case 0xe2: return {Implied, Operation::NOP};
|
case 0xe2: return {Implied, Operation::NOP};
|
||||||
|
|
||||||
case 0x03: return {IndirectIndexedModify, Operation::ASO};
|
case 0x03: return {IndexedIndirectModify, Operation::ASO};
|
||||||
case 0x23: return {IndirectIndexedModify, Operation::RLA};
|
case 0x23: return {IndexedIndirectModify, Operation::RLA};
|
||||||
case 0x43: return {IndirectIndexedModify, Operation::LSE};
|
case 0x43: return {IndexedIndirectModify, Operation::LSE};
|
||||||
case 0x63: return {IndirectIndexedModify, Operation::RRA};
|
case 0x63: return {IndexedIndirectModify, Operation::RRA};
|
||||||
case 0x83: return {IndirectIndexedWrite, Operation::SAX};
|
case 0x83: return {IndexedIndirectWrite, Operation::SAX};
|
||||||
case 0xa3: return {IndirectIndexedRead, Operation::LAX};
|
case 0xa3: return {IndexedIndirectRead, Operation::LAX};
|
||||||
case 0xc3: return {IndirectIndexedWrite, Operation::DCP};
|
case 0xc3: return {IndexedIndirectWrite, Operation::DCP};
|
||||||
case 0xe3: return {IndirectIndexedWrite, Operation::INS};
|
case 0xe3: return {IndexedIndirectWrite, Operation::INS};
|
||||||
|
|
||||||
case 0x04: return {ZeroRead, Operation::NOP};
|
case 0x04: return {ZeroRead, Operation::NOP};
|
||||||
case 0x24: return {ZeroRead, Operation::BIT};
|
case 0x24: return {ZeroRead, Operation::BIT};
|
||||||
@@ -283,14 +282,14 @@ struct Decoder<model, std::enable_if_t<is_6502(model)>> {
|
|||||||
case 0xd3: return {IndirectIndexedModify, Operation::DCP};
|
case 0xd3: return {IndirectIndexedModify, Operation::DCP};
|
||||||
case 0xf3: return {IndirectIndexedModify, Operation::INS};
|
case 0xf3: return {IndirectIndexedModify, Operation::INS};
|
||||||
|
|
||||||
case 0x14: return {ZeroXNOP, Operation::NOP};
|
case 0x14: return {ZeroXRead, Operation::NOP};
|
||||||
case 0x34: return {ZeroXNOP, Operation::NOP};
|
case 0x34: return {ZeroXRead, Operation::NOP};
|
||||||
case 0x54: return {ZeroXNOP, Operation::NOP};
|
case 0x54: return {ZeroXRead, Operation::NOP};
|
||||||
case 0x74: return {ZeroXNOP, Operation::NOP};
|
case 0x74: return {ZeroXRead, Operation::NOP};
|
||||||
case 0x94: return {ZeroXWrite, Operation::STY};
|
case 0x94: return {ZeroXWrite, Operation::STY};
|
||||||
case 0xb4: return {ZeroXRead, Operation::LDY};
|
case 0xb4: return {ZeroXRead, Operation::LDY};
|
||||||
case 0xd4: return {ZeroXNOP, Operation::NOP};
|
case 0xd4: return {ZeroXRead, Operation::NOP};
|
||||||
case 0xf4: return {ZeroXNOP, Operation::NOP};
|
case 0xf4: return {ZeroXRead, Operation::NOP};
|
||||||
|
|
||||||
case 0x15: return {ZeroXRead, Operation::ORA};
|
case 0x15: return {ZeroXRead, Operation::ORA};
|
||||||
case 0x35: return {ZeroXRead, Operation::AND};
|
case 0x35: return {ZeroXRead, Operation::AND};
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
|||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
|
|
||||||
// MARK: - Fetch/decode.
|
// MARK: - Fetch/decode.
|
||||||
|
|
||||||
fetch_decode:
|
fetch_decode:
|
||||||
case ResumePoint::FetchDecode:
|
case ResumePoint::FetchDecode:
|
||||||
|
|
||||||
@@ -114,6 +115,28 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
|||||||
CPU::MOS6502Mk2::perform<model>(Storage::decoded_.operation, registers, registers.a, Storage::opcode_);
|
CPU::MOS6502Mk2::perform<model>(Storage::decoded_.operation, registers, registers.a, Storage::opcode_);
|
||||||
goto fetch_decode;
|
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.
|
// MARK: - Zero.
|
||||||
|
|
||||||
case access_program(ZeroRead):
|
case access_program(ZeroRead):
|
||||||
@@ -209,7 +232,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
|||||||
|
|
||||||
// MARK: - Indexed indirect.
|
// MARK: - Indexed indirect.
|
||||||
|
|
||||||
case access_program(IndirectIndexedRead):
|
case access_program(IndexedIndirectRead):
|
||||||
++registers.pc.full;
|
++registers.pc.full;
|
||||||
access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway);
|
access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway);
|
||||||
Storage::operand_ += registers.x;
|
Storage::operand_ += registers.x;
|
||||||
@@ -221,7 +244,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
|||||||
perform_operation();
|
perform_operation();
|
||||||
goto fetch_decode;
|
goto fetch_decode;
|
||||||
|
|
||||||
case access_program(IndirectIndexedWrite):
|
case access_program(IndexedIndirectWrite):
|
||||||
++registers.pc.full;
|
++registers.pc.full;
|
||||||
access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway);
|
access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway);
|
||||||
Storage::operand_ += registers.x;
|
Storage::operand_ += registers.x;
|
||||||
@@ -233,15 +256,83 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
|||||||
access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_);
|
access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_);
|
||||||
goto fetch_decode;
|
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):
|
case access_program(IndirectIndexedModify):
|
||||||
++registers.pc.full;
|
++registers.pc.full;
|
||||||
access(BusOperation::Read, ZeroPage(Storage::operand_), throwaway);
|
|
||||||
Storage::operand_ += registers.x;
|
|
||||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low);
|
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low);
|
||||||
++Storage::operand_;
|
++Storage::operand_;
|
||||||
|
|
||||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high);
|
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::Read, Literal(Storage::address_.full), Storage::operand_);
|
||||||
access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_);
|
access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_);
|
||||||
|
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
perform_operation();
|
perform_operation();
|
||||||
access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_);
|
access(BusOperation::Write, Literal(Storage::address_.full), Storage::operand_);
|
||||||
|
|||||||
@@ -14,6 +14,24 @@
|
|||||||
|
|
||||||
namespace CPU::MOS6502Mk2 {
|
namespace CPU::MOS6502Mk2 {
|
||||||
|
|
||||||
|
template <typename RegistersT>
|
||||||
|
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 <Model model, typename RegistersT>
|
template <Model model, typename RegistersT>
|
||||||
void perform(const Operation operation, RegistersT ®isters, uint8_t &operand, const uint8_t opcode) {
|
void perform(const Operation operation, RegistersT ®isters, uint8_t &operand, const uint8_t opcode) {
|
||||||
(void)opcode;
|
(void)opcode;
|
||||||
|
|||||||
Reference in New Issue
Block a user