added "jalr" command

This commit is contained in:
black
2025-07-08 20:31:11 +02:00
parent 4fdaf3dafa
commit bc77fae7ee
6 changed files with 77 additions and 10 deletions

View File

@@ -27,11 +27,15 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
int arg2 = 0;
if (commandVector.at(2).find('(') != std::string::npos) {
arg2 = parseAddress(commandVector.at(2));
} else {
arg2 = parseArgument(commandVector.at(2));
}
/// Wandle Vektor[3] (das dritte Argument) nur um, falls dieser existiert
/// Wandle Vektor[3] (das dritte Argument) nur um, falls dieser existiert und kein immediate Wert ist
int arg3 = 0;
if (commandVector.size() > 3 && isdigit(commandVector.at(3).at(1))) {
arg3 = parseArgument(commandVector.at(3));
if (commandVector.size() > 3) {
if (const std::string &arg = commandVector.at(3); isRegister(arg) || isImmediate(arg)) {
arg3 = parseArgument(arg);
}
}
if (command == "add") {
@@ -138,14 +142,24 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
Register::getInstance().setRegister(arg1, pos);
Manager::getInstance()->setStreamPosition(streamPos);
} else if (command == "jalr") {
/// Jump and link register Befehl
/// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
/// und führt zu undefiniertem Verhalten !!!
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
const auto &label = commandVector.at(3);
const auto streamPosLabel = ProgramLoader::getInstance()->getStreamPosition(label);
const auto posOffset = Register::getInstance().getRegister(arg2);
Register::getInstance().setRegister(arg1, pos);
Manager::getInstance()->setStreamPosition(streamPosLabel);
for (int i = 0; i < posOffset; ++i) {
Manager::getInstance()->gotoNextStreamLine();
}
}
}
int Alu::parseArgument(std::string argument) {
/// Falls das erste Argument ein Register ist, entferne das führende "x"
if (argument.at(0) == 'x') {
argument = argument.substr(1, argument.length() - 1);
}
if (argument.at(0) == 'x') argument = argument.substr(1);
/// Da das Argument noch als String vorliegt, muss es in ein int umgewandelt werden
return std::stoi(argument);
}
@@ -162,3 +176,28 @@ int Alu::parseAddress(const std::string &argument) {
}
return 0;
}
bool Alu::isRegister(const std::string &argument) {
/// Überprüfe, ob das nichtleere Argument mit 'x' startet
if (argument.empty() || argument.at(0) != 'x') return false;
/// Entfernt das voranstehende 'x' und checkt, ob darauf etwas folgt
const std::string numberPart = argument.substr(1);
if (numberPart.empty()) return false;
/// Überprüfe, ob alle Zeichen im restlichen Argument Nummern sind
for (const char c: numberPart) {
if (!std::isdigit(c)) return false;
}
/// Konvertiere zu int und überprüfe, ob es ein Register zwischen inklusive x0 und x32 ist
const int regNum = std::stoi(numberPart);
return regNum >= 0 && regNum <= 32;
}
bool Alu::isImmediate(const std::string &argument) {
if (argument.empty()) return false;
constexpr size_t start = 0;
/// Überprüfe, ob jedes Zeichen im Argument eine Nummer ista
for (size_t i = start; i < argument.size(); ++i) {
if (!std::isdigit(argument.at(i))) return false;
}
return true;
}