1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Ensures that page-crossing indexing no longer causes an extra read of an invalid address on the 65C02.

It rereads the last byte of the instruction stream instead.
This commit is contained in:
Thomas Harte 2018-08-15 18:47:53 -04:00
parent 901e0d65b9
commit c35dca783f
2 changed files with 23 additions and 11 deletions

View File

@ -436,32 +436,42 @@ if(number_of_cycles <= Cycles(0)) break;
// MARK: - Addressing Mode Work // MARK: - Addressing Mode Work
#define page_crossing_stall_read() \
if(is_65c02(personality)) { \
throwaway_read(pc_.full - 1); \
} else { \
throwaway_read(address_.full); \
}
case CycleAddXToAddressLow: case CycleAddXToAddressLow:
nextAddress.full = address_.full + x_; nextAddress.full = address_.full + x_;
address_.bytes.low = nextAddress.bytes.low; address_.bytes.low = nextAddress.bytes.low;
if(address_.bytes.high != nextAddress.bytes.high) { if(address_.bytes.high != nextAddress.bytes.high) {
throwaway_read(address_.full); page_crossing_stall_read();
break; break;
} }
continue; continue;
case CycleAddXToAddressLowRead: case CycleAddXToAddressLowRead:
nextAddress.full = address_.full + x_; nextAddress.full = address_.full + x_;
address_.bytes.low = nextAddress.bytes.low; address_.bytes.low = nextAddress.bytes.low;
throwaway_read(address_.full); page_crossing_stall_read();
break; break;
case CycleAddYToAddressLow: case CycleAddYToAddressLow:
nextAddress.full = address_.full + y_; nextAddress.full = address_.full + y_;
address_.bytes.low = nextAddress.bytes.low; address_.bytes.low = nextAddress.bytes.low;
if(address_.bytes.high != nextAddress.bytes.high) { if(address_.bytes.high != nextAddress.bytes.high) {
throwaway_read(address_.full); page_crossing_stall_read();
break; break;
} }
continue; continue;
case CycleAddYToAddressLowRead: case CycleAddYToAddressLowRead:
nextAddress.full = address_.full + y_; nextAddress.full = address_.full + y_;
address_.bytes.low = nextAddress.bytes.low; address_.bytes.low = nextAddress.bytes.low;
throwaway_read(address_.full); page_crossing_stall_read();
break; break;
#undef page_crossing_stall_read
case OperationCorrectAddressHigh: case OperationCorrectAddressHigh:
address_.full = nextAddress.full; address_.full = nextAddress.full;
continue; continue;

View File

@ -17,10 +17,12 @@ class ProcessorStorage {
protected: protected:
ProcessorStorage(Personality); ProcessorStorage(Personality);
/* /*!
This emulation functions by decomposing instructions into micro programs, consisting of the micro operations This emulation functions by decomposing instructions into micro programs, consisting of the micro operations
as per the enum below. Each micro op takes at most one cycle. By convention, those called CycleX take a cycle defined by MicroOp. Each micro op takes at most one cycle. By convention, those called CycleX take a cycle
to perform whereas those called OperationX occur for free (so, in effect, their cost is loaded onto the next cycle). to perform whereas those called OperationX occur for free (so, in effect, their cost is loaded onto the next cycle).
This micro-instruction set was put together in a fairly ad hoc fashion, I'm afraid, so is unlikely to be optimal.
*/ */
enum MicroOp { enum MicroOp {
CycleFetchOperation, // fetches (PC) to operation_, storing PC to last_operation_pc_ before incrementing it CycleFetchOperation, // fetches (PC) to operation_, storing PC to last_operation_pc_ before incrementing it
@ -72,10 +74,10 @@ class ProcessorStorage {
CycleLoadAddessZeroX, // copies (operand_+x)&0xff to address_, increments the PC, and reads from operand_, throwing away the result CycleLoadAddessZeroX, // copies (operand_+x)&0xff to address_, increments the PC, and reads from operand_, throwing away the result
CycleLoadAddessZeroY, // copies (operand_+y)&0xff to address_, increments the PC, and reads from operand_, throwing away the result CycleLoadAddessZeroY, // copies (operand_+y)&0xff to address_, increments the PC, and reads from operand_, throwing away the result
CycleAddXToAddressLow, // calculates address_ + x and stores it to next_address_; copies next_address_.l back to address_.l; if address_ now does not equal next_address_, schedules a throwaway read from address_ CycleAddXToAddressLow, // calculates address_ + x and stores it to next_address_; copies next_address_.l back to address_.l; 6502: if address_ now does not equal next_address_, schedules a throwaway read from address_; 65C02: schedules a throaway read from PC-1
CycleAddYToAddressLow, // calculates address_ + y and stores it to next_address_; copies next_address_.l back to address_.l; if address_ now does not equal next_address_, schedules a throwaway read from address_ CycleAddYToAddressLow, // calculates address_ + y and stores it to next_address_; copies next_address_.l back to address_.l; 6502: if address_ now does not equal next_address_, schedules a throwaway read from address_; 65C02: schedules a throaway read from PC-1
CycleAddXToAddressLowRead, // calculates address_ + x and stores it to next_address; copies next_address.l back to address_.l; schedules a throwaway read from address_ CycleAddXToAddressLowRead, // calculates address_ + x and stores it to next_address; copies next_address.l back to address_.l; 6502: schedules a throwaway read from address_; 65C02: schedules a throaway read from PC-1
CycleAddYToAddressLowRead, // calculates address_ + y and stores it to next_address; copies next_address.l back to address_.l; schedules a throwaway read from address_ CycleAddYToAddressLowRead, // calculates address_ + y and stores it to next_address; copies next_address.l back to address_.l; 6502: schedules a throwaway read from address_; 65C02: schedules a throaway read from PC-1
OperationCorrectAddressHigh, // copies next_address_ to address_ OperationCorrectAddressHigh, // copies next_address_ to address_
OperationIncrementPC, // increments the PC OperationIncrementPC, // increments the PC