code cleanup and fixes
This commit is contained in:
@@ -5,32 +5,35 @@
|
|||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "components/Alu.h"
|
#include "components/Alu.h"
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
Manager::~Manager() {
|
Manager::~Manager() {
|
||||||
|
std::cout << "Schließe Quellcode Datei: '" << m_path << "'" << "\n" << std::flush;
|
||||||
m_programFile.close();
|
m_programFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager *Manager::getInstance() {
|
Manager &Manager::getInstance() {
|
||||||
static Manager instance;
|
static Manager instance;
|
||||||
return &instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Manager::run() {
|
int Manager::run() {
|
||||||
if (!m_programFile.is_open()) {
|
if (!m_programFile.is_open()) {
|
||||||
std::cerr << "Bitte zuerst die init() Methode aufrufen!" << "\n" << std::flush;
|
std::cerr << "Bitte zuerst die init() Methode aufrufen!" << "\n" << std::flush;
|
||||||
}
|
}
|
||||||
ProgramLoader::getInstance()->indexFile(m_programFile);
|
ProgramLoader::getInstance().indexFile(m_programFile);
|
||||||
/// Die Position des Streams (virtueller Lesekopf) muss nach dem Indexen wieder zurückgesetzt werden
|
// Die Position des Streams (virtueller Lesekopf) muss nach dem Indexen wieder zurückgesetzt werden
|
||||||
m_programFile.clear();
|
m_programFile.clear();
|
||||||
m_programFile.seekg(0);
|
m_programFile.seekg(0);
|
||||||
|
|
||||||
|
// Bearbeite jede Zeile des Quellcodes in der ALU
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(m_programFile, line)) {
|
while (std::getline(m_programFile, line)) {
|
||||||
auto lineVector = ProgramLoader::parseLine(line);
|
auto lineVector = ProgramLoader::parseLine(line);
|
||||||
|
// Sollte die aktuelle Zeile leer sein, überspringe die ALU
|
||||||
if (lineVector.empty()) continue;
|
if (lineVector.empty()) continue;
|
||||||
Alu::calculate(lineVector);
|
Alu::calculate(lineVector);
|
||||||
}
|
}
|
||||||
@@ -48,11 +51,15 @@ std::streampos Manager::getStreamPosition() {
|
|||||||
void Manager::init(const std::string &program_path) {
|
void Manager::init(const std::string &program_path) {
|
||||||
m_path = program_path;
|
m_path = program_path;
|
||||||
std::cout << "Öffne Quellcode Datei: '" << m_path << "'" << "\n" << std::flush;
|
std::cout << "Öffne Quellcode Datei: '" << m_path << "'" << "\n" << std::flush;
|
||||||
|
|
||||||
|
//Überprüfe, ob die Datei existiert
|
||||||
if (!fs::exists(m_path)) {
|
if (!fs::exists(m_path)) {
|
||||||
std::cerr << "Datei existiert nicht: " << m_path << "\n" << std::flush;
|
std::cerr << "Datei existiert nicht: " << m_path << "\n" << std::flush;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_programFile.open(m_path);
|
m_programFile.open(m_path);
|
||||||
|
|
||||||
|
// Sollte die Datei nicht geöffnet worden sein, gib den Fehler aus
|
||||||
if (!m_programFile.is_open()) {
|
if (!m_programFile.is_open()) {
|
||||||
std::cerr << "Datei konnte nicht geöffnet werden: " << m_path << "\n" << std::flush;
|
std::cerr << "Datei konnte nicht geöffnet werden: " << m_path << "\n" << std::flush;
|
||||||
std::cerr << "fail (z.B. Zugriffsrechte): " << m_programFile.fail() << "\n" << std::flush;
|
std::cerr << "fail (z.B. Zugriffsrechte): " << m_programFile.fail() << "\n" << std::flush;
|
||||||
@@ -62,12 +69,14 @@ void Manager::init(const std::string &program_path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::streampos Manager::getNextStreamLineOffset() {
|
std::streampos Manager::getNextStreamLineOffset() {
|
||||||
/// Speichert das aktuelle stream offset
|
// Speichert das aktuelle stream offset
|
||||||
const auto positionBefore = m_programFile.tellg();
|
const auto positionBefore = m_programFile.tellg();
|
||||||
/// Geht eine Zeile nach vorne zum nächsten Befehl (PC+4) und speichert den offset
|
|
||||||
|
// Geht eine Zeile nach vorne zum nächsten Befehl (PC+4) und speichert den offset
|
||||||
gotoNextStreamLine();
|
gotoNextStreamLine();
|
||||||
const auto positionAfter = m_programFile.tellg();
|
const auto positionAfter = m_programFile.tellg();
|
||||||
/// Geht zum offset vom Anfang zurück und gibt die nächste Adresse (PC+4) zurück
|
|
||||||
|
// Geht zum offset vom Anfang zurück und gibt die nächste Adresse (PC+4) zurück
|
||||||
m_programFile.seekg(positionBefore);
|
m_programFile.seekg(positionBefore);
|
||||||
return positionAfter;
|
return positionAfter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
#include "ProgramLoader.h"
|
#include "ProgramLoader.h"
|
||||||
|
|
||||||
/// Die Manager Instanz sorgt für die Koordination von user input, Datei einlesen, code execution und anderen Aktionen.
|
// Die Manager Instanz sorgt für die Koordination von user input, Datei einlesen, code execution und anderen Aktionen.
|
||||||
|
|
||||||
class Manager {
|
class Manager {
|
||||||
private:
|
private:
|
||||||
/// Die Instanz des Managers soll mit einem immutable path zum Programm erstellt werden
|
// Die Instanz des Managers soll mit einem immutable path zum Programm erstellt werden
|
||||||
Manager() = default;
|
Manager() = default;
|
||||||
|
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
@@ -21,7 +21,7 @@ private:
|
|||||||
std::ifstream m_programFile;
|
std::ifstream m_programFile;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Singleton Logik
|
// Singleton Logik
|
||||||
Manager(const Manager &) = delete;
|
Manager(const Manager &) = delete;
|
||||||
|
|
||||||
Manager(const Manager &&) = delete;
|
Manager(const Manager &&) = delete;
|
||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return Die Singleton Instance des Managers
|
* @return Die Singleton Instance des Managers
|
||||||
*/
|
*/
|
||||||
static Manager *getInstance();
|
static Manager &getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Die Hauptmethode des Emulators.
|
* Die Hauptmethode des Emulators.
|
||||||
|
|||||||
@@ -5,44 +5,58 @@
|
|||||||
#include "ProgramLoader.h"
|
#include "ProgramLoader.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
ProgramLoader *ProgramLoader::getInstance() {
|
ProgramLoader &ProgramLoader::getInstance() {
|
||||||
static ProgramLoader instance;
|
static ProgramLoader instance;
|
||||||
return &instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::vector<std::string> ProgramLoader::parseLine(const std::string &input) {
|
[[nodiscard]] std::vector<std::string> ProgramLoader::parseLine(const std::string &input) {
|
||||||
|
// Sollte die aktuelle Zeile leer sein, gib einen leeren Vektor zurück
|
||||||
if (input.empty()) return std::vector<std::string>{};
|
if (input.empty()) return std::vector<std::string>{};
|
||||||
std::vector<std::string> output{};
|
std::vector<std::string> output{};
|
||||||
/// Konvertiere den Input String in einen IStringStream, damit dieser bei Leerzeichen gesplittet werden kann
|
// Konvertiere den Input String in einen IStringStream, damit dieser bei Leerzeichen gesplittet werden kann
|
||||||
std::istringstream iss(input);
|
std::istringstream iss(input);
|
||||||
std::string out;
|
std::string out;
|
||||||
do {
|
do {
|
||||||
out.clear();
|
out.clear();
|
||||||
/// Trenne den IStringStream bei jedem Leerzeichen und füge die Befehl(e)/-sargumente dem Output hinzu
|
|
||||||
|
// Trenne den IStringStream bei jedem Leerzeichen und füge die Befehl(e)/-sargumente dem Output hinzu
|
||||||
std::getline(iss, out, ' ');
|
std::getline(iss, out, ' ');
|
||||||
if (out.empty()) break;
|
if (out.empty()) break;
|
||||||
/// Stoppe, sobald ein Kommentar im Source Code vorkommt
|
|
||||||
|
// Entferne alle Leerzeichen hinter dem Befehl/Argument
|
||||||
|
while (out.at(out.length() - 1) == ' ') {
|
||||||
|
out.erase(out.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stoppe, sobald ein Kommentar im Source Code vorkommt
|
||||||
if (out.at(0) != '#') {
|
if (out.at(0) != '#') {
|
||||||
if (out.at(out.length() - 1) == ',') {
|
if (out.at(out.length() - 1) == ',') {
|
||||||
out.erase(out.length() - 1);
|
out.erase(out.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.push_back(out);
|
output.push_back(out);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (!out.empty());
|
} while (!out.empty());
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgramLoader::indexFile(std::ifstream &m_programFile) {
|
void ProgramLoader::indexFile(std::ifstream &m_programFile) {
|
||||||
|
// Setze den Lesekop zurück
|
||||||
m_programFile.clear();
|
m_programFile.clear();
|
||||||
m_programFile.seekg(0);
|
m_programFile.seekg(0);
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
/// Parse Zeile für Zeile
|
// Parse Zeile für Zeile
|
||||||
while (std::getline(m_programFile, line)) {
|
while (std::getline(m_programFile, line)) {
|
||||||
|
// Parst die aktuelle Zeile und springt zur nächsten, falls die aktuelle leer ist
|
||||||
auto lineVector = parseLine(line);
|
auto lineVector = parseLine(line);
|
||||||
if (lineVector.empty()) continue;
|
if (lineVector.empty()) continue;
|
||||||
/// Sobald ein Label gefunden wurde, speichere die Position des Streams
|
|
||||||
|
// Sobald ein Label gefunden wurde, speichere die Position des Streams
|
||||||
if (const auto first = lineVector.begin(); first->at(first->length() - 1) == ':') {
|
if (const auto first = lineVector.begin(); first->at(first->length() - 1) == ':') {
|
||||||
m_labels[first->substr(0, first->length() - 1)] = m_programFile.tellg();
|
m_labels[first->substr(0, first->length() - 1)] = m_programFile.tellg();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/// Der ProgramLoader, zuständig für das Lesen und Parsen des Quellcodes
|
// Der ProgramLoader, zuständig für das Lesen und Parsen des Quellcodes
|
||||||
|
|
||||||
class ProgramLoader {
|
class ProgramLoader {
|
||||||
private:
|
private:
|
||||||
@@ -21,7 +21,7 @@ private:
|
|||||||
std::map<std::string, std::streampos> m_labels;
|
std::map<std::string, std::streampos> m_labels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Singleton Logik
|
// Singleton Logik
|
||||||
ProgramLoader(const ProgramLoader &) = delete;
|
ProgramLoader(const ProgramLoader &) = delete;
|
||||||
|
|
||||||
ProgramLoader(const ProgramLoader &&) = delete;
|
ProgramLoader(const ProgramLoader &&) = delete;
|
||||||
@@ -35,7 +35,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return ProgramLoader Instanz
|
* @return ProgramLoader Instanz
|
||||||
*/
|
*/
|
||||||
static ProgramLoader *getInstance();
|
static ProgramLoader &getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parst eine Zeile des Assembly Codes und gibt diese als sortierten Vektor zurück
|
* Parst eine Zeile des Assembly Codes und gibt diese als sortierten Vektor zurück
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "Alu.h"
|
#include "Alu.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
@@ -13,6 +14,11 @@
|
|||||||
#include "../ProgramLoader.h"
|
#include "../ProgramLoader.h"
|
||||||
|
|
||||||
void Alu::calculate(const std::vector<std::string> &commandVector) {
|
void Alu::calculate(const std::vector<std::string> &commandVector) {
|
||||||
|
auto ® = Register::getInstance();
|
||||||
|
auto &mem = Memory::getInstance();
|
||||||
|
const auto &pl = ProgramLoader::getInstance();
|
||||||
|
auto &man = Manager::getInstance();
|
||||||
|
|
||||||
// Falls die aktuelle Zeile ein Label ist, return
|
// Falls die aktuelle Zeile ein Label ist, return
|
||||||
if (const auto length = commandVector.at(0).size(); commandVector.at(0).at(length - 1) == ':') {
|
if (const auto length = commandVector.at(0).size(); commandVector.at(0).at(length - 1) == ':') {
|
||||||
return;
|
return;
|
||||||
@@ -23,13 +29,16 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
|
|||||||
|
|
||||||
// Extrahiere die Argumente des Befehls
|
// Extrahiere die Argumente des Befehls
|
||||||
const auto arg1 = parseArgument(commandVector.at(1));
|
const auto arg1 = parseArgument(commandVector.at(1));
|
||||||
// Wandle Vektor[2] (das zweite Argument) nur um, falls es kein SW/LW Argument ist
|
|
||||||
|
// Wandle Vektor[2] (das zweite Argument) in eine Adresse um, falls es ein SW/LW Argument ist
|
||||||
int arg2 = 0;
|
int arg2 = 0;
|
||||||
if (commandVector.at(2).find('(') != std::string::npos) {
|
if (commandVector.at(2).find('(') != std::string::npos) {
|
||||||
arg2 = parseAddress(commandVector.at(2));
|
arg2 = parseAddress(commandVector.at(2));
|
||||||
} else {
|
} else {
|
||||||
|
// Ansonsten wandle es in ein Registerargument um
|
||||||
arg2 = parseArgument(commandVector.at(2));
|
arg2 = parseArgument(commandVector.at(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wandle Vektor[3] (das dritte Argument) nur um, falls dieser existiert und kein immediate Wert ist
|
// Wandle Vektor[3] (das dritte Argument) nur um, falls dieser existiert und kein immediate Wert ist
|
||||||
int arg3 = 0;
|
int arg3 = 0;
|
||||||
if (commandVector.size() > 3) {
|
if (commandVector.size() > 3) {
|
||||||
@@ -41,124 +50,126 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
|
|||||||
if (command == "add") {
|
if (command == "add") {
|
||||||
// Addition Befehl
|
// Addition Befehl
|
||||||
// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = reg.getRegister(arg3);
|
||||||
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 + register2;
|
const auto result = register1 + register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "sub") {
|
} else if (command == "sub") {
|
||||||
// Subtraktion Befehl
|
// Subtraktion Befehl
|
||||||
// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = reg.getRegister(arg3);
|
||||||
// Subtrahiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Subtrahiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 - register2;
|
const auto result = register1 - register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "and") {
|
} else if (command == "and") {
|
||||||
// Binärer und Befehl
|
// Binärer und Befehl
|
||||||
// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = reg.getRegister(arg3);
|
||||||
// Verknüpfe die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
// Verknüpfe die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 & register2;
|
const auto result = register1 & register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "or") {
|
} else if (command == "or") {
|
||||||
// Binärer oder Befehl
|
// Binärer oder Befehl
|
||||||
// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = reg.getRegister(arg3);
|
||||||
// Unterscheide die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
// Unterscheide die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 | register2;
|
const auto result = register1 | register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "xor") {
|
} else if (command == "xor") {
|
||||||
// Binärer exklusiver oder Befehl
|
// Binärer exklusiver oder Befehl
|
||||||
// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = reg.getRegister(arg3);
|
||||||
// Unterscheide die beiden Werte binär exklusiv und schreibe das Ergebnis ins angegebene Register zurück
|
// Unterscheide die beiden Werte binär exklusiv und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 ^ register2;
|
const auto result = register1 ^ register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "addi") {
|
} else if (command == "addi") {
|
||||||
// Immediate und Befehl
|
// Immediate und Befehl
|
||||||
// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto immediate = arg3;
|
const auto immediate = arg3;
|
||||||
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 + immediate;
|
const auto result = register1 + immediate;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "andi") {
|
} else if (command == "andi") {
|
||||||
// Binärer immediate und Befehl
|
// Binärer immediate und Befehl
|
||||||
// Hole Wert1 aus dem angegebnen Register und Wert2 aus dem Befehlsargument
|
// Hole Wert1 aus dem angegebnen Register und Wert2 aus dem Befehlsargument
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto immediate = arg3;
|
const auto immediate = arg3;
|
||||||
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 & immediate;
|
const auto result = register1 & immediate;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "ori") {
|
} else if (command == "ori") {
|
||||||
// Binärer immediate oder Befehl
|
// Binärer immediate oder Befehl
|
||||||
// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = reg.getRegister(arg2);
|
||||||
const auto immediate = arg3;
|
const auto immediate = arg3;
|
||||||
// Unterscheide beide Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
// Unterscheide beide Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 | immediate;
|
const auto result = register1 | immediate;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
reg.setRegister(arg1, result);
|
||||||
} else if (command == "lw") {
|
} else if (command == "lw") {
|
||||||
// Loadword Befehl
|
// Loadword Befehl
|
||||||
// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem RAM
|
// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem RAM
|
||||||
const auto address = arg2;
|
const auto address = arg2;
|
||||||
const auto data = Memory::getInstance()->load(address);
|
const auto data = mem.load(address);
|
||||||
// Speichere die Daten im angegeben Register
|
// Speichere die Daten im angegeben Register
|
||||||
Register::getInstance().setRegister(arg1, data);
|
reg.setRegister(arg1, data);
|
||||||
} else if (command == "sw") {
|
} else if (command == "sw") {
|
||||||
// Storeword Befehl
|
// Storeword Befehl
|
||||||
// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem Register
|
// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem Register
|
||||||
const auto address = arg2;
|
const auto address = arg2;
|
||||||
const auto data = Register::getInstance().getRegister(arg1);
|
const auto data = reg.getRegister(arg1);
|
||||||
// Speichere die Daten im angegeben RAM slot
|
// Speichere die Daten im angegeben RAM slot
|
||||||
Memory::getInstance()->store(address, data);
|
mem.store(address, data);
|
||||||
} else if (command == "beq") {
|
} else if (command == "beq") {
|
||||||
const auto register1 = Register::getInstance().getRegister(arg1);
|
const auto register1 = reg.getRegister(arg1);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg2);
|
const auto register2 = reg.getRegister(arg2);
|
||||||
const auto &label = commandVector.at(3);
|
const auto &label = commandVector.at(3);
|
||||||
const auto streamPos = ProgramLoader::getInstance()->getStreamPosition(label);
|
const auto streamPos = pl.getStreamPosition(label);
|
||||||
if (register1 == register2) {
|
if (register1 == register2) {
|
||||||
Manager::getInstance()->setStreamPosition(streamPos);
|
man.setStreamPosition(streamPos);
|
||||||
}
|
}
|
||||||
} else if (command == "bne") {
|
} else if (command == "bne") {
|
||||||
const auto register1 = Register::getInstance().getRegister(arg1);
|
const auto register1 = reg.getRegister(arg1);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg2);
|
const auto register2 = reg.getRegister(arg2);
|
||||||
const auto &label = commandVector.at(3);
|
const auto &label = commandVector.at(3);
|
||||||
const auto streamPos = ProgramLoader::getInstance()->getStreamPosition(label);
|
const auto streamPos = pl.getStreamPosition(label);
|
||||||
if (register1 != register2) {
|
if (register1 != register2) {
|
||||||
Manager::getInstance()->setStreamPosition(streamPos);
|
man.setStreamPosition(streamPos);
|
||||||
}
|
}
|
||||||
} else if (command == "jal") {
|
} else if (command == "jal") {
|
||||||
// Jump and link Befehl
|
// Jump and link Befehl
|
||||||
// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
||||||
// und führt zu undefiniertem Verhalten !!!
|
// und führt zu undefiniertem Verhalten !!!
|
||||||
// Speichert die Position des nächsten Befehls im angegebenen Register
|
// Speichert die Position des nächsten Befehls im angegebenen Register
|
||||||
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
|
const auto pos = static_cast<int>(man.getNextStreamLineOffset().operator std::streamoff());
|
||||||
Register::getInstance().setRegister(arg1, pos);
|
reg.setRegister(arg1, pos);
|
||||||
// Holt sich die Position des angegebenen labels und die stream Position auf diese
|
// Holt sich die Position des angegebenen labels und die stream Position auf diese
|
||||||
const auto &label = commandVector.at(2);
|
const auto &label = commandVector.at(2);
|
||||||
const auto streamPos = ProgramLoader::getInstance()->getStreamPosition(label);
|
const auto streamPos = pl.getStreamPosition(label);
|
||||||
Manager::getInstance()->setStreamPosition(streamPos);
|
man.setStreamPosition(streamPos);
|
||||||
} else if (command == "jalr") {
|
} else if (command == "jalr") {
|
||||||
// Jump and link register Befehl
|
// Jump and link register Befehl
|
||||||
// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
||||||
// und führt zu undefiniertem Verhalten !!!
|
// und führt zu undefiniertem Verhalten !!!
|
||||||
// Speichert die Position des nächsten Befehls im angegebenen Register
|
// Speichert die Position des nächsten Befehls im angegebenen Register
|
||||||
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
|
const auto pos = static_cast<int>(man.getNextStreamLineOffset().operator std::streamoff());
|
||||||
Register::getInstance().setRegister(arg1, pos);
|
reg.setRegister(arg1, pos);
|
||||||
// Holt sich die Position des angegebenen labels und das Offset aus dem angegebenen Register
|
// Holt sich die Position des angegebenen labels und das Offset aus dem angegebenen Register
|
||||||
const auto &label = commandVector.at(3);
|
const auto &label = commandVector.at(3);
|
||||||
const auto streamPosLabel = ProgramLoader::getInstance()->getStreamPosition(label);
|
const auto streamPosLabel = pl.getStreamPosition(label);
|
||||||
const auto posOffset = Register::getInstance().getRegister(arg2);
|
const auto posOffset = reg.getRegister(arg2);
|
||||||
// Setzt die stream Position auf den gegebenen Wert & erhöht sie um den angegebenen Offset
|
// Setzt die stream Position auf den gegebenen Wert & erhöht sie um den angegebenen Offset
|
||||||
Manager::getInstance()->setStreamPosition(streamPosLabel);
|
man.setStreamPosition(streamPosLabel);
|
||||||
for (int i = 0; i < posOffset; ++i) {
|
for (int i = 0; i < posOffset; ++i) {
|
||||||
Manager::getInstance()->gotoNextStreamLine();
|
man.gotoNextStreamLine();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Befehl " << command << " wurde nicht gefunden!";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +199,7 @@ bool Alu::isRegister(const std::string &argument) {
|
|||||||
// Entfernt das voranstehende 'x' und checkt, ob darauf etwas folgt
|
// Entfernt das voranstehende 'x' und checkt, ob darauf etwas folgt
|
||||||
const std::string numberPart = argument.substr(1);
|
const std::string numberPart = argument.substr(1);
|
||||||
if (numberPart.empty()) return false;
|
if (numberPart.empty()) return false;
|
||||||
|
|
||||||
// Überprüfe, ob alle Zeichen im restlichen Argument Nummern sind
|
// Überprüfe, ob alle Zeichen im restlichen Argument Nummern sind
|
||||||
for (const char c: numberPart) {
|
for (const char c: numberPart) {
|
||||||
if (!std::isdigit(c)) return false;
|
if (!std::isdigit(c)) return false;
|
||||||
@@ -199,6 +211,7 @@ bool Alu::isRegister(const std::string &argument) {
|
|||||||
|
|
||||||
bool Alu::isImmediate(const std::string &argument) {
|
bool Alu::isImmediate(const std::string &argument) {
|
||||||
if (argument.empty()) return false;
|
if (argument.empty()) return false;
|
||||||
|
|
||||||
constexpr size_t start = 0;
|
constexpr size_t start = 0;
|
||||||
// Überprüfe, ob jedes Zeichen im Argument eine Nummer ista
|
// Überprüfe, ob jedes Zeichen im Argument eine Nummer ista
|
||||||
for (size_t i = start; i < argument.size(); ++i) {
|
for (size_t i = start; i < argument.size(); ++i) {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ Memory::Memory() {
|
|||||||
m_memory = {0};
|
m_memory = {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory *Memory::getInstance() {
|
Memory &Memory::getInstance() {
|
||||||
static Memory instance;
|
static Memory instance;
|
||||||
return &instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::store(const int address, const int value) {
|
void Memory::store(const int address, const int value) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return Memory Instanz
|
* @return Memory Instanz
|
||||||
*/
|
*/
|
||||||
static Memory *getInstance();
|
static Memory &getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Speichert den angegebenen Wert an der angegebenen Adresse im Hauptspeicher
|
* Speichert den angegebenen Wert an der angegebenen Adresse im Hauptspeicher
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
Manager::getInstance()->init(
|
Manager::getInstance().init(
|
||||||
"/home/black/Nextcloud/Dokumente/Dokumente/Hochschule/2. Semester/Rechnerarchitektur/Projekt/test.txt"
|
"/home/black/Nextcloud/Dokumente/Dokumente/Hochschule/2. Semester/Rechnerarchitektur/Projekt/test.txt"
|
||||||
);
|
);
|
||||||
Manager::getInstance()->run();
|
Manager::getInstance().run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user