mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-21 02:17:08 +00:00
Eliminate 'addr' side effects.
This commit is contained in:
@@ -48,12 +48,12 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
|
||||
#define restore_point() (__COUNTER__ + int(ResumePoint::Max) + int(AddressingMode::Max))
|
||||
|
||||
#define join(a, b) a##b
|
||||
#define attach(a, b) join(a, b)
|
||||
#define join(a, b) a##b
|
||||
#define attach(a, b) join(a, b)
|
||||
#define access_label() attach(repeat, __LINE__)
|
||||
|
||||
// TODO: find a way not to generate a restore point if pause precision and uses_ready_line/model allows it.
|
||||
#define access(type, addr, value) { \
|
||||
#define access(type, addr, value, ...) { \
|
||||
static constexpr int location = restore_point(); \
|
||||
[[fallthrough]]; case location: \
|
||||
[[maybe_unused]] access_label(): \
|
||||
@@ -80,11 +80,12 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
} else { \
|
||||
Data::Writeable target; \
|
||||
Storage::cycles_ -= Storage::bus_handler_.template perform<type>(addr, target); \
|
||||
WriteableReader::assign(value, target); \
|
||||
WriteableReader::assign(value, target); \
|
||||
} \
|
||||
} else { \
|
||||
Storage::cycles_ -= Storage::bus_handler_.template perform<type>(addr, value); \
|
||||
} \
|
||||
__VA_ARGS__; \
|
||||
}
|
||||
|
||||
#define access_program(name) int(ResumePoint::Max) + int(AddressingMode::name)
|
||||
@@ -110,6 +111,12 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
Storage::decoded_.operation == Operation::SBC
|
||||
) && registers.flags.decimal;
|
||||
};
|
||||
const auto set_interrupt_flag = [&] {
|
||||
registers.flags.inverse_interrupt = 0;
|
||||
if constexpr (is_65c02(model)) {
|
||||
registers.flags.decimal = 0;
|
||||
}
|
||||
};
|
||||
|
||||
using Literal = Address::Literal;
|
||||
using ZeroPage = Address::ZeroPage;
|
||||
@@ -207,8 +214,8 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
|
||||
access_absolute_65c02_decimal:
|
||||
access(BusOperation::Read, Literal(Storage::address_.full), Storage::operand_);
|
||||
perform_operation();
|
||||
access(BusOperation::Read, Literal(Storage::address_.full), Storage::operand_);
|
||||
perform_operation();
|
||||
goto fetch_decode;
|
||||
|
||||
// MARK: - Fetch/decode.
|
||||
@@ -226,8 +233,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
goto interrupt;
|
||||
}
|
||||
|
||||
access(BusOperation::ReadOpcode, Literal(registers.pc.full), Storage::opcode_);
|
||||
++registers.pc.full;
|
||||
access(BusOperation::ReadOpcode, Literal(registers.pc.full), Storage::opcode_, ++registers.pc.full);
|
||||
Storage::decoded_ = Decoder<model>::decode(Storage::opcode_);
|
||||
|
||||
// 65c02 special case: support single-cycle NOPs.
|
||||
@@ -259,9 +265,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
goto fetch_decode;
|
||||
|
||||
immediate_65c02_decimal:
|
||||
access(BusOperation::Read, Literal(registers.pc.full), Storage::operand_);
|
||||
|
||||
++registers.pc.full;
|
||||
access(BusOperation::Read, Literal(registers.pc.full), Storage::operand_, ++registers.pc.full);
|
||||
perform_operation();
|
||||
goto fetch_decode;
|
||||
|
||||
@@ -277,14 +281,14 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
// MARK: - Stack.
|
||||
|
||||
case access_program(Pull):
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, ++registers.s);
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_);
|
||||
access(BusOperation::Read, Stack(registers.inc_s()), Storage::operand_);
|
||||
perform_operation();
|
||||
goto fetch_decode;
|
||||
|
||||
case access_program(Push):
|
||||
perform_operation();
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), Storage::operand_);
|
||||
access(BusOperation::Write, Stack(registers.s), Storage::operand_, --registers.s);
|
||||
goto fetch_decode;
|
||||
|
||||
// MARK: - Relative, and BBR/BBS (for the 65c02).
|
||||
@@ -314,9 +318,8 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
Storage::address_.halves.low = Storage::operand_;
|
||||
access(BusOperation::Read, ZeroPage(Storage::address_.halves.low), Storage::operand_);
|
||||
access(BusOperation::Read, ZeroPage(Storage::address_.halves.low), Storage::operand_);
|
||||
access(BusOperation::Read, Literal(registers.pc.full), Storage::address_.halves.low);
|
||||
access(BusOperation::Read, Literal(registers.pc.full), Storage::address_.halves.low, ++registers.pc.full);
|
||||
|
||||
++registers.pc.full;
|
||||
if(!test_bbr_bbs(Storage::opcode_, Storage::operand_)) {
|
||||
goto fetch_decode;
|
||||
}
|
||||
@@ -352,7 +355,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
// MARK: - Zero indirect (which is exclusive to the 65c02).
|
||||
|
||||
case access_program(ZeroIndirect):
|
||||
access(BusOperation::Read, ZeroPage(Storage::operand_++), Storage::address_.halves.low);
|
||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low, ++Storage::operand_);
|
||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high);
|
||||
|
||||
goto access_absolute;
|
||||
@@ -418,17 +421,14 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
case access_program(IndexedIndirect):
|
||||
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.low, ++Storage::operand_);
|
||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.high);
|
||||
goto access_absolute;
|
||||
|
||||
// MARK: - Indirect indexed.
|
||||
|
||||
case access_program(IndirectIndexed):
|
||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low);
|
||||
++Storage::operand_;
|
||||
|
||||
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;
|
||||
@@ -455,10 +455,8 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
|
||||
case access_program(SHxAbsoluteXY):
|
||||
++registers.pc.full;
|
||||
|
||||
Storage::address_.halves.low = Storage::operand_;
|
||||
access(BusOperation::Read, Literal(registers.pc.full), Storage::address_.halves.high);
|
||||
++registers.pc.full;
|
||||
access(BusOperation::Read, Literal(registers.pc.full), Storage::address_.halves.high, ++registers.pc.full);
|
||||
|
||||
Storage::operand_ = Storage::address_.halves.high;
|
||||
Storage::address_.full += (Storage::decoded_.operation == Operation::SHY) ? registers.x : registers.y;
|
||||
@@ -490,10 +488,7 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
|
||||
case access_program(SHxIndirectIndexed):
|
||||
++registers.pc.full;
|
||||
|
||||
access(BusOperation::Read, ZeroPage(Storage::operand_), Storage::address_.halves.low);
|
||||
++Storage::operand_;
|
||||
|
||||
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;
|
||||
@@ -534,31 +529,30 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
case access_program(JSR):
|
||||
++registers.pc.full;
|
||||
access(BusOperation::Read, Stack(registers.s), throwaway);
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), registers.pc.halves.high);
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), registers.pc.halves.low);
|
||||
access(BusOperation::Write, Stack(registers.s), registers.pc.halves.high, --registers.s);
|
||||
access(BusOperation::Write, Stack(registers.s), registers.pc.halves.low, --registers.s);
|
||||
access(BusOperation::Read, Literal(registers.pc.full), registers.pc.halves.high);
|
||||
registers.pc.halves.low = Storage::operand_;
|
||||
|
||||
goto fetch_decode;
|
||||
|
||||
case access_program(RTI):
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_);
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, ++registers.s);
|
||||
|
||||
access(BusOperation::Read, Stack(registers.inc_s()), Storage::operand_);
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, ++registers.s);
|
||||
registers.flags = Flags(Storage::operand_);
|
||||
|
||||
access(BusOperation::Read, Stack(registers.inc_s()), registers.pc.halves.low);
|
||||
access(BusOperation::Read, Stack(registers.inc_s()), registers.pc.halves.high);
|
||||
access(BusOperation::Read, Stack(registers.s), registers.pc.halves.low, ++registers.s);
|
||||
access(BusOperation::Read, Stack(registers.s), registers.pc.halves.high);
|
||||
|
||||
goto fetch_decode;
|
||||
|
||||
case access_program(RTS):
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_);
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, ++registers.s);
|
||||
|
||||
access(BusOperation::Read, Stack(registers.inc_s()), registers.pc.halves.low);
|
||||
access(BusOperation::Read, Stack(registers.inc_s()), registers.pc.halves.high);
|
||||
access(BusOperation::Read, Literal(registers.pc.full), throwaway);
|
||||
++registers.pc.full;
|
||||
access(BusOperation::Read, Stack(registers.s), registers.pc.halves.low, ++registers.s);
|
||||
access(BusOperation::Read, Stack(registers.s), registers.pc.halves.high);
|
||||
access(BusOperation::Read, Literal(registers.pc.full), throwaway, ++registers.pc.full);
|
||||
|
||||
goto fetch_decode;
|
||||
|
||||
@@ -595,7 +589,12 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
access(BusOperation::Read, Literal(registers.pc.full), throwaway);
|
||||
|
||||
Storage::address_.full += registers.x;
|
||||
access(BusOperation::Read, Literal(Storage::address_.full++), registers.pc.halves.low);
|
||||
access(
|
||||
BusOperation::Read,
|
||||
Literal(Storage::address_.full),
|
||||
registers.pc.halves.low,
|
||||
++Storage::address_.full
|
||||
);
|
||||
access(BusOperation::Read, Literal(Storage::address_.full), registers.pc.halves.high);
|
||||
|
||||
goto fetch_decode;
|
||||
@@ -604,19 +603,16 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
|
||||
case access_program(BRK):
|
||||
++registers.pc.full;
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), registers.pc.halves.high);
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), registers.pc.halves.low);
|
||||
access(BusOperation::Write, Stack(registers.s), registers.pc.halves.high, --registers.s);
|
||||
access(BusOperation::Write, Stack(registers.s), registers.pc.halves.low, --registers.s);
|
||||
access(
|
||||
BusOperation::Write,
|
||||
Stack(registers.dec_s()),
|
||||
static_cast<uint8_t>(registers.flags) | Flag::Break
|
||||
Stack(registers.s),
|
||||
static_cast<uint8_t>(registers.flags) | Flag::Break,
|
||||
--registers.s
|
||||
);
|
||||
|
||||
registers.flags.inverse_interrupt = 0;
|
||||
if constexpr (is_65c02(model)) {
|
||||
registers.flags.decimal = 0;
|
||||
}
|
||||
|
||||
set_interrupt_flag();
|
||||
access(BusOperation::Read, Vector(0xfe), registers.pc.halves.low);
|
||||
access(BusOperation::Read, Vector(0xff), registers.pc.halves.high);
|
||||
goto fetch_decode;
|
||||
@@ -630,17 +626,16 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
goto reset;
|
||||
}
|
||||
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), registers.pc.halves.high);
|
||||
access(BusOperation::Write, Stack(registers.dec_s()), registers.pc.halves.low);
|
||||
access(BusOperation::Write, Stack(registers.s), registers.pc.halves.high, --registers.s);
|
||||
access(BusOperation::Write, Stack(registers.s), registers.pc.halves.low, --registers.s);
|
||||
access(
|
||||
BusOperation::Write,
|
||||
Stack(registers.dec_s()),
|
||||
static_cast<uint8_t>(registers.flags) & ~Flag::Break
|
||||
Stack(registers.s),
|
||||
static_cast<uint8_t>(registers.flags) & ~Flag::Break,
|
||||
--registers.s
|
||||
);
|
||||
|
||||
registers.flags.inverse_interrupt = 0;
|
||||
if constexpr (is_65c02(model)) registers.flags.decimal = 0;
|
||||
|
||||
set_interrupt_flag();
|
||||
if(Storage::captured_interrupt_requests_ & InterruptRequest::NMI) {
|
||||
Storage::inputs_.interrupt_requests &= ~InterruptRequest::NMI;
|
||||
goto nmi;
|
||||
@@ -656,13 +651,11 @@ void Processor<model, Traits>::run_for(const Cycles cycles) {
|
||||
goto fetch_decode;
|
||||
|
||||
reset:
|
||||
access(BusOperation::Read, Stack(registers.dec_s()), Storage::operand_);
|
||||
access(BusOperation::Read, Stack(registers.dec_s()), Storage::operand_);
|
||||
access(BusOperation::Read, Stack(registers.dec_s()), Storage::operand_);
|
||||
|
||||
registers.flags.inverse_interrupt = 0;
|
||||
if constexpr (is_65c02(model)) registers.flags.decimal = 0;
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, --registers.s);
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, --registers.s);
|
||||
access(BusOperation::Read, Stack(registers.s), Storage::operand_, --registers.s);
|
||||
|
||||
set_interrupt_flag();
|
||||
access(BusOperation::Read, Vector(0xfc), registers.pc.halves.low);
|
||||
access(BusOperation::Read, Vector(0xfd), registers.pc.halves.high);
|
||||
goto fetch_decode;
|
||||
|
||||
@@ -121,9 +121,6 @@ struct Registers {
|
||||
Flags flags;
|
||||
|
||||
auto operator <=> (const Registers &) const = default;
|
||||
|
||||
uint8_t dec_s() { return s--; }
|
||||
uint8_t inc_s() { return ++s; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user