commit be80b6383cd9d5aef01903f73afb75b282fd2e42 Author: Michael Kuc Date: Sun Nov 17 19:52:52 2019 +0000 Initial implementation of register machine emulator. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48c20bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +Session.vim +Emulator +build/* +.undodir +.ccls +.tup/* diff --git a/Tupfile b/Tupfile new file mode 100644 index 0000000..acda183 --- /dev/null +++ b/Tupfile @@ -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) diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 0000000..cbd9bb8 --- /dev/null +++ b/src/.clang-format @@ -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 + +... diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..631215a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,81 @@ +#include "register.hpp" +#include +#include +#include + +Register& getOrDefault(std::map& 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 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(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(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& mapping, const RegIndex& lookup) { + auto valueIter = mapping.try_emplace(lookup, Register{ 0 }); + return valueIter.first->second; +} diff --git a/src/register.cpp b/src/register.cpp new file mode 100644 index 0000000..1da8f93 --- /dev/null +++ b/src/register.cpp @@ -0,0 +1,43 @@ +#include "register.hpp" + +template <> +std::pair toPair(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 toPair(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 toList(Register unsplit) { + std::vector list{}; + + while (unsplit != 0) { + const auto splitPair = toPair(unsplit); + unsplit = splitPair.second; + list.push_back(splitPair.first); + } + + return list; +} diff --git a/src/register.hpp b/src/register.hpp new file mode 100644 index 0000000..5b081b7 --- /dev/null +++ b/src/register.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + +using Register = mpz_class; +using RegIndex = uint16_t; + +template +std::pair toPair(Register unsplit); + +std::vector toList(Register unsplit);