From c35dca783f37d781ae4f5537f345f662e3522b2c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 15 Aug 2018 18:47:53 -0400 Subject: [PATCH] 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. --- .../Implementation/6502Implementation.hpp | 20 ++++++++++++++----- .../6502/Implementation/6502Storage.hpp | 14 +++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 62b860078..ed67b32d8 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -436,32 +436,42 @@ if(number_of_cycles <= Cycles(0)) break; // 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: nextAddress.full = address_.full + x_; address_.bytes.low = nextAddress.bytes.low; - if(address_.bytes.high != nextAddress.bytes.high) { - throwaway_read(address_.full); + if(address_.bytes.high != nextAddress.bytes.high) { + page_crossing_stall_read(); break; } continue; case CycleAddXToAddressLowRead: nextAddress.full = address_.full + x_; address_.bytes.low = nextAddress.bytes.low; - throwaway_read(address_.full); + page_crossing_stall_read(); break; case CycleAddYToAddressLow: nextAddress.full = address_.full + y_; address_.bytes.low = nextAddress.bytes.low; if(address_.bytes.high != nextAddress.bytes.high) { - throwaway_read(address_.full); + page_crossing_stall_read(); break; } continue; case CycleAddYToAddressLowRead: nextAddress.full = address_.full + y_; address_.bytes.low = nextAddress.bytes.low; - throwaway_read(address_.full); + page_crossing_stall_read(); break; + +#undef page_crossing_stall_read + case OperationCorrectAddressHigh: address_.full = nextAddress.full; continue; diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index 248076a47..9dadc45d2 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -17,10 +17,12 @@ class ProcessorStorage { protected: ProcessorStorage(Personality); - /* + /*! 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). + + This micro-instruction set was put together in a fairly ad hoc fashion, I'm afraid, so is unlikely to be optimal. */ enum MicroOp { 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 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_ - 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_ - CycleAddXToAddressLowRead, // calculates address_ + x 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; 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; 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 OperationCorrectAddressHigh, // copies next_address_ to address_ OperationIncrementPC, // increments the PC