diff --git a/Processors/65816/Implementation/65816Implementation.hpp b/Processors/65816/Implementation/65816Implementation.hpp index 08902279b..0279aae40 100644 --- a/Processors/65816/Implementation/65816Implementation.hpp +++ b/Processors/65816/Implementation/65816Implementation.hpp @@ -410,6 +410,13 @@ template void Processorprogram_offsets[0]]; + continue; } else if(pending_exceptions_ & NMI) { pending_exceptions_ &= ~NMI; data_address_ = registers_.emulation_flag ? 0xfffa : 0xffea; diff --git a/Processors/65816/Implementation/65816Storage.cpp b/Processors/65816/Implementation/65816Storage.cpp index 0909cf79a..a0ab803a6 100644 --- a/Processors/65816/Implementation/65816Storage.cpp +++ b/Processors/65816/Implementation/65816Storage.cpp @@ -70,11 +70,16 @@ struct CPU::WDC65816::ProcessorStorageConstructor { ++opcode; } - void set_exception_generator(Generator generator) { + void set_exception_generator(Generator generator, Generator reset_tail_generator) { const auto map_entry = install(generator); storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].program_offsets[0] = storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].program_offsets[1] = uint16_t(map_entry->second.first); storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].operation = JMPind; + + const auto reset_tail_entry = install(reset_tail_generator); + storage_.instructions[size_t(ProcessorStorage::OperationSlot::ResetTail)].program_offsets[0] = + storage_.instructions[size_t(ProcessorStorage::OperationSlot::ResetTail)].program_offsets[1] = uint16_t(reset_tail_entry->second.first); + storage_.instructions[size_t(ProcessorStorage::OperationSlot::ResetTail)].operation = JMPind; } void install_fetch_decode_execute() { @@ -597,8 +602,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor { target(CycleFetchPCThrowaway); // IO. target(CycleFetchPCThrowaway); // IO. - target(OperationPrepareException); // Populates the data buffer; this skips a micro-op if - // in emulation mode. + target(OperationPrepareException); // Populates the data buffer; if the exception is a + // reset then switches to the reset tail program. + // Otherwise skips a micro-op if in emulation mode. target(CyclePush); // PBR [skipped in emulation mode]. target(CyclePush); // PCH. @@ -611,6 +617,20 @@ struct CPU::WDC65816::ProcessorStorageConstructor { target(OperationPerform); // Jumps to the vector address. } + static void reset_tail(AccessType, bool, const std::function &target) { + // The reset program still walks through three stack accesses as if it were doing + // the usual exception stack activity, but forces them to reads that don't modify + // the stack pointer. Here they are: + target(CycleAccessStack); // PCH. + target(CycleAccessStack); // PCL. + target(CycleAccessStack); // P. + + target(CycleFetchIncrementVector); // AAVL. + target(CycleFetchVector); // AAVH. + + target(OperationPerform); // Jumps to the vector address. + } + // 22b. Stack; s, PLx. static void stack_pull(AccessType, bool is8bit, const std::function &target) { target(CycleFetchPCThrowaway); // IO. @@ -1027,7 +1047,7 @@ ProcessorStorage::ProcessorStorage() { /* 0xff SBC al, x */ op(absolute_long_x, SBC); #undef op - constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception); + constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception, &ProcessorStorageConstructor::reset_tail); constructor.install_fetch_decode_execute(); // Find any OperationMoveToNextProgram. diff --git a/Processors/65816/Implementation/65816Storage.hpp b/Processors/65816/Implementation/65816Storage.hpp index 532433f87..77a137672 100644 --- a/Processors/65816/Implementation/65816Storage.hpp +++ b/Processors/65816/Implementation/65816Storage.hpp @@ -241,14 +241,16 @@ struct ProcessorStorage { /// So the program to perform is that at @c program_offsets[mx_flags[size_field]] uint8_t size_field = 0; }; - Instruction instructions[256 + 2]; // Arranged as: + Instruction instructions[256 + 3]; // Arranged as: // 256 entries: instructions; - // the entry for 'exceptions' (i.e. reset, irq, nmi); and + // the entry for 'exceptions' (i.e. reset, irq, nmi); + // a duplicate entry for the final part of exceptions if the selected exception is a reset; and // the entry for fetch-decode-execute. enum class OperationSlot { Exception = 256, - FetchDecodeExecute + ResetTail, + FetchDecodeExecute, }; // A helper for testing.