Initial implementation of register machine emulator.

This commit is contained in:
2019-11-17 19:52:52 +00:00
commit be80b6383c
6 changed files with 180 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
Session.vim
Emulator
build/*
.undodir
.ccls
.tup/*

12
Tupfile Normal file
View 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
View 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
View 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
View 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
View 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);