From 67c2ce2174d5928cd1c72eb7c9f15782ed2a5e96 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 26 Sep 2020 21:20:01 -0400 Subject: [PATCH] Takes a run at completing the stack section. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not really sure about BRK though — does it gain a signature on the 65816? --- .../65816/Implementation/65816Storage.cpp | 56 ++++++++++++++++--- .../65816/Implementation/65816Storage.hpp | 9 +++ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Processors/65816/Implementation/65816Storage.cpp b/Processors/65816/Implementation/65816Storage.cpp index 2977db29e..8497b9065 100644 --- a/Processors/65816/Implementation/65816Storage.cpp +++ b/Processors/65816/Implementation/65816Storage.cpp @@ -553,19 +553,20 @@ struct CPU::WDC65816::ProcessorStorageConstructor { } // 22a. Stack; s, abort/irq/nmi/res. - static void stack_exception(AccessType, bool is8bit, const std::function &target) { + static void stack_exception(AccessType, bool, const std::function &target) { target(CycleFetchPC); // IO target(CycleFetchPC); // IO - target(OperationPrepareException); // Populates the data buffer. + target(OperationPrepareException); // Populates the data buffer; this skips a micro-op if + // in emulation mode. - if(!is8bit) target(CyclePush); // PBR + target(CyclePush); // PBR [skipped in emulation mode] target(CyclePush); // PCH target(CyclePush); // PCL target(CyclePush); // P target(CycleFetchIncrementData); // AAVL - target(CycleFetchIncrementData); // AAVH + target(CycleFetchData); // AAVH target(OperationPerform); // Jumps to the vector address. } @@ -625,9 +626,46 @@ struct CPU::WDC65816::ProcessorStorageConstructor { } // 22g. Stack; s, RTI. + static void stack_rti(AccessType, bool is8bit, const std::function &target) { + target(CycleFetchIncrementPC); // IO + target(CycleFetchIncrementPC); // IO + + target(CyclePull); // P + target(CyclePull); // New PCL + target(CyclePull); // New PCH + if(!is8bit) target(CyclePull); // PBR + + target(OperationPerform); // [RTI] — to unpack the fields above. + } + // 22h. Stack; s, RTS. + static void stack_rts(AccessType, bool, const std::function &target) { + target(CycleFetchIncrementPC); // IO + target(CycleFetchIncrementPC); // IO + + target(CyclePull); // PCL + target(CyclePull); // PCH + target(CycleAccessStack); // IO + + target(OperationPerform); // [JMP, to perform the RTS] + } + // 22i. Stack; s, RTL. + static void stack_rtl(AccessType, bool, const std::function &target) { + target(CycleFetchIncrementPC); // IO + target(CycleFetchIncrementPC); // IO + + target(CyclePull); // New PCL + target(CyclePull); // New PCH + target(CyclePull); // New PBR + + target(OperationPerform); // [JML, to perform the RTL] + } + // 22j. Stack; s, BRK/COP. + + // Covered by stack_exception. + // 23. Stack Relative; d, s. // 24. Stack Relative Indirect Indexed (d, s), y. }; @@ -641,9 +679,9 @@ ProcessorStorage::ProcessorStorage() { // Install the instructions. #define op(x, y) constructor.install(&ProcessorStorageConstructor::x, y) - /* 0x00 BRK s */ + /* 0x00 BRK s */ op(stack_exception, BRK); /* 0x01 ORA (d, x) */ op(direct_indexed_indirect, ORA); - /* 0x02 COP s */ + /* 0x02 COP s */ op(stack_exception, BRK); /* 0x03 ORA d, s */ /* 0x04 TSB d */ op(direct_rmw, TSB); /* 0x05 ORA d */ op(direct, ORA); @@ -709,7 +747,7 @@ ProcessorStorage::ProcessorStorage() { /* 0x3e ROL a, x */ op(absolute_x_rmw, ROL); /* 0x3f AND al, x */ op(absolute_long_x, AND); - /* 0x40 RTI s */ + /* 0x40 RTI s */ op(stack_rti, RTI); /* 0x41 EOR (d, x) */ op(direct_indexed_indirect, EOR); /* 0x42 WDM i */ /* 0x43 EOR d, s */ @@ -743,7 +781,7 @@ ProcessorStorage::ProcessorStorage() { /* 0x5e LSR a, x */ op(absolute_x_rmw, LSR); /* 0x5f EOR al, x */ op(absolute_long_x, EOR); - /* 0x60 RTS s */ + /* 0x60 RTS s */ op(stack_rts, JMP); // [sic]; loads the PC from data as per an RTS. /* 0x61 ADC (d, x) */ op(direct_indexed_indirect, ADC); /* 0x62 PER s */ op(stack_per, NOP); /* 0x63 ADC d, s */ @@ -754,7 +792,7 @@ ProcessorStorage::ProcessorStorage() { /* 0x68 PLA s */ op(stack_pull, LDA); /* 0x69 ADC # */ op(immediate, ADC); /* 0x6a ROR A */ op(accumulator, ROR); - /* 0x6b RTL s */ + /* 0x6b RTL s */ op(stack_rtl, JML); /* 0x6c JMP (a) */ op(absolute_indirect_jmp, JMP); /* 0x6d ADC a */ op(absolute, ADC); /* 0x6e ROR a */ op(absolute_rmw, ROR); diff --git a/Processors/65816/Implementation/65816Storage.hpp b/Processors/65816/Implementation/65816Storage.hpp index 16bfbabbd..d2c7f8839 100644 --- a/Processors/65816/Implementation/65816Storage.hpp +++ b/Processors/65816/Implementation/65816Storage.hpp @@ -79,6 +79,7 @@ enum MicroOp: uint8_t { OperationConstructDirectY, OperationConstructPER, + OperationConstructBRK, /// Performs whatever operation goes with this program. OperationPerform, @@ -136,6 +137,10 @@ enum Operation: uint8_t { STP, WAI, + // These unpack values from the data buffer, which has been filled + // from the stack. + RTI, RTL, + /// Loads the PC with the operand from the data buffer. JMP, @@ -149,6 +154,10 @@ enum Operation: uint8_t { /// Loads the PC and the PBR with the operand from the data buffer, /// replacing it with the old PC (and only the PC; PBR not included). JSL, + + /// i.e. jump to vector. TODO: is this really distinct from JMP? I'm assuming so for now, + /// as I assume the PBR is implicitly modified. We'll see. + BRK, }; class ProcessorStorageConstructor;