diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index b55b3596f..1c4bcbe5d 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -544,11 +544,6 @@ template void Proces break; } continue; - case CycleAddXToAddressLowRead: - next_address_.full = address_.full + x_; - address_.halves.low = next_address_.halves.low; - page_crossing_stall_read(); - break; case CycleAddYToAddressLow: next_address_.full = address_.full + y_; address_.halves.low = next_address_.halves.low; @@ -557,13 +552,36 @@ template void Proces break; } continue; + +#undef page_crossing_stall_read + + case CycleAddXToAddressLowRead: + next_address_.full = address_.full + x_; + address_.halves.low = next_address_.halves.low; + + // Cf. https://groups.google.com/g/comp.sys.apple2/c/RuTGaRxu5Iw/m/uyFLEsF8ceIJ + // + // STA abs,X has been fixed for the PX (page-crossing) case by adding a dummy read of the + // program counter, so the change was rW -> W. In the non-PX case it still reads the destination + // address, so there is no change: RW -> RW. + if(!is_65c02(personality) || next_address_.full == address_.full) { + throwaway_read(address_.full); + } else { + throwaway_read(pc_.full - 1); + } + break; case CycleAddYToAddressLowRead: next_address_.full = address_.full + y_; address_.halves.low = next_address_.halves.low; - page_crossing_stall_read(); - break; -#undef page_crossing_stall_read + // A similar rule as for above applies; this one adjusts (abs, y) addressing. + + if(!is_65c02(personality) || next_address_.full == address_.full) { + throwaway_read(address_.full); + } else { + throwaway_read(pc_.full - 1); + } + break; case OperationCorrectAddressHigh: // Preserve the uncorrected address in next_address_ (albeit that it's diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 1bb88d5c9..34d49afc7 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -346,11 +346,14 @@ ProcessorStorage::ProcessorStorage(Personality personality) { } // Correct JMP (abs) and install JMP (abs, x). + // + // Guess: JMP (abs, x), being listed at a fixed 6 cycles, uses the slower abs,x of INC and DEC. Install(0x6c, Program(CycleReadAddressHLoadAddressL, CycleReadPCLFromAddress, CycleReadPCHFromAddressLowInc, CycleReadPCHFromAddressFixed)); Install(0x7c, Program( CycleReadAddressHLoadAddressL, // (3) read second byte of (addr) - CycleAddXToAddressLowRead, // (4) calculate addr+x, read from (addr+x) with high byte not yet calculated - OperationCorrectAddressHigh, CycleReadPCLFromAddress, // (5) read from real (addr+x) + CycleAddXToAddressLowRead, + OperationCorrectAddressHigh, // (4) read from incorrectly-calculated address + CycleReadPCLFromAddress, // (5) read from real (addr+x) CycleReadPCHFromAddressInc // (6) read from addr+x+1 )); diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index 5984e4c27..47f5c206c 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -71,12 +71,19 @@ class ProcessorStorage { 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 - 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; 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; 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; 6502: schedules a throwaway read from address_; 65C02: schedules a throaway read from PC-1 + 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 throwaway read from PC-1 + 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 throwaway read from PC-1 OperationCorrectAddressHigh, // copies next_address_ to address_ + // 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 throwaway read from PC-1 if a page boundary was crossed; + // otherwise does as per the 6502. + // + CycleAddXToAddressLowRead, + CycleAddYToAddressLowRead, // As per CycleAddXToAddressLowRead, but uses Y rather than X. + OperationIncrementPC, // increments the PC CycleFetchOperandFromAddress, // fetches operand_ from address_ CycleWriteOperandToAddress, // writes operand_ to address_