From b7ba0d43277d50154ad56b9d1ffbbda350d8ec22 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 5 Oct 2020 17:04:57 -0400 Subject: [PATCH] Attempts to complete all addressing modes. So, if bugs didn't exist, it'd just be members of the Operation enum to go. --- .../Implementation/65816Implementation.hpp | 73 +++++++++++++++++-- .../65816/Implementation/65816Storage.cpp | 8 +- .../65816/Implementation/65816Storage.hpp | 43 ++++++++--- 3 files changed, 101 insertions(+), 23 deletions(-) diff --git a/Processors/65816/Implementation/65816Implementation.hpp b/Processors/65816/Implementation/65816Implementation.hpp index 866748c82..50844b09c 100644 --- a/Processors/65816/Implementation/65816Implementation.hpp +++ b/Processors/65816/Implementation/65816Implementation.hpp @@ -166,12 +166,30 @@ template void Processor::run_for(const Cycles data_buffer_ = instruction_buffer_; break; + case OperationCopyAToData: + if(mx_flags_[0]) { + data_buffer_.size = 1; + data_buffer_.value = a_.halves.high; + } else { + data_buffer_.size = 2; + data_buffer_.value = a_.full; + } + break; + + case OperationCopyDataToA: + if(mx_flags_[0]) { + a_.halves.high = data_buffer_.value; + } else { + a_.full = data_buffer_.value; + } + break; + // // Address construction. // case OperationConstructAbsolute: - data_address_ = instruction_buffer_.value | data_bank_; + data_address_ = instruction_buffer_.value + data_bank_; break; case OperationConstructAbsoluteIndexedIndirect: @@ -179,13 +197,13 @@ template void Processor::run_for(const Cycles break; case OperationConstructAbsoluteLongX: - data_address_ = instruction_buffer_.value + x(); + data_address_ = (instruction_buffer_.value + x()) & 0xffff + instruction_buffer_.value & 0xff0000; break; case OperationConstructAbsoluteXRead: case OperationConstructAbsoluteX: - data_address_ = ((instruction_buffer_.value + x()) & 0xffff) | data_bank_; - incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) | data_bank_; + data_address_ = ((instruction_buffer_.value + x()) & 0xffff) + data_bank_; + incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) + data_bank_; // If the incorrect address isn't actually incorrect, skip its usage. if(operation == OperationConstructAbsoluteXRead && data_address_ == incorrect_data_address_) { @@ -195,8 +213,8 @@ template void Processor::run_for(const Cycles case OperationConstructAbsoluteYRead: case OperationConstructAbsoluteY: - data_address_ = ((instruction_buffer_.value + y()) & 0xffff) | data_bank_; - incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) | data_bank_; + data_address_ = ((instruction_buffer_.value + y()) & 0xffff) + data_bank_; + incorrect_data_address_ = (data_address_ & 0xff) + (instruction_buffer_.value & 0xff00) + data_bank_; // If the incorrect address isn't actually incorrect, skip its usage. if(operation == OperationConstructAbsoluteYRead && data_address_ == incorrect_data_address_) { @@ -225,6 +243,45 @@ template void Processor::run_for(const Cycles } break; + case OperationConstructDirectIndirectIndexedLong: + // TODO: assumed here is that the low 16-bit calculation can't carry into + // the high byte. Test this! + data_address_ = (y() + instruction_buffer_.value) & 0xffff + instruction_buffer_.value & 0xff0000; + break; + + case OperationConstructDirectIndirectLong: + data_address_ = instruction_buffer_.value; + break; + + case OperationConstructDirectX: + data_address_ = (direct_ + x()) & 0xffff; + incorrect_data_address_ = (direct_ & 0xff00) + (data_address_ & 0x00ff); + if(!(direct_&0xff)) { + ++next_op_; + } + break; + + case OperationConstructDirectY: + data_address_ = (direct_ + y()) & 0xffff; + incorrect_data_address_ = (direct_ & 0xff00) + (data_address_ & 0x00ff); + if(!(direct_&0xff)) { + ++next_op_; + } + break; + + case OperationConstructPER: + data_buffer_.value = instruction_buffer_.value + pc_; + data_buffer_.size = 2; + break; + + case OperationConstructStackRelative: + data_address_ = (s_.full + instruction_buffer_.value) & 0xffff; + break; + + case OperationConstructStackRelativeIndexedIndirect: + data_address_ = data_bank_ + (instruction_buffer_.value + y()) & 0xffff; + break; + // // Performance. // @@ -315,8 +372,8 @@ template void Processor::run_for(const Cycles } break; - default: - assert(false); +// default: +// assert(false); } number_of_cycles -= bus_handler_.perform_bus_operation(bus_operation, bus_address, bus_value); diff --git a/Processors/65816/Implementation/65816Storage.cpp b/Processors/65816/Implementation/65816Storage.cpp index c57ca6ee1..2439f2189 100644 --- a/Processors/65816/Implementation/65816Storage.cpp +++ b/Processors/65816/Implementation/65816Storage.cpp @@ -424,21 +424,17 @@ struct CPU::WDC65816::ProcessorStorageConstructor { static void direct_indirect_indexed(AccessType type, bool is8bit, const std::function &target) { target(CycleFetchIncrementPC); // DO. - target(OperationConstructDirectIndirect); + target(OperationConstructDirect); target(CycleFetchPC); // IO. target(CycleFetchIncrementData); // AAL. target(CycleFetchData); // AAH. - target(OperationConstructDirectIndirectIndexed); + target(OperationConstructAbsoluteYRead); target(CycleFetchIncorrectDataAddress); // IO. read_write(type, is8bit, target); } - // TODO: verify, especially re: false addresses. - // i.e. it currently looks to me superficially as though I can reuse - // OperationConstructDirectIndirect here, but writing the proper - // interpreter will help to clarify. // 14. Direct Indirect Indexed Long; [d], y. static void direct_indirect_indexed_long(AccessType type, bool is8bit, const std::function &target) { diff --git a/Processors/65816/Implementation/65816Storage.hpp b/Processors/65816/Implementation/65816Storage.hpp index 0baa015ba..b0e12ccdd 100644 --- a/Processors/65816/Implementation/65816Storage.hpp +++ b/Processors/65816/Implementation/65816Storage.hpp @@ -22,9 +22,6 @@ enum MicroOp: uint8_t { /// of the instruction buffer, throwing the result away. CycleFetchIncorrectDataAddress, - /// Fetches a vector (i.e. IRQ, NMI, etc) into the data buffer. - CycleFetchVector, - // Dedicated block-move cycles; these use the data buffer as an intermediary. CycleFetchBlockX, CycleFetchBlockY, @@ -44,11 +41,15 @@ enum MicroOp: uint8_t { /// Pulls a single byte to the data buffer from the stack. CyclePull, - /// Sets the data address by copying the final two bytes of the instruction buffer. + /// Sets the data address by copying the final two bytes of the instruction buffer and + /// using the data register as a high byte. OperationConstructAbsolute, - /// Sets the data address to the result of (a, x). - /// TODO: explain better once implemented. + + /// Sets the data address to the 16-bit result of adding x to the value in the instruction buffer. OperationConstructAbsoluteIndexedIndirect, + + /// Sets the data address to the 24-bit result of adding x to the low 16-bits of the value in the + /// instruction buffer and retaining the highest 8-bits as specified. OperationConstructAbsoluteLongX, /// Calculates an a, x address; if: @@ -68,19 +69,40 @@ enum MicroOp: uint8_t { /// Skips the next micro-op if the low byte of the direct register is 0. OperationConstructDirect, - // These follow similar skip-one-if-possible logic to OperationConstructDirect. + /// Constructs the current direct indexed indirect address using the data bank, + /// direct and x registers plus the value currently in the instruction buffer. + /// Skips the next micro-op if the low byte of the direct register is 0. OperationConstructDirectIndexedIndirect, + + /// Constructs the current direct indexed indirect address using the data bank and + /// direct registers plus the value currently in the instruction buffer. + /// Skips the next micro-op if the low byte of the direct register is 0. OperationConstructDirectIndirect, - OperationConstructDirectIndirectIndexed, + + /// Adds y to the low 16-bits currently in the instruction buffer and appends a high 8-bits + /// also from the instruction buffer. OperationConstructDirectIndirectIndexedLong, + + /// Uses the 24-bit address currently in the instruction buffer. OperationConstructDirectIndirectLong, + + /// Adds the x register to the direct register to produce a 16-bit address; + /// skips the next micro-op if the low byte of the direct register is 0. OperationConstructDirectX, + + /// Adds the y register to the direct register to produce a 16-bit address; + /// skips the next micro-op if the low byte of the direct register is 0. OperationConstructDirectY, + /// Adds the instruction buffer to the program counter, making a 16-bit result, + /// *and stores it into the data buffer*. OperationConstructPER, - OperationConstructBRK, + /// Adds the stack pointer to the instruction buffer to produce a 16-bit address. OperationConstructStackRelative, + + /// Adds y to the value in the instruction buffer to produce a 16-bit result and + /// prefixes the current data bank. OperationConstructStackRelativeIndexedIndirect, /// Performs whatever operation goes with this program. @@ -93,7 +115,10 @@ enum MicroOp: uint8_t { /// Copies the current PBR to the data buffer. OperationCopyPBRToData, + /// Copies A to the data buffer. OperationCopyAToData, + + /// Copies the data buffer to A. OperationCopyDataToA, /// Fills the data buffer with three or four bytes, depending on emulation mode, containing the program