From bdc1136b965aeff227eb8ef8ccfb74f4158c1fe3 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 3 Oct 2020 21:30:24 -0400 Subject: [PATCH] Edges towards working short absolute addressing mode. --- .../Implementation/65816Implementation.hpp | 52 ++++++++++++++++++- .../65816/Implementation/65816Storage.hpp | 36 +++++++++---- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/Processors/65816/Implementation/65816Implementation.hpp b/Processors/65816/Implementation/65816Implementation.hpp index b85ac3779..e9ca6dee9 100644 --- a/Processors/65816/Implementation/65816Implementation.hpp +++ b/Processors/65816/Implementation/65816Implementation.hpp @@ -52,7 +52,7 @@ template void Processor::run_for(const Cycles case CycleFetchIncrementPC: case CycleFetchOpcode: bus_address = pc_ | program_bank_; - bus_value = instruction_buffer_.next(); + bus_value = instruction_buffer_.next_input(); bus_operation = (operation == CycleFetchOpcode) ? MOS6502Esque::ReadOpcode : MOS6502Esque::Read; // TODO: split this action when I'm happy that my route to bus accesses is settled, to avoid repeating the conditional // embedded into the `switch`. @@ -65,6 +65,43 @@ template void Processor::run_for(const Cycles bus_operation = MOS6502Esque::Read; break; + // + // Data fetches and stores. + // + + case CycleFetchData: + bus_address = data_address_; + bus_value = data_buffer_.next_input(); + bus_operation = MOS6502Esque::Read; + break; + + case CycleFetchIncrementData: + bus_address = data_address_; + bus_value = data_buffer_.next_input(); + bus_operation = MOS6502Esque::Read; + ++data_address_; + break; + + case CycleStoreData: + bus_address = data_address_; + bus_value = data_buffer_.next_output(); + bus_operation = MOS6502Esque::Read; + break; + + case CycleStoreIncrementData: + bus_address = data_address_; + bus_value = data_buffer_.next_output(); + bus_operation = MOS6502Esque::Read; + ++data_address_; + break; + + case CycleStoreDecrementData: + bus_address = data_address_; + bus_value = data_buffer_.next_output(); + bus_operation = MOS6502Esque::Read; + --data_address_; + break; + // // Data movement. // @@ -78,6 +115,14 @@ template void Processor::run_for(const Cycles data_buffer_ = instruction_buffer_; break; + // + // Address construction. + // + + case OperationConstructAbsolute: + data_address_ = instruction_buffer_.value | data_bank_; + break; + // // Performance. // @@ -118,6 +163,11 @@ template void Processor::run_for(const Cycles #undef LD + case STA: + data_buffer_.value = a_.full & m_masks_[1]; + data_buffer_.size = 2 - mx_flags_[0]; + break; + default: assert(false); } diff --git a/Processors/65816/Implementation/65816Storage.hpp b/Processors/65816/Implementation/65816Storage.hpp index 680f42d18..514447606 100644 --- a/Processors/65816/Implementation/65816Storage.hpp +++ b/Processors/65816/Implementation/65816Storage.hpp @@ -204,7 +204,7 @@ struct ProcessorStorage { // Flags aplenty. uint8_t carry_flag_, negative_result_, zero_result_, decimal_flag_, overflow_flag_, inverse_interrupt_flag_ = 0; - uint8_t mx_flags_[2] = {1, 1}; // [0] = m; [1] = x. In both cases either `0` or `1`. + uint8_t mx_flags_[2] = {1, 1}; // [0] = m; [1] = x. In both cases either `0` or `1`; `1` => 8-bit. uint16_t m_masks_[2] = {0xff00, 0x00ff}; // [0] = src mask; [1] = dst mask. uint16_t x_masks_[2] = {0xff00, 0x00ff}; // [0] = src mask; [1] = dst mask. int instruction_offset_ = 0; @@ -228,24 +228,42 @@ struct ProcessorStorage { struct Buffer { uint32_t value = 0; int size = 0; + int read = 0; void clear() { value = 0; size = 0; + read = 0; } - uint8_t *next() { - #if TARGET_RT_BIG_ENDIAN - uint8_t *const target = reinterpret_cast(&value) + (3 ^ size); - #else - uint8_t *const target = reinterpret_cast(&value) + size; - #endif - + uint8_t *next_input() { + uint8_t *const next = byte(size); ++size; - return target; + return next; } + + uint8_t *next_output() { + uint8_t *const next = byte(read); + ++read; + return next; + } + + uint8_t *next_stack() { + --size; + return byte(size); + } + + private: + uint8_t *byte(int pointer) { + #if TARGET_RT_BIG_ENDIAN + return reinterpret_cast(&value) + (3 ^ pointer); + #else + return reinterpret_cast(&value) + pointer; + #endif + } }; Buffer instruction_buffer_, data_buffer_; + uint32_t data_address_; std::vector micro_ops_; MicroOp *next_op_ = nullptr;