1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-28 22:30:30 +00:00

Revokes stack-local storage non-optimisation.

This commit is contained in:
Thomas Harte 2020-10-15 21:03:10 -04:00
parent 7aa6cf4c6b
commit 9a2f32795f
2 changed files with 35 additions and 49 deletions

View File

@ -13,16 +13,6 @@
*/ */
template <Personality personality, typename T, bool uses_ready_line> void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) { template <Personality personality, typename T, bool uses_ready_line> void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
uint8_t throwaway_target;
// These plus program below act to give the compiler permission to update these values
// without touching the class storage (i.e. it explicitly says they need be completely up
// to date in this stack frame only); which saves some complicated addressing
RegisterPair16 nextAddress = next_address_;
BusOperation nextBusOperation = next_bus_operation_;
uint16_t busAddress = bus_address_;
uint8_t *busValue = bus_value_;
#define checkSchedule() \ #define checkSchedule() \
if(!scheduled_program_counter_) {\ if(!scheduled_program_counter_) {\
if(interrupt_requests_) {\ if(interrupt_requests_) {\
@ -43,8 +33,8 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
#define bus_access() \ #define bus_access() \
interrupt_requests_ = (interrupt_requests_ & ~InterruptRequestFlags::IRQ) | irq_request_history_; \ interrupt_requests_ = (interrupt_requests_ & ~InterruptRequestFlags::IRQ) | irq_request_history_; \
irq_request_history_ = irq_line_ & flags_.inverse_interrupt; \ irq_request_history_ = irq_line_ & flags_.inverse_interrupt; \
number_of_cycles -= bus_handler_.perform_bus_operation(nextBusOperation, busAddress, busValue); \ number_of_cycles -= bus_handler_.perform_bus_operation(next_bus_operation_, bus_address_, bus_value_); \
nextBusOperation = BusOperation::None; \ next_bus_operation_ = BusOperation::None; \
if(number_of_cycles <= Cycles(0)) break; if(number_of_cycles <= Cycles(0)) break;
checkSchedule(); checkSchedule();
@ -54,12 +44,12 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// Deal with a potential RDY state, if this 6502 has anything connected to ready. // Deal with a potential RDY state, if this 6502 has anything connected to ready.
while(uses_ready_line && ready_is_active_ && number_of_cycles > Cycles(0)) { while(uses_ready_line && ready_is_active_ && number_of_cycles > Cycles(0)) {
number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, busAddress, busValue); number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, bus_address_, bus_value_);
} }
// Deal with a potential STP state, if this 6502 implements STP. // Deal with a potential STP state, if this 6502 implements STP.
while(has_stpwai(personality) && stop_is_active_ && number_of_cycles > Cycles(0)) { while(has_stpwai(personality) && stop_is_active_ && number_of_cycles > Cycles(0)) {
number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, busAddress, busValue); number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, bus_address_, bus_value_);
if(interrupt_requests_ & InterruptRequestFlags::Reset) { if(interrupt_requests_ & InterruptRequestFlags::Reset) {
stop_is_active_ = false; stop_is_active_ = false;
checkSchedule(); checkSchedule();
@ -69,7 +59,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
// Deal with a potential WAI state, if this 6502 implements WAI. // Deal with a potential WAI state, if this 6502 implements WAI.
while(has_stpwai(personality) && wait_is_active_ && number_of_cycles > Cycles(0)) { while(has_stpwai(personality) && wait_is_active_ && number_of_cycles > Cycles(0)) {
number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, busAddress, busValue); number_of_cycles -= bus_handler_.perform_bus_operation(BusOperation::Ready, bus_address_, bus_value_);
interrupt_requests_ |= (irq_line_ & flags_.inverse_interrupt); interrupt_requests_ |= (irq_line_ & flags_.inverse_interrupt);
if(interrupt_requests_ & InterruptRequestFlags::NMI || irq_line_) { if(interrupt_requests_ & InterruptRequestFlags::NMI || irq_line_) {
wait_is_active_ = false; wait_is_active_ = false;
@ -79,7 +69,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
} }
if((!uses_ready_line || !ready_is_active_) && (!has_stpwai(personality) || (!wait_is_active_ && !stop_is_active_))) { if((!uses_ready_line || !ready_is_active_) && (!has_stpwai(personality) || (!wait_is_active_ && !stop_is_active_))) {
if(nextBusOperation != BusOperation::None) { if(next_bus_operation_ != BusOperation::None) {
bus_access(); bus_access();
} }
@ -88,10 +78,10 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
const MicroOp cycle = *scheduled_program_counter_; const MicroOp cycle = *scheduled_program_counter_;
scheduled_program_counter_++; scheduled_program_counter_++;
#define read_op(val, addr) nextBusOperation = BusOperation::ReadOpcode; busAddress = addr; busValue = &val; val = 0xff #define read_op(val, addr) next_bus_operation_ = BusOperation::ReadOpcode; bus_address_ = addr; bus_value_ = &val; val = 0xff
#define read_mem(val, addr) nextBusOperation = BusOperation::Read; busAddress = addr; busValue = &val; val = 0xff #define read_mem(val, addr) next_bus_operation_ = BusOperation::Read; bus_address_ = addr; bus_value_ = &val; val = 0xff
#define throwaway_read(addr) nextBusOperation = BusOperation::Read; busAddress = addr; busValue = &throwaway_target; throwaway_target = 0xff #define throwaway_read(addr) next_bus_operation_ = BusOperation::Read; bus_address_ = addr; bus_value_ = &bus_throwaway_; bus_throwaway_ = 0xff
#define write_mem(val, addr) nextBusOperation = BusOperation::Write; busAddress = addr; busValue = &val #define write_mem(val, addr) next_bus_operation_ = BusOperation::Write; bus_address_ = addr; bus_value_ = &val
switch(cycle) { switch(cycle) {
@ -155,17 +145,17 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
case OperationBRKPickVector: case OperationBRKPickVector:
if(is_65c02(personality)) { if(is_65c02(personality)) {
nextAddress.full = 0xfffe; next_address_.full = 0xfffe;
} else { } else {
// NMI can usurp BRK-vector operations on the pre-C 6502s. // NMI can usurp BRK-vector operations on the pre-C 6502s.
nextAddress.full = (interrupt_requests_ & InterruptRequestFlags::NMI) ? 0xfffa : 0xfffe; next_address_.full = (interrupt_requests_ & InterruptRequestFlags::NMI) ? 0xfffa : 0xfffe;
interrupt_requests_ &= ~InterruptRequestFlags::NMI; interrupt_requests_ &= ~InterruptRequestFlags::NMI;
} }
continue; continue;
case OperationNMIPickVector: nextAddress.full = 0xfffa; continue; case OperationNMIPickVector: next_address_.full = 0xfffa; continue;
case OperationRSTPickVector: nextAddress.full = 0xfffc; continue; case OperationRSTPickVector: next_address_.full = 0xfffc; continue;
case CycleReadVectorLow: read_mem(pc_.halves.low, nextAddress.full); break; case CycleReadVectorLow: read_mem(pc_.halves.low, next_address_.full); break;
case CycleReadVectorHigh: read_mem(pc_.halves.high, nextAddress.full+1); break; case CycleReadVectorHigh: read_mem(pc_.halves.high, next_address_.full+1); break;
case OperationSetIRQFlags: case OperationSetIRQFlags:
flags_.inverse_interrupt = 0; flags_.inverse_interrupt = 0;
if(is_65c02(personality)) flags_.decimal = 0; if(is_65c02(personality)) flags_.decimal = 0;
@ -464,36 +454,36 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
} }
case CycleAddXToAddressLow: case CycleAddXToAddressLow:
nextAddress.full = address_.full + x_; next_address_.full = address_.full + x_;
address_.halves.low = nextAddress.halves.low; address_.halves.low = next_address_.halves.low;
if(address_.halves.high != nextAddress.halves.high) { if(address_.halves.high != next_address_.halves.high) {
page_crossing_stall_read(); page_crossing_stall_read();
break; break;
} }
continue; continue;
case CycleAddXToAddressLowRead: case CycleAddXToAddressLowRead:
nextAddress.full = address_.full + x_; next_address_.full = address_.full + x_;
address_.halves.low = nextAddress.halves.low; address_.halves.low = next_address_.halves.low;
page_crossing_stall_read(); page_crossing_stall_read();
break; break;
case CycleAddYToAddressLow: case CycleAddYToAddressLow:
nextAddress.full = address_.full + y_; next_address_.full = address_.full + y_;
address_.halves.low = nextAddress.halves.low; address_.halves.low = next_address_.halves.low;
if(address_.halves.high != nextAddress.halves.high) { if(address_.halves.high != next_address_.halves.high) {
page_crossing_stall_read(); page_crossing_stall_read();
break; break;
} }
continue; continue;
case CycleAddYToAddressLowRead: case CycleAddYToAddressLowRead:
nextAddress.full = address_.full + y_; next_address_.full = address_.full + y_;
address_.halves.low = nextAddress.halves.low; address_.halves.low = next_address_.halves.low;
page_crossing_stall_read(); page_crossing_stall_read();
break; break;
#undef page_crossing_stall_read #undef page_crossing_stall_read
case OperationCorrectAddressHigh: case OperationCorrectAddressHigh:
address_.full = nextAddress.full; address_.full = next_address_.full;
continue; continue;
case CycleIncrementPCFetchAddressLowFromOperand: case CycleIncrementPCFetchAddressLowFromOperand:
pc_.full++; pc_.full++;
@ -573,12 +563,12 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
#undef BRA #undef BRA
case CycleAddSignedOperandToPC: case CycleAddSignedOperandToPC:
nextAddress.full = uint16_t(pc_.full + int8_t(operand_)); next_address_.full = uint16_t(pc_.full + int8_t(operand_));
pc_.halves.low = nextAddress.halves.low; pc_.halves.low = next_address_.halves.low;
if(nextAddress.halves.high != pc_.halves.high) { if(next_address_.halves.high != pc_.halves.high) {
uint16_t halfUpdatedPc = pc_.full; const uint16_t half_updated_pc = pc_.full;
pc_.full = nextAddress.full; pc_.full = next_address_.full;
throwaway_read(halfUpdatedPc); throwaway_read(half_updated_pc);
break; break;
} else if(is_65c02(personality)) { } else if(is_65c02(personality)) {
// 65C02 modification to all branches: a branch that is taken but requires only a single cycle // 65C02 modification to all branches: a branch that is taken but requires only a single cycle
@ -650,7 +640,7 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
if(has_stpwai(personality) && (stop_is_active_ || wait_is_active_)) { if(has_stpwai(personality) && (stop_is_active_ || wait_is_active_)) {
break; break;
} }
if(uses_ready_line && ready_line_is_enabled_ && (is_65c02(personality) || isReadOperation(nextBusOperation))) { if(uses_ready_line && ready_line_is_enabled_ && (is_65c02(personality) || isReadOperation(next_bus_operation_))) {
ready_is_active_ = true; ready_is_active_ = true;
break; break;
} }
@ -660,11 +650,6 @@ template <Personality personality, typename T, bool uses_ready_line> void Proces
} }
cycles_left_to_run_ = number_of_cycles; cycles_left_to_run_ = number_of_cycles;
next_address_ = nextAddress;
next_bus_operation_ = nextBusOperation;
bus_address_ = busAddress;
bus_value_ = busValue;
bus_handler_.flush(); bus_handler_.flush();
} }

View File

@ -243,6 +243,7 @@ class ProcessorStorage {
BusOperation next_bus_operation_ = BusOperation::None; BusOperation next_bus_operation_ = BusOperation::None;
uint16_t bus_address_; uint16_t bus_address_;
uint8_t *bus_value_; uint8_t *bus_value_;
static inline uint8_t bus_throwaway_;
/*! /*!
Gets the flags register. Gets the flags register.