From 37a20e125c443ac639cb4466dbb62448e07fea91 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 15 Jan 2021 22:47:52 -0500 Subject: [PATCH] Completes the M50740 decoder. Completely untested. --- InstructionSets/M50740/Decoder.cpp | 31 ++++++++++++++++--- InstructionSets/M50740/Decoder.hpp | 5 ++-- InstructionSets/M50740/Instruction.hpp | 41 ++++++++++++++++++-------- 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/InstructionSets/M50740/Decoder.cpp b/InstructionSets/M50740/Decoder.cpp index 03be2f5e4..c43dc34e7 100644 --- a/InstructionSets/M50740/Decoder.cpp +++ b/InstructionSets/M50740/Decoder.cpp @@ -8,6 +8,8 @@ #include "Decoder.hpp" +#include + namespace InstructionSet { namespace M50740 { @@ -21,6 +23,7 @@ std::pair Decoder::decode(const uint8_ switch(instruction) { default: + consumed_ = 0; return std::make_pair(1, Instruction()); #define Map(opcode, operation, addressing_mode) case opcode: instr_ = Instruction(Operation::operation, AddressingMode::addressing_mode); break @@ -236,11 +239,31 @@ std::pair Decoder::decode(const uint8_ #undef Map } - // TODO: can I build these into the AddressingMode constants, to avoid the switch? - switch(instr_.addressing_mode) { - default: operand_size_ = 0; break; - } + operand_size_ = size(instr_.addressing_mode); + phase_ = operand_size_ ? Phase::AwaitingOperand : Phase::ReadyToPost; + operand_bytes_ = 0; + } + if(phase_ == Phase::AwaitingOperand && source != end) { + const int outstanding_bytes = operand_size_ - operand_bytes_; + const int bytes_to_consume = std::min(int(end - source), outstanding_bytes); + + consumed_ += bytes_to_consume; + source += bytes_to_consume; + operand_bytes_ += bytes_to_consume; + + if(operand_size_ == operand_bytes_) { + phase_ = Phase::ReadyToPost; + } else { + return std::make_pair(-(operand_size_ - operand_bytes_), Instruction()); + } + } + + if(phase_ == Phase::ReadyToPost) { + const auto result = std::make_pair(consumed_, instr_); + consumed_ = 0; + phase_ = Phase::Instruction; + return result; } return std::make_pair(0, Instruction()); diff --git a/InstructionSets/M50740/Decoder.hpp b/InstructionSets/M50740/Decoder.hpp index 68bdd3396..01b5aa1e6 100644 --- a/InstructionSets/M50740/Decoder.hpp +++ b/InstructionSets/M50740/Decoder.hpp @@ -24,9 +24,10 @@ class Decoder { private: enum class Phase { Instruction, - AwaitingOperand + AwaitingOperand, + ReadyToPost } phase_ = Phase::Instruction; - int operand_size_ = 0; + int operand_size_ = 0, operand_bytes_ = 0; int consumed_ = 0; Instruction instr_; }; diff --git a/InstructionSets/M50740/Instruction.hpp b/InstructionSets/M50740/Instruction.hpp index 552d4e2d5..126232cd4 100644 --- a/InstructionSets/M50740/Instruction.hpp +++ b/InstructionSets/M50740/Instruction.hpp @@ -15,20 +15,12 @@ namespace InstructionSet { namespace M50740 { enum class AddressingMode { - Implied, - Accumulator, - Immediate, - Absolute, - AbsoluteX, - AbsoluteY, - ZeroPage, - ZeroPageX, - ZeroPageY, - XIndirect, - IndirectY, + Implied, Accumulator, Immediate, + Absolute, AbsoluteX, AbsoluteY, + ZeroPage, ZeroPageX, ZeroPageY, + XIndirect, IndirectY, Relative, - AbsoluteIndirect, - ZeroPageIndirect, + AbsoluteIndirect, ZeroPageIndirect, SpecialPage, ImmediateZeroPage, @@ -45,6 +37,29 @@ enum class AddressingMode { Bit4ZeroPageRelative, Bit5ZeroPageRelative, Bit6ZeroPageRelative, Bit7ZeroPageRelative, }; +inline int size(AddressingMode mode) { + // This is coupled to the AddressingMode list above; be careful! + constexpr int sizes[] = { + 0, 0, 0, + 2, 2, 2, + 1, 1, 1, + 1, 1, + 1, + 2, 1, + 1, + 2, + 0, 0, 0, 0, + 0, 0, 0, 0, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 2, 2, 2, 2, + 2, 2, 2, 2, + }; + return sizes[int(mode)]; +} + enum class Operation: uint8_t { Invalid,