1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-07 23:25:00 +00:00

Completes the M50740 decoder.

Completely untested.
This commit is contained in:
Thomas Harte
2021-01-15 22:47:52 -05:00
parent 2910faf963
commit 37a20e125c
3 changed files with 58 additions and 19 deletions

View File

@@ -8,6 +8,8 @@
#include "Decoder.hpp" #include "Decoder.hpp"
#include <algorithm>
namespace InstructionSet { namespace InstructionSet {
namespace M50740 { namespace M50740 {
@@ -21,6 +23,7 @@ std::pair<int, InstructionSet::M50740::Instruction> Decoder::decode(const uint8_
switch(instruction) { switch(instruction) {
default: default:
consumed_ = 0;
return std::make_pair(1, Instruction()); return std::make_pair(1, Instruction());
#define Map(opcode, operation, addressing_mode) case opcode: instr_ = Instruction(Operation::operation, AddressingMode::addressing_mode); break #define Map(opcode, operation, addressing_mode) case opcode: instr_ = Instruction(Operation::operation, AddressingMode::addressing_mode); break
@@ -236,11 +239,31 @@ std::pair<int, InstructionSet::M50740::Instruction> Decoder::decode(const uint8_
#undef Map #undef Map
} }
// TODO: can I build these into the AddressingMode constants, to avoid the switch? operand_size_ = size(instr_.addressing_mode);
switch(instr_.addressing_mode) { phase_ = operand_size_ ? Phase::AwaitingOperand : Phase::ReadyToPost;
default: operand_size_ = 0; break; 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()); return std::make_pair(0, Instruction());

View File

@@ -24,9 +24,10 @@ class Decoder {
private: private:
enum class Phase { enum class Phase {
Instruction, Instruction,
AwaitingOperand AwaitingOperand,
ReadyToPost
} phase_ = Phase::Instruction; } phase_ = Phase::Instruction;
int operand_size_ = 0; int operand_size_ = 0, operand_bytes_ = 0;
int consumed_ = 0; int consumed_ = 0;
Instruction instr_; Instruction instr_;
}; };

View File

@@ -15,20 +15,12 @@ namespace InstructionSet {
namespace M50740 { namespace M50740 {
enum class AddressingMode { enum class AddressingMode {
Implied, Implied, Accumulator, Immediate,
Accumulator, Absolute, AbsoluteX, AbsoluteY,
Immediate, ZeroPage, ZeroPageX, ZeroPageY,
Absolute, XIndirect, IndirectY,
AbsoluteX,
AbsoluteY,
ZeroPage,
ZeroPageX,
ZeroPageY,
XIndirect,
IndirectY,
Relative, Relative,
AbsoluteIndirect, AbsoluteIndirect, ZeroPageIndirect,
ZeroPageIndirect,
SpecialPage, SpecialPage,
ImmediateZeroPage, ImmediateZeroPage,
@@ -45,6 +37,29 @@ enum class AddressingMode {
Bit4ZeroPageRelative, Bit5ZeroPageRelative, Bit6ZeroPageRelative, Bit7ZeroPageRelative, 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 { enum class Operation: uint8_t {
Invalid, Invalid,