Initial implementation of register machine emulator.
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Session.vim
|
||||||
|
Emulator
|
||||||
|
build/*
|
||||||
|
.undodir
|
||||||
|
.ccls
|
||||||
|
.tup/*
|
||||||
12
Tupfile
Normal file
12
Tupfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CXX = g++
|
||||||
|
CXXFLAGS = -pedantic -std=c++17 -Wall -Wno-unused-parameter -Wno-reorder -Wno-sign-compare -Wno-address -Wno-noexcept-type -Wno-unknown-attributes -Wno-unknown-warning-option
|
||||||
|
CPPFLAGS =
|
||||||
|
LDFLAGS =
|
||||||
|
LIBS = -lgmpxx -lgmp
|
||||||
|
|
||||||
|
SRC_DIR = src
|
||||||
|
BUILD_DIR = build
|
||||||
|
PROG = Emulator
|
||||||
|
|
||||||
|
: foreach $(SRC_DIR)/*.cpp |> $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c %f -o %o |> $(BUILD_DIR)/%B.o
|
||||||
|
: $(BUILD_DIR)/*.o |> $(CXX) %f $(LDFLAGS) $(LIBS) -o %o |> $(PROG)
|
||||||
25
src/.clang-format
Normal file
25
src/.clang-format
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: llvm
|
||||||
|
IndentWidth: 4
|
||||||
|
---
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
ColumnLimit: 100
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
Language: Cpp
|
||||||
|
NamespaceIndentation: All
|
||||||
|
PointerAlignment: Left
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: ForIndentation
|
||||||
|
|
||||||
|
...
|
||||||
81
src/main.cpp
Normal file
81
src/main.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include "register.hpp"
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
Register& getOrDefault(std::map<RegIndex, Register>& mapping, const RegIndex& lookup);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
const constexpr size_t registerIndexPadding = 6;
|
||||||
|
bool executing = true;
|
||||||
|
|
||||||
|
std::cout << "Please enter the program" << std::endl;
|
||||||
|
|
||||||
|
RegIndex pc = 0;
|
||||||
|
Register reg;
|
||||||
|
std::map<RegIndex, Register> registers{};
|
||||||
|
|
||||||
|
std::cin >> reg;
|
||||||
|
auto registerStates = toList(reg);
|
||||||
|
|
||||||
|
std::cout << "\nRegister states at startup:\n";
|
||||||
|
RegIndex i = 0;
|
||||||
|
|
||||||
|
for (; i < registerStates.size(); i++) {
|
||||||
|
const auto registerState = registerStates[i];
|
||||||
|
|
||||||
|
registers.insert(std::make_pair(i, registerState));
|
||||||
|
std::cout << std::setw(registerIndexPadding) << i << ": " << registerState << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::setw(registerIndexPadding) << i << ": 0...\n\n";
|
||||||
|
std::cout << "Beginning Execution..." << std::endl;
|
||||||
|
|
||||||
|
registers.insert(std::make_pair(pc, reg));
|
||||||
|
|
||||||
|
while (executing) {
|
||||||
|
std::cout << "L" << pc << "\t";
|
||||||
|
Register instruction = getOrDefault(registers, pc);
|
||||||
|
|
||||||
|
if (instruction == 0) { /* HALT instruction. */
|
||||||
|
std::cout << "HALT" << std::endl;
|
||||||
|
executing = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto splitInstruction = toPair<false>(instruction);
|
||||||
|
|
||||||
|
if (splitInstruction.first % 2 == 0) { /* R+ instruction */
|
||||||
|
RegIndex sourceRegisterIndex = splitInstruction.first.get_ui();
|
||||||
|
RegIndex destinationLabel = splitInstruction.second.get_ui();
|
||||||
|
|
||||||
|
std::cout << "R" << sourceRegisterIndex << u8"\u207a \u21a3 " << destinationLabel
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
getOrDefault(registers, sourceRegisterIndex)++;
|
||||||
|
pc = destinationLabel;
|
||||||
|
} else {
|
||||||
|
RegIndex sourceRegisterIndex = splitInstruction.first.get_ui();
|
||||||
|
|
||||||
|
auto branches = toPair<true>(splitInstruction.second);
|
||||||
|
RegIndex trueLabel = branches.first.get_ui();
|
||||||
|
RegIndex falseLabel = branches.second.get_ui();
|
||||||
|
|
||||||
|
std::cout << "R" << sourceRegisterIndex << "\u207b \u21a3 " << trueLabel << ", "
|
||||||
|
<< falseLabel << "\n";
|
||||||
|
|
||||||
|
auto& sourceRegister = getOrDefault(registers, sourceRegisterIndex);
|
||||||
|
|
||||||
|
if (sourceRegister > 0) {
|
||||||
|
sourceRegister--;
|
||||||
|
pc = trueLabel;
|
||||||
|
} else
|
||||||
|
pc = falseLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Register& getOrDefault(std::map<RegIndex, Register>& mapping, const RegIndex& lookup) {
|
||||||
|
auto valueIter = mapping.try_emplace(lookup, Register{ 0 });
|
||||||
|
return valueIter.first->second;
|
||||||
|
}
|
||||||
43
src/register.cpp
Normal file
43
src/register.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include "register.hpp"
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<Register, Register> toPair<false>(Register unsplit) {
|
||||||
|
Register x = 0;
|
||||||
|
|
||||||
|
/* Skip to the first 1 bit in representation */
|
||||||
|
while (unsplit % 2 != 1) {
|
||||||
|
unsplit >>= 1;
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsplit >>= 1;
|
||||||
|
|
||||||
|
return std::make_pair(x, unsplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::pair<Register, Register> toPair<true>(Register unsplit) {
|
||||||
|
Register x = 0;
|
||||||
|
|
||||||
|
/* Skip past the first 1 bits in representation */
|
||||||
|
while (unsplit % 2 == 1) {
|
||||||
|
unsplit >>= 1;
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsplit >>= 1;
|
||||||
|
|
||||||
|
return std::make_pair(x, unsplit);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Register> toList(Register unsplit) {
|
||||||
|
std::vector<Register> list{};
|
||||||
|
|
||||||
|
while (unsplit != 0) {
|
||||||
|
const auto splitPair = toPair<false>(unsplit);
|
||||||
|
unsplit = splitPair.second;
|
||||||
|
list.push_back(splitPair.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
13
src/register.hpp
Normal file
13
src/register.hpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <gmpxx.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using Register = mpz_class;
|
||||||
|
using RegIndex = uint16_t;
|
||||||
|
|
||||||
|
template <bool mapZero>
|
||||||
|
std::pair<Register, Register> toPair(Register unsplit);
|
||||||
|
|
||||||
|
std::vector<Register> toList(Register unsplit);
|
||||||
Reference in New Issue
Block a user